From 075856efbb92cc8f3e03fd3bbb3b6c0b873350ac Mon Sep 17 00:00:00 2001 From: yassa Date: Wed, 23 Aug 2023 09:46:56 +0300 Subject: [PATCH 01/30] Add rescript example (#442) * Add rescript build configurations * Create rescript page components * Add rescript deps --- .gitignore | 2 + Procfile.dev | 1 + app/controllers/pages_controller.rb | 2 + app/views/pages/rescript.html.erb | 1 + bsconfig.json | 30 +++ .../app/bundles/comments/constants/paths.js | 1 + .../comments/src/Actions/Actions.bs.mjs | 51 ++++ .../bundles/comments/src/Actions/Actions.res | 91 +++++++ .../bundles/comments/src/Actions/Types.bs.mjs | 2 + .../src/CommentForm/CommentForm.bs.mjs | 243 ++++++++++++++++++ .../src/CommentForm/CommentForm.module.scss | 11 + .../comments/src/CommentForm/CommentForm.res | 117 +++++++++ .../CommentForm/forms/HorizontalForm.bs.mjs | 79 ++++++ .../src/CommentForm/forms/InlineForm.bs.mjs | 66 +++++ .../src/CommentForm/forms/StackedFrom.bs.mjs | 65 +++++ .../CommentList/AlertError/AlertError.bs.mjs | 46 ++++ .../src/CommentList/Comment/Comment.bs.mjs | 39 +++ .../CommentList/Comment/Comment.module.scss | 11 + .../src/CommentList/Comment/Comment.res | 17 ++ .../src/CommentList/CommentList.bs.mjs | 76 ++++++ .../comments/src/CommentList/CommentList.res | 82 ++++++ .../bundles/comments/src/Header/Header.bs.mjs | 90 +++++++ .../bundles/comments/src/Header/Header.res | 51 ++++ .../bundles/comments/src/ReScriptShow.bs.mjs | 157 +++++++++++ .../bundles/comments/src/RescriptPage.bs.mjs | 109 ++++++++ .../comments/src/RescriptPage.module.scss | 19 ++ .../app/bundles/comments/src/RescriptPage.res | 46 ++++ .../comments/src/bindings/Axios.bs.mjs | 2 + .../comments/src/bindings/CSSAnimation.bs.mjs | 12 + .../comments/src/bindings/Marked.bs.mjs | 2 + .../comments/src/bindings/ReactOnRails.bs.mjs | 2 + client/app/bundles/comments/src/vars.scss | 10 + client/app/packs/client-bundle.js | 2 + client/app/packs/server-bundle.js | 2 + config/routes.rb | 1 + package.json | 8 + spec/rescript/rescript_spec.rb | 78 ++++++ yarn.lock | 25 ++ 38 files changed, 1649 insertions(+) create mode 100644 app/views/pages/rescript.html.erb create mode 100644 bsconfig.json create mode 100644 client/app/bundles/comments/src/Actions/Actions.bs.mjs create mode 100644 client/app/bundles/comments/src/Actions/Actions.res create mode 100644 client/app/bundles/comments/src/Actions/Types.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentForm/CommentForm.module.scss create mode 100644 client/app/bundles/comments/src/CommentForm/CommentForm.res create mode 100644 client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentList/Comment/Comment.module.scss create mode 100644 client/app/bundles/comments/src/CommentList/Comment/Comment.res create mode 100644 client/app/bundles/comments/src/CommentList/CommentList.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentList/CommentList.res create mode 100644 client/app/bundles/comments/src/Header/Header.bs.mjs create mode 100644 client/app/bundles/comments/src/Header/Header.res create mode 100644 client/app/bundles/comments/src/ReScriptShow.bs.mjs create mode 100644 client/app/bundles/comments/src/RescriptPage.bs.mjs create mode 100644 client/app/bundles/comments/src/RescriptPage.module.scss create mode 100644 client/app/bundles/comments/src/RescriptPage.res create mode 100644 client/app/bundles/comments/src/bindings/Axios.bs.mjs create mode 100644 client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs create mode 100644 client/app/bundles/comments/src/bindings/Marked.bs.mjs create mode 100644 client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs create mode 100644 client/app/bundles/comments/src/vars.scss create mode 100644 spec/rescript/rescript_spec.rb diff --git a/.gitignore b/.gitignore index 1743c0ba..9e31d6eb 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,5 @@ client/app/libs/i18n/default.js /yarn-error.log yarn-debug.log* .yarn-integrity + +lib/bs diff --git a/Procfile.dev b/Procfile.dev index 49aba946..20453bbe 100644 --- a/Procfile.dev +++ b/Procfile.dev @@ -1,5 +1,6 @@ # Procfile for development using HMR # You can run these commands in separate shells +rescript: yarn res:dev redis: redis-server rails: bundle exec rails s -p 3000 wp-client: HMR=true RAILS_ENV=development NODE_ENV=development bin/shakapacker-dev-server diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 2ebf76ed..c9f6543e 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -36,6 +36,8 @@ def no_router def simple; end + def rescript; end + private def set_comments diff --git a/app/views/pages/rescript.html.erb b/app/views/pages/rescript.html.erb new file mode 100644 index 00000000..c6630d13 --- /dev/null +++ b/app/views/pages/rescript.html.erb @@ -0,0 +1 @@ +<%= react_component "RescriptPage" %> diff --git a/bsconfig.json b/bsconfig.json new file mode 100644 index 00000000..fea05cca --- /dev/null +++ b/bsconfig.json @@ -0,0 +1,30 @@ +{ + "name": "react-webpack-rails-tutorial", + "sources": [ + { + "dir": "client/app/bundles/comments/src", + "subdirs": true + } + ], + "package-specs": [ + { + "module": "es6", + "in-source": true + } + ], + "bsc-flags": [ + "-bs-super-errors", + "-open JsonCombinators" + ], + "suffix": ".bs.mjs", + "bs-dependencies": [ + "@rescript/react", + "@rescript/core", + "@glennsl/rescript-fetch", + "@glennsl/rescript-json-combinators" + ], + "jsx": { + "version": 4, + "mode": "automatic" + } +} \ No newline at end of file diff --git a/client/app/bundles/comments/constants/paths.js b/client/app/bundles/comments/constants/paths.js index de56ab7a..11194de8 100644 --- a/client/app/bundles/comments/constants/paths.js +++ b/client/app/bundles/comments/constants/paths.js @@ -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'; diff --git a/client/app/bundles/comments/src/Actions/Actions.bs.mjs b/client/app/bundles/comments/src/Actions/Actions.bs.mjs new file mode 100644 index 00000000..a1723d69 --- /dev/null +++ b/client/app/bundles/comments/src/Actions/Actions.bs.mjs @@ -0,0 +1,51 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Curry from "rescript/lib/es6/curry.js"; +import * as Axios from "axios"; +import * as Js_exn from "rescript/lib/es6/js_exn.js"; +import ReactOnRails from "react-on-rails"; +import * as Json$JsonCombinators from "@glennsl/rescript-json-combinators/src/Json.bs.mjs"; +import * as Json_Decode$JsonCombinators from "@glennsl/rescript-json-combinators/src/Json_Decode.bs.mjs"; + +async function fetchComments(param) { + var response = await fetch("comments.json"); + var jsonRes = await response.json(); + var jsonComment = Json_Decode$JsonCombinators.object(function (field) { + return { + author: field.required("author", Json_Decode$JsonCombinators.string), + text: field.required("text", Json_Decode$JsonCombinators.string), + id: field.required("id", Json_Decode$JsonCombinators.$$int) + }; + }); + var jsonComments = Json_Decode$JsonCombinators.object(function (field) { + return { + comments: field.required("comments", Json_Decode$JsonCombinators.array(jsonComment)) + }; + }); + var decodedRes = Json$JsonCombinators.decode(jsonRes, jsonComments); + if (decodedRes.TAG === /* Ok */0) { + return decodedRes._0.comments; + } else { + return Js_exn.raiseError(decodedRes._0); + } +} + +async function storeComment(author, text) { + await Axios.post("comments.json", { + author: author, + text: text + }, { + responseType: "json", + headers: Curry._1(ReactOnRails.default.authenticityHeaders, undefined) + }); +} + +var Api = { + fetchComments: fetchComments, + storeComment: storeComment +}; + +export { + Api , +} +/* axios Not a pure module */ diff --git a/client/app/bundles/comments/src/Actions/Actions.res b/client/app/bundles/comments/src/Actions/Actions.res new file mode 100644 index 00000000..d63b8c02 --- /dev/null +++ b/client/app/bundles/comments/src/Actions/Actions.res @@ -0,0 +1,91 @@ +// ReactOnRails binding +type rorDefault = { + authenticityHeaders: unit => {.} +} +type rorModule = { + default: rorDefault +} +@module("react-on-rails") external ror: rorModule = "default"; + +type storeCommentData = { + author: string, + text: string +} + +// axios binding +type reqOptions = { + responseType: string, + headers: {.} +} +@module("axios") external post: (string, storeCommentData, reqOptions) => promise = "post"; + +module Api = { + type comment = { + author: string, + text: string, + id: int + }; + + type comments = array + + type commentsRes = { + comments: comments + } + + let fetchComments = async (): comments => { + 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) => decodedRes.comments + | Error(err) => Js.Exn.raiseError(err) + } + } + + let storeComment = async (author: string, text: string) => { + let _ = await post( + "comments.json", + { + author: author, + text: text + }, + { + responseType: "json", + headers:ror.default.authenticityHeaders() + } + ) + + + // setIsSaving(_ => true) + // try { + // let _ = await post( + // "comments.json", + // { + // author: author, + // text: text + // }, + // { + // responseType: "json", + // headers:ror.default.authenticityHeaders() + // } + // ) + // setIsSaving(_ => false) + // let comments = await fetchComments() + // setComments(_ => comments) + // } catch { + // | _ => setError(_ => true) + // } + } +} diff --git a/client/app/bundles/comments/src/Actions/Types.bs.mjs b/client/app/bundles/comments/src/Actions/Types.bs.mjs new file mode 100644 index 00000000..d856702b --- /dev/null +++ b/client/app/bundles/comments/src/Actions/Types.bs.mjs @@ -0,0 +1,2 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs new file mode 100644 index 00000000..148e198a --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs @@ -0,0 +1,243 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Curry from "rescript/lib/es6/curry.js"; +import * as React from "react"; +import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; +import * as JsxRuntime from "react/jsx-runtime"; +import CommentFormModuleScss from "./CommentForm.module.scss"; + +var css = CommentFormModuleScss; + +function CommentForm(props) { + var storeComment = props.storeComment; + var match = React.useState(function () { + return ""; + }); + var setAuthor = match[1]; + var author = match[0]; + var match$1 = React.useState(function () { + return ""; + }); + var setText = match$1[1]; + var text = match$1[0]; + var match$2 = React.useState(function () { + return "Horizontal Form"; + }); + var setCurrFormType = match$2[1]; + var currformType = match$2[0]; + var handleAuthorChange = function (e) { + Curry._1(setAuthor, e.currentTarget.value); + }; + var handleTextChange = function (e) { + Curry._1(setText, e.currentTarget.value); + }; + var handleSubmit = function (e) { + e.preventDefault(); + Curry._2(storeComment, author, text); + }; + var horizontalForm = JsxRuntime.jsxs("form", { + children: [ + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("label", { + children: "Name", + className: "form-label pull-right" + }), + className: "col-sm-2" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "form-control", + placeholder: "Your Name", + type: "text", + value: author, + onChange: handleAuthorChange + }), + className: "col-sm-10" + }) + ], + className: "form-group" + }), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("label", { + children: "Text", + className: "form-label pull-right" + }), + className: "col-sm-2" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "form-control", + placeholder: "Say something using markdown...", + type: "text", + value: text, + onChange: handleTextChange + }), + className: "col-sm-10" + }) + ], + className: "form-group" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "btn btn-primary", + type: "submit" + }), + className: "col-sm-10 col-sm-offset-2" + }), + className: "form-group" + }) + ], + className: "form-horizontal", + disabled: props.isSaving, + onSubmit: handleSubmit + }); + var inlineForm = JsxRuntime.jsxs("form", { + children: [ + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Name", + className: "form-label mr-15" + }), + JsxRuntime.jsx("input", { + className: "form-control", + placeholder: "Your Name", + type: "text", + value: author + }) + ], + className: "form-group" + }), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Text", + className: "form-label mr-15" + }), + JsxRuntime.jsx("input", { + className: "form-control w-50", + placeholder: "Say something using markdown...", + type: "text", + value: text, + onChange: handleTextChange + }) + ], + className: "form-group ml-15 mr-15" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "btn btn-primary", + type: "submit", + onSubmit: handleSubmit + }), + className: "form-group" + }) + ], + className: "form-inline", + onChange: handleAuthorChange + }); + var stackedForm = JsxRuntime.jsxs("form", { + children: [ + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Name", + className: "form-label" + }), + JsxRuntime.jsx("input", { + className: "form-control", + placeholder: "Your Name", + type: "text", + value: author, + onChange: handleAuthorChange + }) + ], + className: "form-group" + }), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Name", + className: "form-label" + }), + JsxRuntime.jsx("input", { + className: "form-control", + placeholder: "Say something using markdown...", + type: "text", + value: text, + onChange: handleTextChange + }) + ], + className: "form-group" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "btn btn-primary", + type: "submit", + onSubmit: handleSubmit + }), + className: "form-group" + }) + ], + onChange: handleAuthorChange + }); + var formTypes = [ + "Horizontal Form", + "Stacked Form", + "Inline Form" + ]; + var formsNavbarComponent = Belt_Array.map(formTypes, (function (formType) { + return JsxRuntime.jsx("li", { + children: JsxRuntime.jsx("a", { + children: formType, + className: css.anchorButton + }), + className: "nav-item " + ( + currformType === formType ? "active" : "" + ), + role: "presentation", + onClick: (function (param) { + Curry._1(setCurrFormType, (function (param) { + return formType; + })); + }) + }, "form_" + formType); + })); + var form; + switch (currformType) { + case "Horizontal Form" : + form = horizontalForm; + break; + case "Inline Form" : + form = inlineForm; + break; + case "Stacked Form" : + form = stackedForm; + break; + default: + form = horizontalForm; + } + return JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("ul", { + children: formsNavbarComponent, + className: "nav nav-pills" + }), + JsxRuntime.jsx("hr", {}), + form + ] + }); +} + +var make = CommentForm; + +export { + css , + make , +} +/* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.module.scss b/client/app/bundles/comments/src/CommentForm/CommentForm.module.scss new file mode 100644 index 00000000..e68605ed --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.module.scss @@ -0,0 +1,11 @@ +.anchorButton { + background-color: transparent; + border: 0; + color: #337AB7; + cursor: pointer; + padding: 0; +} + +.anchorButton:hover { + text-decoration: underline; +} diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.res b/client/app/bundles/comments/src/CommentForm/CommentForm.res new file mode 100644 index 00000000..e4f61853 --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.res @@ -0,0 +1,117 @@ +@module("./CommentForm.module.scss") external css: {..} = "default" +type storeCommentAction = (string, string) => unit; + +@react.component +let make = (~storeComment: storeCommentAction, ~isSaving: bool) => { + let (author, setAuthor) = React.useState(_ => "") + let (text, setText) = React.useState(_ => "") + let (currformType, setCurrFormType) = React.useState(_ => "Horizontal Form") + + let handleAuthorChange = (e) => { + setAuthor(ReactEvent.Form.currentTarget(e)["value"]) + () + } + + let handleTextChange = (e) => { + setText(ReactEvent.Form.currentTarget(e)["value"]) + () + } + + let handleSubmit = (e) => { + ReactEvent.Form.preventDefault(e) + storeComment(author, text) + } + + let horizontalForm = ( +
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ ) + + let inlineForm = ( +
+
+ + +
+
+ + +
+
+ +
+
+ ) + + let stackedForm = ( +
+
+ + +
+
+ + +
+
+ +
+
+ ) + + let formTypes: array = [ + "Horizontal Form", + "Stacked Form", + "Inline Form" + ] + + let handleClick = (formType: string): unit => { + setCurrFormType(_ => formType) + (); + } + + let formsNavbarComponent = ( + Belt.Array.map(formTypes, formType => +
  • handleClick(formType)) role="presentation"> + {React.string(formType)} +
  • + ) + ) + + let form = switch currformType { + | "Horizontal Form" => horizontalForm + | "Stacked Form" => stackedForm + | "Inline Form" => inlineForm + | _ => horizontalForm + } + +
    +
      + { React.array(formsNavbarComponent) } +
    +
    + form +
    + +} \ No newline at end of file diff --git a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs new file mode 100644 index 00000000..c013deff --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs @@ -0,0 +1,79 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as JsxRuntime from "react/jsx-runtime"; + +function HorizontalForm(props) { + return JsxRuntime.jsxs("form", { + children: [ + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("label", { + children: "Name", + className: "form-label pull-right" + }), + className: "col-sm-2" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "form-control", + id: "comment_author", + name: "comment_author", + placeholder: "Your Name", + type: "text", + value: props.author, + onChange: props.handleAuthorChange + }), + className: "col-sm-10" + }) + ], + className: "form-group" + }), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("label", { + children: "Text", + className: "form-label pull-right" + }), + className: "col-sm-2" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "form-control", + id: "comment_text", + name: "comment_text", + placeholder: "Say something using markdown...", + type: "text", + value: props.text, + onChange: props.handleTextChange + }), + className: "col-sm-10" + }) + ], + className: "form-group" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "btn btn-primary", + type: "submit", + value: "Post" + }), + className: "col-sm-10 col-sm-offset-2" + }), + className: "form-group" + }) + ], + className: "form-horizontal", + disabled: props.isSaving === /* BusySaving */1, + onSubmit: props.handleSubmit + }); +} + +var make = HorizontalForm; + +export { + make , +} +/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs new file mode 100644 index 00000000..6adaad89 --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs @@ -0,0 +1,66 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as JsxRuntime from "react/jsx-runtime"; + +function InlineForm(props) { + var handleSubmit = props.handleSubmit; + return JsxRuntime.jsxs("form", { + children: [ + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Name", + className: "form-label mr-15" + }), + JsxRuntime.jsx("input", { + className: "form-control", + id: "comment_author", + name: "comment_author", + placeholder: "Your Name", + type: "text", + value: props.author, + onChange: props.handleAuthorChange + }) + ], + className: "form-group" + }), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Text", + className: "form-label mr-15" + }), + JsxRuntime.jsx("input", { + className: "form-control w-50", + id: "comment_text", + name: "comment_text", + placeholder: "Say something using markdown...", + type: "text", + value: props.text, + onChange: props.handleTextChange + }) + ], + className: "form-group ml-15 mr-15" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "btn btn-primary", + type: "submit", + value: "Post", + onSubmit: handleSubmit + }), + className: "form-group" + }) + ], + className: "form-inline", + disabled: props.isSaving === /* BusySaving */1, + onSubmit: handleSubmit + }); +} + +var make = InlineForm; + +export { + make , +} +/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs new file mode 100644 index 00000000..07c196cc --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs @@ -0,0 +1,65 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as JsxRuntime from "react/jsx-runtime"; + +function StackedFrom(props) { + var handleSubmit = props.handleSubmit; + return JsxRuntime.jsxs("form", { + children: [ + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Name", + className: "form-label" + }), + JsxRuntime.jsx("input", { + className: "form-control", + id: "comment_author", + name: "comment_author", + placeholder: "Your Name", + type: "text", + value: props.author, + onChange: props.handleAuthorChange + }) + ], + className: "form-group" + }), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("label", { + children: "Name", + className: "form-label" + }), + JsxRuntime.jsx("input", { + className: "form-control", + id: "comment_text", + name: "comment_text", + placeholder: "Say something using markdown...", + type: "text", + value: props.text, + onChange: props.handleTextChange + }) + ], + className: "form-group" + }), + JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("input", { + className: "btn btn-primary", + type: "submit", + value: "Post", + onSubmit: handleSubmit + }), + className: "form-group" + }) + ], + disabled: props.isSaving === /* BusySaving */1, + onSubmit: handleSubmit + }); +} + +var make = StackedFrom; + +export { + make , +} +/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs new file mode 100644 index 00000000..cc1ed0d7 --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs @@ -0,0 +1,46 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as React from "react"; +import * as JsxRuntime from "react/jsx-runtime"; +import * as ReactTransitionGroup from "react-transition-group"; + +function AlertError(props) { + var cssTransitionGroupClassNames = props.cssTransitionGroupClassNames; + var nodeRef = React.useRef(null); + switch (props.error) { + case /* NoError */0 : + return null; + case /* FailedToSaveComment */1 : + return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { + children: JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("strong", { + children: "Your comment was not saved!" + }), + className: "alert alert-danger" + }), + timeout: 500, + nodeRef: nodeRef, + classNames: cssTransitionGroupClassNames + }, "commentFetchError"); + case /* FailedToFetchComments */2 : + return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { + children: JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("strong", { + children: "Can't fetch the comments!" + }), + className: "alert alert-danger" + }), + timeout: 500, + nodeRef: nodeRef, + classNames: cssTransitionGroupClassNames + }, "commentFetchError"); + + } +} + +var make = AlertError; + +export { + make , +} +/* react Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs b/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs new file mode 100644 index 00000000..0ac41408 --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs @@ -0,0 +1,39 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Marked from "marked"; +import * as Caml_option from "rescript/lib/es6/caml_option.js"; +import * as JsxRuntime from "react/jsx-runtime"; +import CommentModuleScss from "./Comment.module.scss"; + +var css = CommentModuleScss; + +function $$Comment(props) { + var comment = props.comment; + var rawMarkup = Marked.marked(comment.text, { + gfm: true + }); + var innerHTML = { + __html: rawMarkup + }; + return JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("h2", { + children: comment.author, + className: css.commentAuthor + }), + JsxRuntime.jsx("span", { + dangerouslySetInnerHTML: Caml_option.some(innerHTML) + }) + ], + ref: Caml_option.some(props.nodeRef), + className: css.comment + }); +} + +var make = $$Comment; + +export { + css , + make , +} +/* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.module.scss b/client/app/bundles/comments/src/CommentList/Comment/Comment.module.scss new file mode 100644 index 00000000..9d156501 --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.module.scss @@ -0,0 +1,11 @@ +.comment { + + .commentAuthor { + color: $comment-author-color; // <--- Loaded via sass-resources-loader + } + + p { + color: $comment-text-color; // <-- This one also + } + +} diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.res b/client/app/bundles/comments/src/CommentList/Comment/Comment.res new file mode 100644 index 00000000..2b7e8250 --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.res @@ -0,0 +1,17 @@ +@module("./Comment.module.scss") external css: {..} = "default" + +type markedOptions = { + gfm: bool +} +@module("marked") external marked: (string, markedOptions) => string = "marked"; + +@react.component +let make = (~comment: Actions.Api.comment, ~nodeRef) => { + let rawMarkup = marked(comment.text, {gfm: true}) + let innerHTML = { "__html": rawMarkup } + +
    +

    {comment.author->React.string}

    + +
    +} \ No newline at end of file diff --git a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs new file mode 100644 index 00000000..f3be48b5 --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs @@ -0,0 +1,76 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as React from "react"; +import * as $$Comment from "./Comment/Comment.bs.mjs"; +import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; +import * as JsxRuntime from "react/jsx-runtime"; +import * as ReactTransitionGroup from "react-transition-group"; +import RescriptPageModuleScss from "../RescriptPage.module.scss"; + +var css = RescriptPageModuleScss; + +var TransitionGroup = {}; + +var CSSTransition = {}; + +function CommentList(props) { + var cssTransitionGroupClassNames_enter = css.elementEnter; + var cssTransitionGroupClassNames_enterActive = css.elementEnterActive; + var cssTransitionGroupClassNames_exit = css.elementLeave; + var cssTransitionGroupClassNames_exitActive = css.elementLeaveActive; + var cssTransitionGroupClassNames = { + enter: cssTransitionGroupClassNames_enter, + enterActive: cssTransitionGroupClassNames_enterActive, + exit: cssTransitionGroupClassNames_exit, + exitActive: cssTransitionGroupClassNames_exitActive + }; + var errorMsg; + if (props.error) { + var nodeRef = React.useRef(null); + errorMsg = JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { + children: JsxRuntime.jsx("div", { + children: JsxRuntime.jsx("strong", { + children: "Your comment was not saved!" + }), + className: "alert alert-danger" + }), + timeout: 500, + nodeRef: nodeRef, + classNames: cssTransitionGroupClassNames + }, "commentFetchError"); + } else { + errorMsg = JsxRuntime.jsx(JsxRuntime.Fragment, {}); + } + var commentsElements = Belt_Array.map(props.comments, (function (comment) { + var nodeRef = React.useRef(null); + return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { + children: JsxRuntime.jsx($$Comment.make, { + comment: comment, + nodeRef: nodeRef + }), + timeout: 500, + nodeRef: nodeRef, + classNames: cssTransitionGroupClassNames + }, "component_" + String(comment.id)); + })); + return JsxRuntime.jsxs("div", { + children: [ + errorMsg, + JsxRuntime.jsx(ReactTransitionGroup.TransitionGroup, { + children: commentsElements, + className: "commentList", + component: "div" + }) + ] + }); +} + +var make = CommentList; + +export { + css , + TransitionGroup , + CSSTransition , + make , +} +/* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/CommentList.res b/client/app/bundles/comments/src/CommentList/CommentList.res new file mode 100644 index 00000000..36840873 --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/CommentList.res @@ -0,0 +1,82 @@ +@module("../RescriptPage.module.scss") external css: {..} = "default" + +module TransitionGroup = { + @react.component @module("react-transition-group") + external make: ( + ~children: React.element, + ~className: string, + ~component: string + ) => React.element = "TransitionGroup" +} + +type cssTransitionGroupClassNamesT = { + enter: string, + enterActive: string, + exit: string, + exitActive: string +} + +module CSSTransition = { + @react.component @module("react-transition-group") + external make: ( + ~children: React.element, + ~key: string, + ~timeout: int, + ~nodeRef: React.ref>, + ~classNames: cssTransitionGroupClassNamesT + ) => React.element = "CSSTransition" +} + +@react.component +let make = (~comments: Actions.Api.comments, ~error: bool) => { + let cssTransitionGroupClassNames = { + enter: css["elementEnter"], + enterActive: css["elementEnterActive"], + exit: css["elementLeave"], + exitActive: css["elementLeaveActive"] + } + + let errorMsg = switch error { + | true => (() => { + let nodeRef = React.useRef(Js.Nullable.null) + + // The 500 must correspond to the 0.5s in: + // ../RescriptPage.module.scss:8 + +
    + {React.string("Your comment was not saved!")} +
    +
    + })() + | false => <> + } + + let commentsElements = Belt.Array.map( + comments, + comment => { + let nodeRef = React.useRef(Js.Nullable.null) + + // The 500 must correspond to the 0.5s in: + // ../RescriptPage.module.scss:8 + + + + }); + +
    + errorMsg + + {React.array(commentsElements)} + +
    +} diff --git a/client/app/bundles/comments/src/Header/Header.bs.mjs b/client/app/bundles/comments/src/Header/Header.bs.mjs new file mode 100644 index 00000000..7b837973 --- /dev/null +++ b/client/app/bundles/comments/src/Header/Header.bs.mjs @@ -0,0 +1,90 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as JsxRuntime from "react/jsx-runtime"; + +function Header(props) { + return JsxRuntime.jsxs(JsxRuntime.Fragment, { + children: [ + JsxRuntime.jsxs("ul", { + children: [ + JsxRuntime.jsxs("li", { + children: [ + JsxRuntime.jsx("a", { + children: "Can ShakaCode Help You? ", + href: "https://blog.shakacode.com/can-shakacode-help-you-4a5b1e5a8a63#.jex6tg9w9" + }), + "We're actively seeking new projects with React, React-Native, or Ruby on Rails." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "See the ", + JsxRuntime.jsx("a", { + children: "github.com/shakacode/react-webpack-rails-tutorial/README.md ", + href: "https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/README.md" + }), + "for details of how this example site was built." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "Read ", + JsxRuntime.jsx("a", { + children: "Documentation for React on Rails", + href: "https://shakacode.gitbooks.io/react-on-rails/content/" + }), + JsxRuntime.jsx("a", { + children: "The React on Rails Doctrine.", + href: "https://www.shakacode.com/blog/the-react-on-rails-doctrine" + }) + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "See our React Native Client: ", + JsxRuntime.jsx("a", { + children: "shakacode/react-native-tutorial", + href: "https://github.com/shakacode/react-native-tutorial" + }), + "." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "Watch the ", + JsxRuntime.jsx("a", { + children: "React On Rails Tutorial Series", + href: "https://www.youtube.com/playlist?list=PL5VAKH-U1M6dj84BApfUtvBjvF-0-JfEU" + }), + "." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + JsxRuntime.jsx("a", { + children: "ShakaCode", + href: "http://www.shakacode.com" + }), + " is doing support for React on Rails, including a private Slack channel, source code reviews, and pair programming sessions. ", + JsxRuntime.jsx("b", { + children: JsxRuntime.jsx("a", { + children: "Click here", + href: "http://www.shakacode.com/work/index.html" + }) + }), + " for more information." + ] + }) + ] + }), + JsxRuntime.jsx("hr", {}) + ] + }); +} + +var make = Header; + +export { + make , +} +/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/Header/Header.res b/client/app/bundles/comments/src/Header/Header.res new file mode 100644 index 00000000..4260a463 --- /dev/null +++ b/client/app/bundles/comments/src/Header/Header.res @@ -0,0 +1,51 @@ +@react.component +let make = () => { + <> + +
    + +} \ No newline at end of file diff --git a/client/app/bundles/comments/src/ReScriptShow.bs.mjs b/client/app/bundles/comments/src/ReScriptShow.bs.mjs new file mode 100644 index 00000000..12722aed --- /dev/null +++ b/client/app/bundles/comments/src/ReScriptShow.bs.mjs @@ -0,0 +1,157 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Curry from "rescript/lib/es6/curry.js"; +import * as React from "react"; +import * as Header from "./Header/Header.bs.mjs"; +import * as Actions from "./Actions/Actions.bs.mjs"; +import * as CommentForm from "./CommentForm/CommentForm.bs.mjs"; +import * as CommentList from "./CommentList/CommentList.bs.mjs"; +import * as JsxRuntime from "react/jsx-runtime"; + +function reducer(state, action) { + switch (action.TAG | 0) { + case /* SetComments */0 : + return { + comments: action._0, + error: state.error, + isSaving: state.isSaving + }; + case /* SetError */1 : + return { + comments: state.comments, + error: action._0, + isSaving: state.isSaving + }; + case /* SetIsSaving */2 : + return { + comments: state.comments, + error: state.error, + isSaving: action._0 + }; + + } +} + +function ReScriptShow$default(props) { + var match = React.useReducer(reducer, { + comments: [], + error: /* NoError */0, + isSaving: /* Free */0 + }); + var dispatch = match[1]; + var state = match[0]; + var storeComment = function (author, text) { + Curry._1(dispatch, { + TAG: /* SetError */1, + _0: /* NoError */0 + }); + Curry._1(dispatch, { + TAG: /* SetIsSaving */2, + _0: /* BusySaving */1 + }); + var saveAndFetchComments = async function (param) { + try { + await Actions.Create.storeComment({ + author: author, + text: text + }); + Curry._1(dispatch, { + TAG: /* SetIsSaving */2, + _0: /* Free */0 + }); + var comments = await Actions.Fetch.fetchComments(undefined); + if (comments.TAG === /* Ok */0) { + return Curry._1(dispatch, { + TAG: /* SetComments */0, + _0: comments._0 + }); + } else { + return Curry._1(dispatch, { + TAG: /* SetError */1, + _0: comments._0 + }); + } + } + catch (exn){ + return Curry._1(dispatch, { + TAG: /* SetError */1, + _0: /* FailedToSaveComment */1 + }); + } + }; + saveAndFetchComments(undefined); + }; + React.useEffect((function () { + var fetchData = async function (param) { + var comments = await Actions.Fetch.fetchComments(undefined); + if (comments.TAG === /* Ok */0) { + return Curry._1(dispatch, { + TAG: /* SetComments */0, + _0: comments._0 + }); + } else { + return Curry._1(dispatch, { + TAG: /* SetError */1, + _0: comments._0 + }); + } + }; + fetchData(undefined); + }), []); + return JsxRuntime.jsxs(JsxRuntime.Fragment, { + children: [ + JsxRuntime.jsxs("h2", { + children: [ + "Rescript + Rails Backend (with ", + JsxRuntime.jsx("a", { + children: "react_on_rails gem", + href: "https://github.com/shakacode/react_on_rails" + }), + ")" + ] + }), + JsxRuntime.jsx(Header.make, {}), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("h2", { + children: "Comments" + }), + JsxRuntime.jsxs("ul", { + children: [ + JsxRuntime.jsx("li", { + children: "Text supports Github Flavored Markdown." + }), + JsxRuntime.jsx("li", { + children: "Comments older than 24 hours are deleted." + }), + JsxRuntime.jsx("li", { + children: "Name is preserved. Text is reset, between submits" + }), + JsxRuntime.jsx("li", { + children: "To see Action Cable instantly update two browsers, open two browsers and submit a comment!" + }) + ] + }), + JsxRuntime.jsx(CommentForm.make, { + storeComment: storeComment, + isSaving: state.isSaving + }), + JsxRuntime.jsx(CommentList.make, { + comments: state.comments, + error: state.error + }) + ], + className: "container" + }) + ] + }); +} + +var $$default = ReScriptShow$default; + +export { + reducer , + $$default , + $$default as default, +} +/* react Not a pure module */ diff --git a/client/app/bundles/comments/src/RescriptPage.bs.mjs b/client/app/bundles/comments/src/RescriptPage.bs.mjs new file mode 100644 index 00000000..6181dae8 --- /dev/null +++ b/client/app/bundles/comments/src/RescriptPage.bs.mjs @@ -0,0 +1,109 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Curry from "rescript/lib/es6/curry.js"; +import * as React from "react"; +import * as Header from "./Header/Header.bs.mjs"; +import * as Actions from "./Actions/Actions.bs.mjs"; +import * as CommentForm from "./CommentForm/CommentForm.bs.mjs"; +import * as CommentList from "./CommentList/CommentList.bs.mjs"; +import * as JsxRuntime from "react/jsx-runtime"; + +function RescriptPage(props) { + var match = React.useState(function () { + return []; + }); + var setComments = match[1]; + var match$1 = React.useState(function () { + return false; + }); + var setError = match$1[1]; + var match$2 = React.useState(function () { + return false; + }); + var setIsSaving = match$2[1]; + var storeComment = function (author, text) { + Curry._1(setIsSaving, (function (param) { + return true; + })); + ((async function (param) { + try { + Actions.Api.storeComment(author, text); + Curry._1(setIsSaving, (function (param) { + return false; + })); + var comments = await Actions.Api.fetchComments(undefined); + return Curry._1(setComments, (function (param) { + return comments; + })); + } + catch (exn){ + return Curry._1(setError, (function (param) { + return true; + })); + } + })(undefined)); + }; + React.useEffect((function () { + var fetchData = async function (param) { + var comments = await Actions.Api.fetchComments(undefined); + return Curry._1(setComments, (function (param) { + return comments; + })); + }; + fetchData(undefined); + }), []); + return JsxRuntime.jsxs(JsxRuntime.Fragment, { + children: [ + JsxRuntime.jsxs("h2", { + children: [ + "Rescript + Rails Backend (with ", + JsxRuntime.jsx("a", { + children: "react_on_rails gem", + href: "https://github.com/shakacode/react_on_rails" + }), + ")" + ] + }), + JsxRuntime.jsx(Header.make, {}), + JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("h2", { + children: "Comments" + }), + JsxRuntime.jsxs("ul", { + children: [ + JsxRuntime.jsx("li", { + children: "Text supports Github Flavored Markdown." + }), + JsxRuntime.jsx("li", { + children: "Comments older than 24 hours are deleted." + }), + JsxRuntime.jsx("li", { + children: "Name is preserved. Text is reset, between submits" + }), + JsxRuntime.jsx("li", { + children: "To see Action Cable instantly update two browsers, open two browsers and submit a comment!" + }) + ] + }), + JsxRuntime.jsx(CommentForm.make, { + storeComment: storeComment, + isSaving: match$2[0] + }), + JsxRuntime.jsx(CommentList.make, { + comments: match[0], + error: match$1[0] + }) + ], + className: "container" + }) + ] + }); +} + +var make = RescriptPage; + +export { + make , +} +/* react Not a pure module */ diff --git a/client/app/bundles/comments/src/RescriptPage.module.scss b/client/app/bundles/comments/src/RescriptPage.module.scss new file mode 100644 index 00000000..a54a6329 --- /dev/null +++ b/client/app/bundles/comments/src/RescriptPage.module.scss @@ -0,0 +1,19 @@ +// The 0.5s must correspond to the 500s in: +// ./CommentList/CommentList.res:47 +.elementEnter { + opacity: 0.01; + + &.elementEnterActive { + opacity: 1; + transition: opacity 0.5s ease-in; + } +} + +.elementLeave { + opacity: 1; + + &.elementLeaveActive { + opacity: 0.01; + transition: opacity 0.5s ease-in; + } +} diff --git a/client/app/bundles/comments/src/RescriptPage.res b/client/app/bundles/comments/src/RescriptPage.res new file mode 100644 index 00000000..7bbfb072 --- /dev/null +++ b/client/app/bundles/comments/src/RescriptPage.res @@ -0,0 +1,46 @@ +@react.component +let make = () => { + let (comments, setComments) = React.useState(_ => ([] : Actions.Api.comments)); + let (error, setError) = React.useState(_ => false) + let (isSaving, setIsSaving) = React.useState(_ => false) + + let storeComment = (author, text) => { + setIsSaving(_ => true) + let _ = (async() => { + try { + let _ = Actions.Api.storeComment(author, text) + setIsSaving(_ => false) + let comments = await Actions.Api.fetchComments() + setComments(_ => comments) + } catch { + | _ => setError(_ => true) + } + })() + } + + React.useEffect1((_) => { + let fetchData = async () => { + let comments = await Actions.Api.fetchComments(); + setComments(_ => comments); + }; + + let _ = fetchData(); + None + }, []) + + <> +

    {"Rescript + Rails Backend (with "->React.string}{"react_on_rails gem"->React.string}{")"->React.string}

    +
    +
    +

    {"Comments"->React.string}

    +
      +
    • {"Text supports Github Flavored Markdown."->React.string}
    • +
    • {"Comments older than 24 hours are deleted."->React.string}
    • +
    • {"Name is preserved. Text is reset, between submits"->React.string}
    • +
    • {"To see Action Cable instantly update two browsers, open two browsers and submit a comment!"->React.string}
    • +
    + + +
    + +} diff --git a/client/app/bundles/comments/src/bindings/Axios.bs.mjs b/client/app/bundles/comments/src/bindings/Axios.bs.mjs new file mode 100644 index 00000000..d856702b --- /dev/null +++ b/client/app/bundles/comments/src/bindings/Axios.bs.mjs @@ -0,0 +1,2 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs b/client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs new file mode 100644 index 00000000..455b477e --- /dev/null +++ b/client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs @@ -0,0 +1,12 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + + +var TransitionGroup = {}; + +var CSSTransition = {}; + +export { + TransitionGroup , + CSSTransition , +} +/* No side effect */ diff --git a/client/app/bundles/comments/src/bindings/Marked.bs.mjs b/client/app/bundles/comments/src/bindings/Marked.bs.mjs new file mode 100644 index 00000000..d856702b --- /dev/null +++ b/client/app/bundles/comments/src/bindings/Marked.bs.mjs @@ -0,0 +1,2 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs b/client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs new file mode 100644 index 00000000..d856702b --- /dev/null +++ b/client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs @@ -0,0 +1,2 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE +/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/vars.scss b/client/app/bundles/comments/src/vars.scss new file mode 100644 index 00000000..38cb5d9d --- /dev/null +++ b/client/app/bundles/comments/src/vars.scss @@ -0,0 +1,10 @@ +// Defining application SASS variables in stand-alone file, +// so we can use them in bootstrap-loader and CSS Modules via sass-resources-loader +$body-bg: #EFF8FB; // background w/ character +$navbar-default-bg: #FFFFE0; // fancy yellow navbar +$font-size-base: 15px; // make it bigger! +$font-family-sans-serif: 'OpenSans-Light'; // apply custom font + +// It will be used in SASS components imported as CSS Modules +$comment-author-color: blue; +$comment-text-color: purple; \ No newline at end of file diff --git a/client/app/packs/client-bundle.js b/client/app/packs/client-bundle.js index 5365a0cc..2a1d6c9e 100644 --- a/client/app/packs/client-bundle.js +++ b/client/app/packs/client-bundle.js @@ -10,6 +10,7 @@ import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import Footer from '../bundles/comments/components/Footer/Footer'; +import { make as RescriptPage } from '../bundles/comments/src/RescriptPage.bs.mjs'; import '../assets/styles/application'; @@ -25,6 +26,7 @@ ReactOnRails.register({ NavigationBarApp, SimpleCommentScreen, Footer, + RescriptPage, }); ReactOnRails.registerStore({ diff --git a/client/app/packs/server-bundle.js b/client/app/packs/server-bundle.js index 4cec29f5..2679927f 100644 --- a/client/app/packs/server-bundle.js +++ b/client/app/packs/server-bundle.js @@ -8,6 +8,7 @@ import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import Footer from '../bundles/comments/components/Footer/Footer'; +import { make as RescriptPage } from '../bundles/comments/src/RescriptPage.bs.mjs'; ReactOnRails.register({ App, @@ -15,6 +16,7 @@ ReactOnRails.register({ NavigationBarApp, SimpleCommentScreen, Footer, + RescriptPage, }); ReactOnRails.registerStore({ diff --git a/config/routes.rb b/config/routes.rb index ab6d4132..1d8c7b7a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,7 @@ root "pages#index" get "simple", to: "pages#simple" + get "rescript", to: "pages#rescript" get "no-router", to: "pages#no_router" # React Router needs a wildcard diff --git a/package.json b/package.json index b1f5a166..ac7e58af 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,9 @@ }, "homepage": "https://github.com/shakacode/react-webpack-rails-tutorial", "scripts": { + "res:clean": "rescript clean", + "res:dev": "yarn res:clean && rescript build -w", + "res:build": "yarn res:clean && rescript build", "lint:eslint": "yarn eslint client --ext \".js,.jsx,.ts\"", "lint:prettier": "yarn prettier \"**/*.@(js|jsx)\" --list-different", "lint": " yarn lint:eslint --fix && yarn lint:prettier --w", @@ -33,10 +36,14 @@ "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", "@babel/runtime": "^7.17.9", + "@glennsl/rescript-fetch": "^0.2.0", + "@glennsl/rescript-json-combinators": "^1.2.1", "@hotwired/stimulus": "^3.2.1", "@hotwired/stimulus-webpack-helpers": "^1.0.1", "@hotwired/turbo-rails": "^7.3.0", "@rails/actioncable": "7.0.5", + "@rescript/core": "^0.5.0", + "@rescript/react": "^0.11.0", "autoprefixer": "^10.4.14", "axios": "^0.21.1", "babel-loader": "^9.1.2", @@ -79,6 +86,7 @@ "react-transition-group": "4.4.5", "redux": "^4.2.1", "redux-thunk": "^2.2.0", + "rescript": "^10.1.4", "resolve-url-loader": "^2.2.0", "sanitize-html": "^2.11.0", "sass": "^1.58.3", diff --git a/spec/rescript/rescript_spec.rb b/spec/rescript/rescript_spec.rb new file mode 100644 index 00000000..e5dc5f4c --- /dev/null +++ b/spec/rescript/rescript_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require "rails_helper" + +describe "with Rescript" do + describe "tabs change on click" do + before do + visit "/rescript" + end + + it "shows horizontal tab on visit" do + page.has_css?("form-horizontal") + end + + it "stops showing horizontal tab when other tab is clicked" do + click_link("Inline Form") + page.has_no_css?("form-horizontal") + end + + it "shows inline form when Inline Form link is clicked" do + click_link("Inline Form") + page.has_css?("form-inline") + end + + it "shows stacked form when Stacked Form link is clicked" do + click_link("Stacked Form") + page.has_no_css?("form-inline") and page.has_no_css?("form-horizontal") + end + end + + describe "form submission functions" do + let(:comment) { Comment.new(author: "Author", text: "This is a comment") } + let(:author_field) { "comment_author" } + let(:author_error) { "Author: can't be blank" } + let(:text_field) { "comment_text" } + let(:text_error) { "Text: can't be blank" } + + before do + visit "/rescript" + end + + it "adds a new comment to the page" do + fill_in author_field, with: comment.author + fill_in text_field, with: comment.text + click_button("Post") + expect(page).to have_selector "h2", text: comment.author + end + + it "comment count increases with successful form submission" do + initital_comment_count = Comment.all.count + new_comment_count = initital_comment_count + 1 + fill_in author_field, with: comment.author + fill_in text_field, with: comment.text + click_button("Post") + expect(Comment.all.count).to equal(new_comment_count) + end + + it "comment count remains the same when author field is empty" do + initial_comment_count = Comment.all.count + fill_in text_field, with: comment.text + click_button("Post") + expect(Comment.all.count).to equal(initial_comment_count) + end + + it "comment count remains the same when text field is empty" do + initial_comment_count = Comment.all.count + fill_in author_field, with: comment.author + click_button("Post") + expect(Comment.all.count).to equal(initial_comment_count) + end + + it "comment count remains the same when both form fields are empty" do + initial_comment_count = Comment.all.count + click_button("Post") + expect(Comment.all.count).to equal(initial_comment_count) + end + end +end diff --git a/yarn.lock b/yarn.lock index f669c60c..4c7e987e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1407,6 +1407,16 @@ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== +"@glennsl/rescript-fetch@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@glennsl/rescript-fetch/-/rescript-fetch-0.2.0.tgz#b72085d8bb19d8b9266aaf18d59c440ddceaf8dd" + integrity sha512-0tsEqJ/6/WBm02prM4RYG+qpnNTaB8QKKIeQHXdDaE4C5YfA/nzjxMNW3CjsGIaEgyrAmmIXFS0kx24UjvOI6A== + +"@glennsl/rescript-json-combinators@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@glennsl/rescript-json-combinators/-/rescript-json-combinators-1.2.1.tgz#3f641e4548ac1a664ce9acb140d5bba9ee1d5c9e" + integrity sha512-2Tw7NtrPerxN+9Y0u9bl9rUgqUqFcZkkRYELjHu9mIT/PDG3n8lO/osrwMIfoo6ze2FAur0Fw8hfDRJV8n3W3A== + "@hotwired/stimulus-webpack-helpers@^1.0.0", "@hotwired/stimulus-webpack-helpers@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz#4cd74487adeca576c9865ac2b9fe5cb20cef16dd" @@ -1853,6 +1863,16 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.7.2.tgz#cba1cf0a04bc04cb66027c51fa600e9cbc388bc8" integrity sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A== +"@rescript/core@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@rescript/core/-/core-0.5.0.tgz#3e83e75aaa60f42f4279e0d184358f2db5d40955" + integrity sha512-Keqnpi+8VqyhCk/3aMwar8hJbNy2IsINAAfIFeQC65IIegCR0QXFDBpQxfVcmbbtoHq6HnW4B3RLm/9GCUJQhQ== + +"@rescript/react@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@rescript/react/-/react-0.11.0.tgz#d2545546d823bdb8e6b59daa1790098d1666f79e" + integrity sha512-RzoAO+3cJwXE2D7yodMo4tBO2EkeDYCN/I/Sj/yRweI3S1CY1ZBOF/GMcVtjeIurJJt7KMveqQXTaRrqoGZBBg== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" @@ -8218,6 +8238,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +rescript@^10.1.4: + version "10.1.4" + resolved "https://registry.yarnpkg.com/rescript/-/rescript-10.1.4.tgz#0f37710d371f32a704f17b4e804f66ce3c79a305" + integrity sha512-FFKlS9AG/XrLepWsyw7B+A9DtQBPWEPDPDKghV831Y2KGbie+eeFBOS0xtRHp0xbt7S0N2Dm6hhX+kTZQ/3Ybg== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" From 94e2a712e8822d618180e3f6d5fdb4e0f208298d Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 24 Aug 2023 14:54:50 +0300 Subject: [PATCH 02/30] Solve render comments issue --- client/app/bundles/comments/src/RescriptPage.bs.mjs | 4 ++-- client/app/bundles/comments/src/RescriptPage.res | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/app/bundles/comments/src/RescriptPage.bs.mjs b/client/app/bundles/comments/src/RescriptPage.bs.mjs index 6181dae8..9b2238de 100644 --- a/client/app/bundles/comments/src/RescriptPage.bs.mjs +++ b/client/app/bundles/comments/src/RescriptPage.bs.mjs @@ -27,11 +27,11 @@ function RescriptPage(props) { })); ((async function (param) { try { - Actions.Api.storeComment(author, text); + await Actions.Api.storeComment(author, text); + var comments = await Actions.Api.fetchComments(undefined); Curry._1(setIsSaving, (function (param) { return false; })); - var comments = await Actions.Api.fetchComments(undefined); return Curry._1(setComments, (function (param) { return comments; })); diff --git a/client/app/bundles/comments/src/RescriptPage.res b/client/app/bundles/comments/src/RescriptPage.res index 7bbfb072..338ec971 100644 --- a/client/app/bundles/comments/src/RescriptPage.res +++ b/client/app/bundles/comments/src/RescriptPage.res @@ -8,9 +8,9 @@ let make = () => { setIsSaving(_ => true) let _ = (async() => { try { - let _ = Actions.Api.storeComment(author, text) - setIsSaving(_ => false) + let _ = await Actions.Api.storeComment(author, text) let comments = await Actions.Api.fetchComments() + setIsSaving(_ => false) setComments(_ => comments) } catch { | _ => setError(_ => true) From fb24f60eae3f1b90583ca794c862f31187ec941a Mon Sep 17 00:00:00 2001 From: yassa Date: Mon, 28 Aug 2023 16:41:19 +0300 Subject: [PATCH 03/30] Refactor css transaction components React Hooks shouldn't be used in loops or if statement. --- .../src/CSSTransition/CSSTransition.bs.mjs | 12 ++++ .../src/CSSTransition/CSSTransition.res | 26 ++++++++ .../CommentList/AlertError/AlertError.bs.mjs | 55 ++++++---------- .../src/CommentList/AlertError/AlertError.res | 17 +++++ .../src/CommentList/Comment/Comment.bs.mjs | 34 ++++++---- .../src/CommentList/Comment/Comment.res | 21 ++++-- .../src/CommentList/CommentList.bs.mjs | 42 +++--------- .../comments/src/CommentList/CommentList.res | 65 ++----------------- .../comments/src/RescriptPage.module.scss | 3 +- 9 files changed, 126 insertions(+), 149 deletions(-) create mode 100644 client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs create mode 100644 client/app/bundles/comments/src/CSSTransition/CSSTransition.res create mode 100644 client/app/bundles/comments/src/CommentList/AlertError/AlertError.res diff --git a/client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs b/client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs new file mode 100644 index 00000000..455b477e --- /dev/null +++ b/client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs @@ -0,0 +1,12 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + + +var TransitionGroup = {}; + +var CSSTransition = {}; + +export { + TransitionGroup , + CSSTransition , +} +/* No side effect */ diff --git a/client/app/bundles/comments/src/CSSTransition/CSSTransition.res b/client/app/bundles/comments/src/CSSTransition/CSSTransition.res new file mode 100644 index 00000000..3e5f93c1 --- /dev/null +++ b/client/app/bundles/comments/src/CSSTransition/CSSTransition.res @@ -0,0 +1,26 @@ +module TransitionGroup = { + @react.component @module("react-transition-group") + external make: ( + ~children: React.element, + ~className: string, + ~component: string + ) => React.element = "TransitionGroup" +} + +type cssTransitionGroupClassNamesT = { + enter: string, + enterActive: string, + exit: string, + exitActive: string +} + +module CSSTransition = { + @react.component @module("react-transition-group") + external make: ( + ~children: React.element, + ~key: string, + ~timeout: int, + ~nodeRef: React.ref>, + ~classNames: cssTransitionGroupClassNamesT + ) => React.element = "CSSTransition" +} diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs index cc1ed0d7..eb430213 100644 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs @@ -1,46 +1,29 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as React from "react"; -import * as JsxRuntime from "react/jsx-runtime"; -import * as ReactTransitionGroup from "react-transition-group"; +import * as React from 'react'; +import * as JsxRuntime from 'react/jsx-runtime'; +import * as ReactTransitionGroup from 'react-transition-group'; function AlertError(props) { - var cssTransitionGroupClassNames = props.cssTransitionGroupClassNames; var nodeRef = React.useRef(null); - switch (props.error) { - case /* NoError */0 : - return null; - case /* FailedToSaveComment */1 : - return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { - children: JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("strong", { - children: "Your comment was not saved!" - }), - className: "alert alert-danger" - }), - timeout: 500, - nodeRef: nodeRef, - classNames: cssTransitionGroupClassNames - }, "commentFetchError"); - case /* FailedToFetchComments */2 : - return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { - children: JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("strong", { - children: "Can't fetch the comments!" - }), - className: "alert alert-danger" - }), - timeout: 500, - nodeRef: nodeRef, - classNames: cssTransitionGroupClassNames - }, "commentFetchError"); - - } + return JsxRuntime.jsx( + ReactTransitionGroup.CSSTransition, + { + children: JsxRuntime.jsx('div', { + children: JsxRuntime.jsx('strong', { + children: 'Your comment was not saved!', + }), + className: 'alert alert-danger', + }), + timeout: 500, + nodeRef: nodeRef, + classNames: props.cssTransitionGroupClassNames, + }, + 'commentFetchError', + ); } var make = AlertError; -export { - make , -} +export { make }; /* react Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res new file mode 100644 index 00000000..02c707be --- /dev/null +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res @@ -0,0 +1,17 @@ +@react.component +let make = (~cssTransitionGroupClassNames: CSSTransition.cssTransitionGroupClassNamesT) => { + let nodeRef = React.useRef(Js.Nullable.null) + + // The 500 must correspond to the 0.5s in: + // ../../RescriptPage.module.scss:9 + +
    + {React.string("Your comment was not saved!")} +
    +
    +} \ No newline at end of file diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs b/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs index 0ac41408..1bbb8b55 100644 --- a/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs @@ -1,9 +1,11 @@ // Generated by ReScript, PLEASE EDIT WITH CARE +import * as React from "react"; import * as Marked from "marked"; import * as Caml_option from "rescript/lib/es6/caml_option.js"; import * as JsxRuntime from "react/jsx-runtime"; import CommentModuleScss from "./Comment.module.scss"; +import * as ReactTransitionGroup from "react-transition-group"; var css = CommentModuleScss; @@ -15,19 +17,25 @@ function $$Comment(props) { var innerHTML = { __html: rawMarkup }; - return JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("h2", { - children: comment.author, - className: css.commentAuthor - }), - JsxRuntime.jsx("span", { - dangerouslySetInnerHTML: Caml_option.some(innerHTML) - }) - ], - ref: Caml_option.some(props.nodeRef), - className: css.comment - }); + var nodeRef = React.useRef(null); + return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { + children: JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsx("h2", { + children: comment.author, + className: css.commentAuthor + }), + JsxRuntime.jsx("span", { + dangerouslySetInnerHTML: Caml_option.some(innerHTML) + }) + ], + ref: Caml_option.some(nodeRef), + className: css.comment + }), + timeout: 500, + nodeRef: nodeRef, + classNames: props.cssTransitionGroupClassNames + }, "component_" + String(comment.id)); } var make = $$Comment; diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.res b/client/app/bundles/comments/src/CommentList/Comment/Comment.res index 2b7e8250..51389f5e 100644 --- a/client/app/bundles/comments/src/CommentList/Comment/Comment.res +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.res @@ -6,12 +6,23 @@ type markedOptions = { @module("marked") external marked: (string, markedOptions) => string = "marked"; @react.component -let make = (~comment: Actions.Api.comment, ~nodeRef) => { +let make = (~comment: Actions.Api.comment, ~cssTransitionGroupClassNames) => { let rawMarkup = marked(comment.text, {gfm: true}) let innerHTML = { "__html": rawMarkup } + let nodeRef = React.useRef(Js.Nullable.null) + + // The 500 must correspond to the 0.5s in: + // ../../RescriptPage.module.scss:9 + +
    +

    {comment.author->React.string}

    + +
    +
    -
    -

    {comment.author->React.string}

    - -
    } \ No newline at end of file diff --git a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs index f3be48b5..6aac1bd9 100644 --- a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs +++ b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs @@ -1,7 +1,7 @@ // Generated by ReScript, PLEASE EDIT WITH CARE -import * as React from "react"; import * as $$Comment from "./Comment/Comment.bs.mjs"; +import * as AlertError from "./AlertError/AlertError.bs.mjs"; import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; import * as JsxRuntime from "react/jsx-runtime"; import * as ReactTransitionGroup from "react-transition-group"; @@ -9,10 +9,6 @@ import RescriptPageModuleScss from "../RescriptPage.module.scss"; var css = RescriptPageModuleScss; -var TransitionGroup = {}; - -var CSSTransition = {}; - function CommentList(props) { var cssTransitionGroupClassNames_enter = css.elementEnter; var cssTransitionGroupClassNames_enterActive = css.elementEnterActive; @@ -24,34 +20,14 @@ function CommentList(props) { exit: cssTransitionGroupClassNames_exit, exitActive: cssTransitionGroupClassNames_exitActive }; - var errorMsg; - if (props.error) { - var nodeRef = React.useRef(null); - errorMsg = JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { - children: JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("strong", { - children: "Your comment was not saved!" - }), - className: "alert alert-danger" - }), - timeout: 500, - nodeRef: nodeRef, - classNames: cssTransitionGroupClassNames - }, "commentFetchError"); - } else { - errorMsg = JsxRuntime.jsx(JsxRuntime.Fragment, {}); - } + var errorMsg = props.error ? JsxRuntime.jsx(AlertError.make, { + cssTransitionGroupClassNames: cssTransitionGroupClassNames + }) : JsxRuntime.jsx(JsxRuntime.Fragment, {}); var commentsElements = Belt_Array.map(props.comments, (function (comment) { - var nodeRef = React.useRef(null); - return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { - children: JsxRuntime.jsx($$Comment.make, { - comment: comment, - nodeRef: nodeRef - }), - timeout: 500, - nodeRef: nodeRef, - classNames: cssTransitionGroupClassNames - }, "component_" + String(comment.id)); + return JsxRuntime.jsx($$Comment.make, { + comment: comment, + cssTransitionGroupClassNames: cssTransitionGroupClassNames + }, "comment_" + String(comment.id)); })); return JsxRuntime.jsxs("div", { children: [ @@ -69,8 +45,6 @@ var make = CommentList; export { css , - TransitionGroup , - CSSTransition , make , } /* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/CommentList.res b/client/app/bundles/comments/src/CommentList/CommentList.res index 36840873..90976019 100644 --- a/client/app/bundles/comments/src/CommentList/CommentList.res +++ b/client/app/bundles/comments/src/CommentList/CommentList.res @@ -1,35 +1,8 @@ @module("../RescriptPage.module.scss") external css: {..} = "default" -module TransitionGroup = { - @react.component @module("react-transition-group") - external make: ( - ~children: React.element, - ~className: string, - ~component: string - ) => React.element = "TransitionGroup" -} - -type cssTransitionGroupClassNamesT = { - enter: string, - enterActive: string, - exit: string, - exitActive: string -} - -module CSSTransition = { - @react.component @module("react-transition-group") - external make: ( - ~children: React.element, - ~key: string, - ~timeout: int, - ~nodeRef: React.ref>, - ~classNames: cssTransitionGroupClassNamesT - ) => React.element = "CSSTransition" -} - @react.component let make = (~comments: Actions.Api.comments, ~error: bool) => { - let cssTransitionGroupClassNames = { + let cssTransitionGroupClassNames: CSSTransition.cssTransitionGroupClassNamesT = { enter: css["elementEnter"], enterActive: css["elementEnterActive"], exit: css["elementLeave"], @@ -37,46 +10,18 @@ let make = (~comments: Actions.Api.comments, ~error: bool) => { } let errorMsg = switch error { - | true => (() => { - let nodeRef = React.useRef(Js.Nullable.null) - - // The 500 must correspond to the 0.5s in: - // ../RescriptPage.module.scss:8 - -
    - {React.string("Your comment was not saved!")} -
    -
    - })() + | true => | false => <> } let commentsElements = Belt.Array.map( comments, - comment => { - let nodeRef = React.useRef(Js.Nullable.null) - - // The 500 must correspond to the 0.5s in: - // ../RescriptPage.module.scss:8 - - - - }); + comment => );
    errorMsg - + {React.array(commentsElements)} - +
    } diff --git a/client/app/bundles/comments/src/RescriptPage.module.scss b/client/app/bundles/comments/src/RescriptPage.module.scss index a54a6329..01a74159 100644 --- a/client/app/bundles/comments/src/RescriptPage.module.scss +++ b/client/app/bundles/comments/src/RescriptPage.module.scss @@ -1,5 +1,6 @@ // The 0.5s must correspond to the 500s in: -// ./CommentList/CommentList.res:47 +// ./CommentList/AlertError/AlertError.res:10 +// ./CommentList/Comment/Comment.res:18 .elementEnter { opacity: 0.01; From 3fe89de9c43d94fe4c02330a2c035335c959d51f Mon Sep 17 00:00:00 2001 From: yassa Date: Mon, 28 Aug 2023 16:46:53 +0300 Subject: [PATCH 04/30] Ignore the rescript output js files from lint The rescript output js files from lint because it doesn't follow the lint rules. --- .eslintignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintignore b/.eslintignore index e9152576..9d1f596b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,3 +4,4 @@ public/ client/app/libs/i18n/translations.js client/app/libs/i18n/default.js postcss.config.js +client/app/bundles/comments/src/ From bf38c2cc7c031f14091f0ada39f153b3043e5c8e Mon Sep 17 00:00:00 2001 From: yassa Date: Mon, 4 Sep 2023 13:03:20 +0300 Subject: [PATCH 05/30] Apply review requested changes --- bsconfig.json | 6 +- .../comments/src/Actions/Actions.bs.mjs | 43 ++- .../bundles/comments/src/Actions/Actions.res | 89 ++--- .../bundles/comments/src/Actions/Types.res | 28 ++ .../src/CSSTransition/CSSTransition.bs.mjs | 12 - .../src/CommentForm/CommentForm.bs.mjs | 318 +++++++----------- .../comments/src/CommentForm/CommentForm.res | 181 +++++----- .../src/CommentForm/forms/HorizontalForm.res | 33 ++ .../src/CommentForm/forms/InlineForm.res | 23 ++ .../src/CommentForm/forms/StackedFrom.res | 23 ++ .../CommentList/AlertError/AlertError.bs.mjs | 1 + .../src/CommentList/AlertError/AlertError.res | 47 ++- .../src/CommentList/Comment/Comment.res | 15 +- .../src/CommentList/CommentList.bs.mjs | 21 +- .../comments/src/CommentList/CommentList.res | 34 +- .../bundles/comments/src/Header/Header.bs.mjs | 4 +- .../bundles/comments/src/Header/Header.res | 22 +- .../bundles/comments/src/RescriptPage.bs.mjs | 127 ++++--- .../app/bundles/comments/src/RescriptPage.res | 70 +++- .../bundles/comments/src/bindings/Axios.res | 5 + .../CSSAnimation.res} | 16 +- .../bundles/comments/src/bindings/Marked.res | 4 + .../comments/src/bindings/ReactOnRails.res | 7 + client/app/bundles/comments/src/vars.scss | 2 +- client/app/packs/client-bundle.js | 2 +- client/app/packs/server-bundle.js | 2 +- spec/rescript/rescript_spec.rb | 10 +- 27 files changed, 613 insertions(+), 532 deletions(-) create mode 100644 client/app/bundles/comments/src/Actions/Types.res delete mode 100644 client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs create mode 100644 client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res create mode 100644 client/app/bundles/comments/src/CommentForm/forms/InlineForm.res create mode 100644 client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res create mode 100644 client/app/bundles/comments/src/bindings/Axios.res rename client/app/bundles/comments/src/{CSSTransition/CSSTransition.res => bindings/CSSAnimation.res} (74%) create mode 100644 client/app/bundles/comments/src/bindings/Marked.res create mode 100644 client/app/bundles/comments/src/bindings/ReactOnRails.res diff --git a/bsconfig.json b/bsconfig.json index fea05cca..3a0e8641 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -13,8 +13,8 @@ } ], "bsc-flags": [ - "-bs-super-errors", - "-open JsonCombinators" + "-open JsonCombinators", + "-open Belt" ], "suffix": ".bs.mjs", "bs-dependencies": [ @@ -27,4 +27,4 @@ "version": 4, "mode": "automatic" } -} \ No newline at end of file +} diff --git a/client/app/bundles/comments/src/Actions/Actions.bs.mjs b/client/app/bundles/comments/src/Actions/Actions.bs.mjs index a1723d69..a83373f6 100644 --- a/client/app/bundles/comments/src/Actions/Actions.bs.mjs +++ b/client/app/bundles/comments/src/Actions/Actions.bs.mjs @@ -2,11 +2,24 @@ import * as Curry from "rescript/lib/es6/curry.js"; import * as Axios from "axios"; -import * as Js_exn from "rescript/lib/es6/js_exn.js"; import ReactOnRails from "react-on-rails"; import * as Json$JsonCombinators from "@glennsl/rescript-json-combinators/src/Json.bs.mjs"; import * as Json_Decode$JsonCombinators from "@glennsl/rescript-json-combinators/src/Json_Decode.bs.mjs"; +async function storeComment(comment) { + await Axios.post("comments.json", { + author: comment.author, + text: comment.text + }, { + responseType: "json", + headers: Curry._1(ReactOnRails.default.authenticityHeaders, undefined) + }); +} + +var Create = { + storeComment: storeComment +}; + async function fetchComments(param) { var response = await fetch("comments.json"); var jsonRes = await response.json(); @@ -24,28 +37,24 @@ async function fetchComments(param) { }); var decodedRes = Json$JsonCombinators.decode(jsonRes, jsonComments); if (decodedRes.TAG === /* Ok */0) { - return decodedRes._0.comments; + return { + TAG: /* Ok */0, + _0: decodedRes._0.comments + }; } else { - return Js_exn.raiseError(decodedRes._0); + return { + TAG: /* Error */1, + _0: /* FailedToFetchComments */2 + }; } } -async function storeComment(author, text) { - await Axios.post("comments.json", { - author: author, - text: text - }, { - responseType: "json", - headers: Curry._1(ReactOnRails.default.authenticityHeaders, undefined) - }); -} - -var Api = { - fetchComments: fetchComments, - storeComment: storeComment +var Fetch = { + fetchComments: fetchComments }; export { - Api , + Create , + Fetch , } /* axios Not a pure module */ diff --git a/client/app/bundles/comments/src/Actions/Actions.res b/client/app/bundles/comments/src/Actions/Actions.res index d63b8c02..f1c92437 100644 --- a/client/app/bundles/comments/src/Actions/Actions.res +++ b/client/app/bundles/comments/src/Actions/Actions.res @@ -1,38 +1,38 @@ -// ReactOnRails binding -type rorDefault = { - authenticityHeaders: unit => {.} -} -type rorModule = { - default: rorDefault -} -@module("react-on-rails") external ror: rorModule = "default"; - -type storeCommentData = { - author: string, - text: string -} +module Create = { + type t = { + author: string, + text: string + } -// axios binding -type reqOptions = { - responseType: string, - headers: {.} + let storeComment = async (comment: t) => { + let _ = await Axios.post( + "comments.json", + { + author: comment.author, + text: comment.text + }, + { + responseType: "json", + headers: ReactOnRails.ror.default.authenticityHeaders() + } + ) + } } -@module("axios") external post: (string, storeCommentData, reqOptions) => promise = "post"; -module Api = { - type comment = { +module Fetch = { + type t = { author: string, text: string, id: int - }; - - type comments = array + } + + type comments = array - type commentsRes = { + type commentsResT = { comments: comments } - let fetchComments = async (): comments => { + let fetchComments = async (): result => { open Json.Decode; let response = await Fetch.get("comments.json") @@ -49,43 +49,8 @@ module Api = { }) switch jsonRes->Json.decode(jsonComments) { - | Ok(decodedRes) => decodedRes.comments - | Error(err) => Js.Exn.raiseError(err) + | Ok(decodedRes) => Ok(decodedRes.comments) + | Error(_) => Error(FailedToFetchComments) } } - - let storeComment = async (author: string, text: string) => { - let _ = await post( - "comments.json", - { - author: author, - text: text - }, - { - responseType: "json", - headers:ror.default.authenticityHeaders() - } - ) - - - // setIsSaving(_ => true) - // try { - // let _ = await post( - // "comments.json", - // { - // author: author, - // text: text - // }, - // { - // responseType: "json", - // headers:ror.default.authenticityHeaders() - // } - // ) - // setIsSaving(_ => false) - // let comments = await fetchComments() - // setComments(_ => comments) - // } catch { - // | _ => setError(_ => true) - // } - } } diff --git a/client/app/bundles/comments/src/Actions/Types.res b/client/app/bundles/comments/src/Actions/Types.res new file mode 100644 index 00000000..97e574eb --- /dev/null +++ b/client/app/bundles/comments/src/Actions/Types.res @@ -0,0 +1,28 @@ +type formDisplayT = HorizontalForm | InlineForm | StackedFrom; + +type commentFormStateT = { + author: string, + text: string, + form: formDisplayT +} + +type commentFormActionT = + | SetAuthor(string) + | SetText(string) + | SetFormType(formDisplayT); + +type formDataT = { + formName: string, + formType: formDisplayT +}; + +type storeCommentActionT = (string, string) => unit; + +type storeCommentDataT = { + author: string, + text: string +} + +type errorT = NoError | FailedToSaveComment | FailedToFetchComments; + +type isSavingT = Free | BusySaving; diff --git a/client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs b/client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs deleted file mode 100644 index 455b477e..00000000 --- a/client/app/bundles/comments/src/CSSTransition/CSSTransition.bs.mjs +++ /dev/null @@ -1,12 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - - -var TransitionGroup = {}; - -var CSSTransition = {}; - -export { - TransitionGroup , - CSSTransition , -} -/* No side effect */ diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs index 148e198a..2fa22824 100644 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs @@ -3,233 +3,140 @@ import * as Curry from "rescript/lib/es6/curry.js"; import * as React from "react"; import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; +import * as InlineForm from "./forms/InlineForm.bs.mjs"; +import * as StackedFrom from "./forms/StackedFrom.bs.mjs"; +import * as HorizontalForm from "./forms/HorizontalForm.bs.mjs"; import * as JsxRuntime from "react/jsx-runtime"; import CommentFormModuleScss from "./CommentForm.module.scss"; var css = CommentFormModuleScss; +function reducer(state, action) { + switch (action.TAG | 0) { + case /* SetAuthor */0 : + return { + author: action._0, + text: state.text, + form: state.form + }; + case /* SetText */1 : + return { + author: state.author, + text: action._0, + form: state.form + }; + case /* SetFormType */2 : + return { + author: state.author, + text: state.text, + form: action._0 + }; + + } +} + function CommentForm(props) { + var isSaving = props.isSaving; var storeComment = props.storeComment; - var match = React.useState(function () { - return ""; - }); - var setAuthor = match[1]; - var author = match[0]; - var match$1 = React.useState(function () { - return ""; + var match = React.useReducer(reducer, { + author: "", + text: "", + form: /* HorizontalForm */0 }); - var setText = match$1[1]; - var text = match$1[0]; - var match$2 = React.useState(function () { - return "Horizontal Form"; - }); - var setCurrFormType = match$2[1]; - var currformType = match$2[0]; - var handleAuthorChange = function (e) { - Curry._1(setAuthor, e.currentTarget.value); + var dispatch = match[1]; + var state = match[0]; + var handleAuthorChange = function ($$event) { + var value = $$event.currentTarget.value; + Curry._1(dispatch, { + TAG: /* SetAuthor */0, + _0: value + }); }; - var handleTextChange = function (e) { - Curry._1(setText, e.currentTarget.value); + var handleTextChange = function ($$event) { + var value = $$event.currentTarget.value; + Curry._1(dispatch, { + TAG: /* SetText */1, + _0: value + }); }; - var handleSubmit = function (e) { - e.preventDefault(); - Curry._2(storeComment, author, text); + var handleSubmit = function ($$event) { + $$event.preventDefault(); + Curry._2(storeComment, state.author, state.text); }; - var horizontalForm = JsxRuntime.jsxs("form", { - children: [ - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("label", { - children: "Name", - className: "form-label pull-right" - }), - className: "col-sm-2" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "form-control", - placeholder: "Your Name", - type: "text", - value: author, - onChange: handleAuthorChange - }), - className: "col-sm-10" - }) - ], - className: "form-group" - }), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("label", { - children: "Text", - className: "form-label pull-right" - }), - className: "col-sm-2" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "form-control", - placeholder: "Say something using markdown...", - type: "text", - value: text, - onChange: handleTextChange - }), - className: "col-sm-10" - }) - ], - className: "form-group" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "btn btn-primary", - type: "submit" - }), - className: "col-sm-10 col-sm-offset-2" - }), - className: "form-group" - }) - ], - className: "form-horizontal", - disabled: props.isSaving, - onSubmit: handleSubmit - }); - var inlineForm = JsxRuntime.jsxs("form", { - children: [ - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Name", - className: "form-label mr-15" - }), - JsxRuntime.jsx("input", { - className: "form-control", - placeholder: "Your Name", - type: "text", - value: author - }) - ], - className: "form-group" - }), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Text", - className: "form-label mr-15" - }), - JsxRuntime.jsx("input", { - className: "form-control w-50", - placeholder: "Say something using markdown...", - type: "text", - value: text, - onChange: handleTextChange - }) - ], - className: "form-group ml-15 mr-15" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "btn btn-primary", - type: "submit", - onSubmit: handleSubmit - }), - className: "form-group" - }) - ], - className: "form-inline", - onChange: handleAuthorChange - }); - var stackedForm = JsxRuntime.jsxs("form", { - children: [ - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Name", - className: "form-label" - }), - JsxRuntime.jsx("input", { - className: "form-control", - placeholder: "Your Name", - type: "text", - value: author, - onChange: handleAuthorChange - }) - ], - className: "form-group" - }), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Name", - className: "form-label" - }), - JsxRuntime.jsx("input", { - className: "form-control", - placeholder: "Say something using markdown...", - type: "text", - value: text, - onChange: handleTextChange - }) - ], - className: "form-group" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "btn btn-primary", - type: "submit", - onSubmit: handleSubmit - }), - className: "form-group" - }) - ], - onChange: handleAuthorChange - }); - var formTypes = [ - "Horizontal Form", - "Stacked Form", - "Inline Form" + var forms = [ + { + formName: "Horizontal Form", + formType: /* HorizontalForm */0 + }, + { + formName: "Inline Form", + formType: /* InlineForm */1 + }, + { + formName: "Stacked Form", + formType: /* StackedFrom */2 + } ]; - var formsNavbarComponent = Belt_Array.map(formTypes, (function (formType) { - return JsxRuntime.jsx("li", { - children: JsxRuntime.jsx("a", { - children: formType, - className: css.anchorButton - }), - className: "nav-item " + ( - currformType === formType ? "active" : "" - ), - role: "presentation", - onClick: (function (param) { - Curry._1(setCurrFormType, (function (param) { - return formType; - })); - }) - }, "form_" + formType); - })); - var form; - switch (currformType) { - case "Horizontal Form" : - form = horizontalForm; + var match$1 = state.form; + var tmp; + switch (match$1) { + case /* HorizontalForm */0 : + tmp = JsxRuntime.jsx(HorizontalForm.make, { + author: state.author, + handleAuthorChange: handleAuthorChange, + text: state.text, + handleTextChange: handleTextChange, + handleSubmit: handleSubmit, + isSaving: isSaving + }); break; - case "Inline Form" : - form = inlineForm; + case /* InlineForm */1 : + tmp = JsxRuntime.jsx(InlineForm.make, { + author: state.author, + handleAuthorChange: handleAuthorChange, + text: state.text, + handleTextChange: handleTextChange, + handleSubmit: handleSubmit, + isSaving: isSaving + }); break; - case "Stacked Form" : - form = stackedForm; + case /* StackedFrom */2 : + tmp = JsxRuntime.jsx(StackedFrom.make, { + author: state.author, + handleAuthorChange: handleAuthorChange, + text: state.text, + handleTextChange: handleTextChange, + handleSubmit: handleSubmit, + isSaving: isSaving + }); break; - default: - form = horizontalForm; + } return JsxRuntime.jsxs("div", { children: [ JsxRuntime.jsx("ul", { - children: formsNavbarComponent, + children: Belt_Array.map(forms, (function (form) { + return JsxRuntime.jsx("li", { + children: JsxRuntime.jsx("a", { + children: form.formName, + className: css.anchorButton + }), + className: "nav-item " + ( + state.form === form.formType ? "active" : "" + ), + role: "presentation", + onClick: (function ($$event) { + Curry._1(dispatch, { + TAG: /* SetFormType */2, + _0: form.formType + }); + }) + }, "form_" + form.formName); + })), className: "nav nav-pills" }), JsxRuntime.jsx("hr", {}), - form + tmp ] }); } @@ -238,6 +145,7 @@ var make = CommentForm; export { css , + reducer , make , } /* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.res b/client/app/bundles/comments/src/CommentForm/CommentForm.res index e4f61853..db3997c3 100644 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.res @@ -1,117 +1,98 @@ @module("./CommentForm.module.scss") external css: {..} = "default" -type storeCommentAction = (string, string) => unit; + +let reducer = ( + state: Types.commentFormStateT, + action: Types.commentFormActionT +): Types.commentFormStateT => { + switch (action) { + | SetAuthor(author) => {...state, author} + | SetText(text) => {...state, text} + | SetFormType(form) => {...state, form: form} + }; +} + @react.component -let make = (~storeComment: storeCommentAction, ~isSaving: bool) => { - let (author, setAuthor) = React.useState(_ => "") - let (text, setText) = React.useState(_ => "") - let (currformType, setCurrFormType) = React.useState(_ => "Horizontal Form") +let make = (~storeComment: Types.storeCommentActionT, ~isSaving: Types.isSavingT) => { + let (state, dispatch) = React.useReducer( + reducer, { + author: "", + text: "", + form: HorizontalForm + } + ) - let handleAuthorChange = (e) => { - setAuthor(ReactEvent.Form.currentTarget(e)["value"]) - () + let handleAuthorChange = (event) => { + let value = ReactEvent.Form.currentTarget(event)["value"] + SetAuthor(value)->dispatch } - let handleTextChange = (e) => { - setText(ReactEvent.Form.currentTarget(e)["value"]) - () + let handleTextChange = (event) => { + let value = ReactEvent.Form.currentTarget(event)["value"] + SetText(value)->dispatch } - let handleSubmit = (e) => { - ReactEvent.Form.preventDefault(e) - storeComment(author, text) + let handleSubmit = (event) => { + ReactEvent.Form.preventDefault(event) + storeComment(state.author, state.text) } - let horizontalForm = ( -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - ) - - let inlineForm = ( -
    -
    - - -
    -
    - - -
    -
    - -
    -
    - ) - - let stackedForm = ( -
    -
    - - -
    -
    - - -
    -
    - -
    -
    - ) - - let formTypes: array = [ - "Horizontal Form", - "Stacked Form", - "Inline Form" + let forms: array = + [ + {formName: "Horizontal Form", formType: HorizontalForm}, + {formName: "Inline Form", formType: InlineForm}, + {formName: "Stacked Form", formType: StackedFrom} ] - let handleClick = (formType: string): unit => { - setCurrFormType(_ => formType) - (); - } - - let formsNavbarComponent = ( - Belt.Array.map(formTypes, formType => -
  • handleClick(formType)) role="presentation"> - {React.string(formType)} -
  • - ) - ) - - let form = switch currformType { - | "Horizontal Form" => horizontalForm - | "Stacked Form" => stackedForm - | "Inline Form" => inlineForm - | _ => horizontalForm - } -
      - { React.array(formsNavbarComponent) } + { + forms + ->Belt.Array.map(form + => ( +
    • SetFormType(form.formType)->dispatch} + role="presentation" + > + {form.formName->React.string} +
    • + ) + )->React.array + }

    - form + { + switch state.form { + | HorizontalForm + => + | StackedFrom + => + | InlineForm + => + } + }
    - -} \ No newline at end of file +} diff --git a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res new file mode 100644 index 00000000..bbe263f8 --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res @@ -0,0 +1,33 @@ +@react.component +let make = ( + ~author, + ~handleAuthorChange, + ~text, + ~handleTextChange, + ~handleSubmit, + ~isSaving: Types.isSavingT + ) => { +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    +
    +} diff --git a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res new file mode 100644 index 00000000..256225fd --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res @@ -0,0 +1,23 @@ +@react.component +let make = ( + ~author, + ~handleAuthorChange, + ~text, + ~handleTextChange, + ~handleSubmit, + ~isSaving: Types.isSavingT + ) => { +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +} diff --git a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res new file mode 100644 index 00000000..1b95a16f --- /dev/null +++ b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res @@ -0,0 +1,23 @@ +@react.component +let make = ( + ~author, + ~handleAuthorChange, + ~text, + ~handleTextChange, + ~handleSubmit, + ~isSaving: Types.isSavingT + ) => { +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +} diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs index eb430213..d7999652 100644 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs @@ -5,6 +5,7 @@ import * as JsxRuntime from 'react/jsx-runtime'; import * as ReactTransitionGroup from 'react-transition-group'; function AlertError(props) { + var cssTransitionGroupClassNames = props.cssTransitionGroupClassNames; var nodeRef = React.useRef(null); return JsxRuntime.jsx( ReactTransitionGroup.CSSTransition, diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res index 02c707be..c77050f5 100644 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res @@ -1,17 +1,34 @@ @react.component -let make = (~cssTransitionGroupClassNames: CSSTransition.cssTransitionGroupClassNamesT) => { +let make = (~cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t, ~error: Types.errorT) => { let nodeRef = React.useRef(Js.Nullable.null) - - // The 500 must correspond to the 0.5s in: - // ../../RescriptPage.module.scss:9 - -
    - {React.string("Your comment was not saved!")} -
    -
    -} \ No newline at end of file + + switch error { + | FailedToSaveComment => + // The 500 must correspond to the 0.5s in: + // ../../RescriptPage.module.scss:9 + +
    + {"Your comment was not saved!"->React.string} +
    +
    + | FailedToFetchComments => + // The 500 must correspond to the 0.5s in: + // ../../RescriptPage.module.scss:9 + +
    + {"Can't fetch the comments!"->React.string} +
    +
    + | NoError => React.null + } +} diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.res b/client/app/bundles/comments/src/CommentList/Comment/Comment.res index 51389f5e..16cb0021 100644 --- a/client/app/bundles/comments/src/CommentList/Comment/Comment.res +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.res @@ -1,19 +1,14 @@ @module("./Comment.module.scss") external css: {..} = "default" -type markedOptions = { - gfm: bool -} -@module("marked") external marked: (string, markedOptions) => string = "marked"; - @react.component -let make = (~comment: Actions.Api.comment, ~cssTransitionGroupClassNames) => { - let rawMarkup = marked(comment.text, {gfm: true}) +let make = (~comment: Actions.Fetch.t, ~cssTransitionGroupClassNames) => { + let rawMarkup = Marked.marked(comment.text, {gfm: true}) let innerHTML = { "__html": rawMarkup } let nodeRef = React.useRef(Js.Nullable.null) // The 500 must correspond to the 0.5s in: // ../../RescriptPage.module.scss:9 - {

    {comment.author->React.string}

    -
    + -} \ No newline at end of file +} diff --git a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs index 6aac1bd9..c217d008 100644 --- a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs +++ b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs @@ -20,20 +20,19 @@ function CommentList(props) { exit: cssTransitionGroupClassNames_exit, exitActive: cssTransitionGroupClassNames_exitActive }; - var errorMsg = props.error ? JsxRuntime.jsx(AlertError.make, { - cssTransitionGroupClassNames: cssTransitionGroupClassNames - }) : JsxRuntime.jsx(JsxRuntime.Fragment, {}); - var commentsElements = Belt_Array.map(props.comments, (function (comment) { - return JsxRuntime.jsx($$Comment.make, { - comment: comment, - cssTransitionGroupClassNames: cssTransitionGroupClassNames - }, "comment_" + String(comment.id)); - })); return JsxRuntime.jsxs("div", { children: [ - errorMsg, + JsxRuntime.jsx(AlertError.make, { + cssTransitionGroupClassNames: cssTransitionGroupClassNames, + error: props.error + }), JsxRuntime.jsx(ReactTransitionGroup.TransitionGroup, { - children: commentsElements, + children: Belt_Array.map(props.comments, (function (comment) { + return JsxRuntime.jsx($$Comment.make, { + comment: comment, + cssTransitionGroupClassNames: cssTransitionGroupClassNames + }, "comment_" + String(comment.id)); + })), className: "commentList", component: "div" }) diff --git a/client/app/bundles/comments/src/CommentList/CommentList.res b/client/app/bundles/comments/src/CommentList/CommentList.res index 90976019..e916cbf7 100644 --- a/client/app/bundles/comments/src/CommentList/CommentList.res +++ b/client/app/bundles/comments/src/CommentList/CommentList.res @@ -1,27 +1,31 @@ @module("../RescriptPage.module.scss") external css: {..} = "default" @react.component -let make = (~comments: Actions.Api.comments, ~error: bool) => { - let cssTransitionGroupClassNames: CSSTransition.cssTransitionGroupClassNamesT = { +let make = (~comments: Actions.Fetch.comments, ~error: Types.errorT) => { + let cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t = { enter: css["elementEnter"], enterActive: css["elementEnterActive"], exit: css["elementLeave"], exitActive: css["elementLeaveActive"] } - let errorMsg = switch error { - | true => - | false => <> - } - - let commentsElements = Belt.Array.map( - comments, - comment => ); -
    - errorMsg - - {React.array(commentsElements)} - + { + + } + + { + comments->Belt.Array.map( + comment => + Belt.Int.toString + } + /> + )->React.array + } +
    } diff --git a/client/app/bundles/comments/src/Header/Header.bs.mjs b/client/app/bundles/comments/src/Header/Header.bs.mjs index 7b837973..5fe7b1d6 100644 --- a/client/app/bundles/comments/src/Header/Header.bs.mjs +++ b/client/app/bundles/comments/src/Header/Header.bs.mjs @@ -65,7 +65,9 @@ function Header(props) { children: "ShakaCode", href: "http://www.shakacode.com" }), - " is doing support for React on Rails, including a private Slack channel, source code reviews, and pair programming sessions. ", + " is doing support for React on Rails, \ + including a private Slack channel, \ + source code reviews, and pair programming sessions. ", JsxRuntime.jsx("b", { children: JsxRuntime.jsx("a", { children: "Click here", diff --git a/client/app/bundles/comments/src/Header/Header.res b/client/app/bundles/comments/src/Header/Header.res index 4260a463..299c832a 100644 --- a/client/app/bundles/comments/src/Header/Header.res +++ b/client/app/bundles/comments/src/Header/Header.res @@ -20,32 +20,34 @@ let make = () => { {"Documentation for React on Rails"->React.string} - {React.string("The React on Rails Doctrine.")} + {"The React on Rails Doctrine."->React.string}
  • - {React.string("See our React Native Client: ")} + {"See our React Native Client: "->React.string} - {React.string("shakacode/react-native-tutorial")} + {"shakacode/react-native-tutorial"->React.string} - {React.string(".")} + {"."->React.string}
  • - {React.string("Watch the ")} + {"Watch the "->React.string} - {React.string("React On Rails Tutorial Series")} + {"React On Rails Tutorial Series"->React.string} - {React.string(".")} + {"."->React.string}
  • {"ShakaCode"->React.string} - {React.string(" is doing support for React on Rails, including a private Slack channel, source code reviews, and pair programming sessions. ")} + {" is doing support for React on Rails, \ + including a private Slack channel, \ + source code reviews, and pair programming sessions. "->React.string} {"Click here"->React.string} - {React.string(" for more information.")} + {" for more information."->React.string}

  • -} \ No newline at end of file +} diff --git a/client/app/bundles/comments/src/RescriptPage.bs.mjs b/client/app/bundles/comments/src/RescriptPage.bs.mjs index 9b2238de..1db680f5 100644 --- a/client/app/bundles/comments/src/RescriptPage.bs.mjs +++ b/client/app/bundles/comments/src/RescriptPage.bs.mjs @@ -8,47 +8,93 @@ import * as CommentForm from "./CommentForm/CommentForm.bs.mjs"; import * as CommentList from "./CommentList/CommentList.bs.mjs"; import * as JsxRuntime from "react/jsx-runtime"; +function reducer(state, action) { + switch (action.TAG | 0) { + case /* SetComments */0 : + return { + comments: action._0, + error: state.error, + isSaving: state.isSaving + }; + case /* SetError */1 : + return { + comments: state.comments, + error: action._0, + isSaving: state.isSaving + }; + case /* SetIsSaving */2 : + return { + comments: state.comments, + error: state.error, + isSaving: action._0 + }; + + } +} + function RescriptPage(props) { - var match = React.useState(function () { - return []; - }); - var setComments = match[1]; - var match$1 = React.useState(function () { - return false; + var match = React.useReducer(reducer, { + comments: [], + error: /* NoError */0, + isSaving: /* Free */0 }); - var setError = match$1[1]; - var match$2 = React.useState(function () { - return false; - }); - var setIsSaving = match$2[1]; + var dispatch = match[1]; + var state = match[0]; var storeComment = function (author, text) { - Curry._1(setIsSaving, (function (param) { - return true; - })); - ((async function (param) { - try { - await Actions.Api.storeComment(author, text); - var comments = await Actions.Api.fetchComments(undefined); - Curry._1(setIsSaving, (function (param) { - return false; - })); - return Curry._1(setComments, (function (param) { - return comments; - })); - } - catch (exn){ - return Curry._1(setError, (function (param) { - return true; - })); - } - })(undefined)); + Curry._1(dispatch, { + TAG: /* SetError */1, + _0: /* NoError */0 + }); + Curry._1(dispatch, { + TAG: /* SetIsSaving */2, + _0: /* BusySaving */1 + }); + var saveAndFetchComments = async function (param) { + try { + await Actions.Create.storeComment({ + author: author, + text: text + }); + Curry._1(dispatch, { + TAG: /* SetIsSaving */2, + _0: /* Free */0 + }); + var comments = await Actions.Fetch.fetchComments(undefined); + if (comments.TAG === /* Ok */0) { + return Curry._1(dispatch, { + TAG: /* SetComments */0, + _0: comments._0 + }); + } else { + return Curry._1(dispatch, { + TAG: /* SetError */1, + _0: comments._0 + }); + } + } + catch (exn){ + return Curry._1(dispatch, { + TAG: /* SetError */1, + _0: /* FailedToSaveComment */1 + }); + } + }; + saveAndFetchComments(undefined); }; React.useEffect((function () { var fetchData = async function (param) { - var comments = await Actions.Api.fetchComments(undefined); - return Curry._1(setComments, (function (param) { - return comments; - })); + var comments = await Actions.Fetch.fetchComments(undefined); + if (comments.TAG === /* Ok */0) { + return Curry._1(dispatch, { + TAG: /* SetComments */0, + _0: comments._0 + }); + } else { + return Curry._1(dispatch, { + TAG: /* SetError */1, + _0: comments._0 + }); + } }; fetchData(undefined); }), []); @@ -88,11 +134,11 @@ function RescriptPage(props) { }), JsxRuntime.jsx(CommentForm.make, { storeComment: storeComment, - isSaving: match$2[0] + isSaving: state.isSaving }), JsxRuntime.jsx(CommentList.make, { - comments: match[0], - error: match$1[0] + comments: state.comments, + error: state.error }) ], className: "container" @@ -103,7 +149,12 @@ function RescriptPage(props) { var make = RescriptPage; +var $$default = RescriptPage; + export { + reducer , make , + $$default , + $$default as default, } /* react Not a pure module */ diff --git a/client/app/bundles/comments/src/RescriptPage.res b/client/app/bundles/comments/src/RescriptPage.res index 338ec971..43a3e29b 100644 --- a/client/app/bundles/comments/src/RescriptPage.res +++ b/client/app/bundles/comments/src/RescriptPage.res @@ -1,30 +1,66 @@ +type rescriptPageStateT = { + comments: Actions.Fetch.comments, + error: Types.errorT, + isSaving: Types.isSavingT +} + +type rescriptPageActionT = + | SetComments(Actions.Fetch.comments) + | SetError(Types.errorT) + | SetIsSaving(Types.isSavingT) + + +let reducer = ( + state: rescriptPageStateT, + action: rescriptPageActionT +): rescriptPageStateT => { + switch (action) { + | SetComments(comments) => {...state, comments} + | SetError(error) => {...state, error} + | SetIsSaving(isSaving) => {...state, isSaving} + }; +} + @react.component let make = () => { - let (comments, setComments) = React.useState(_ => ([] : Actions.Api.comments)); - let (error, setError) = React.useState(_ => false) - let (isSaving, setIsSaving) = React.useState(_ => false) + let (state, dispatch) = React.useReducer( + reducer, { + comments: ([]: Actions.Fetch.comments), + error: NoError, + isSaving: Free + } + ) let storeComment = (author, text) => { - setIsSaving(_ => true) - let _ = (async() => { + SetError(NoError)->dispatch + SetIsSaving(BusySaving)->dispatch + let saveAndFetchComments = async () => { try { - let _ = await Actions.Api.storeComment(author, text) - let comments = await Actions.Api.fetchComments() - setIsSaving(_ => false) - setComments(_ => comments) + let _ = await Actions.Create.storeComment({author, text}) + SetIsSaving(Free)->dispatch + + let comments = await Actions.Fetch.fetchComments() + switch comments { + | Ok(comments) => SetComments(comments)->dispatch + | Error(e) => SetError(e)->dispatch + } } catch { - | _ => setError(_ => true) + | _ => SetError(FailedToSaveComment)->dispatch } - })() + } + saveAndFetchComments()->ignore } React.useEffect1((_) => { let fetchData = async () => { - let comments = await Actions.Api.fetchComments(); - setComments(_ => comments); + let comments = await Actions.Fetch.fetchComments(); + switch comments { + | Ok(comments) => SetComments(comments)->dispatch + | Error(e) => SetError(e)->dispatch + } }; - let _ = fetchData(); + fetchData()->ignore None }, []) @@ -39,8 +75,10 @@ let make = () => {
  • {"Name is preserved. Text is reset, between submits"->React.string}
  • {"To see Action Cable instantly update two browsers, open two browsers and submit a comment!"->React.string}
  • - - + + } + +let default = make diff --git a/client/app/bundles/comments/src/bindings/Axios.res b/client/app/bundles/comments/src/bindings/Axios.res new file mode 100644 index 00000000..035fb91d --- /dev/null +++ b/client/app/bundles/comments/src/bindings/Axios.res @@ -0,0 +1,5 @@ +type reqOptions = { + responseType: string, + headers: {.} +} +@module("axios") external post: (string, Types.storeCommentDataT, reqOptions) => promise = "post"; diff --git a/client/app/bundles/comments/src/CSSTransition/CSSTransition.res b/client/app/bundles/comments/src/bindings/CSSAnimation.res similarity index 74% rename from client/app/bundles/comments/src/CSSTransition/CSSTransition.res rename to client/app/bundles/comments/src/bindings/CSSAnimation.res index 3e5f93c1..d84b327b 100644 --- a/client/app/bundles/comments/src/CSSTransition/CSSTransition.res +++ b/client/app/bundles/comments/src/bindings/CSSAnimation.res @@ -7,20 +7,20 @@ module TransitionGroup = { ) => React.element = "TransitionGroup" } -type cssTransitionGroupClassNamesT = { - enter: string, - enterActive: string, - exit: string, - exitActive: string -} - module CSSTransition = { + type t = { + enter: string, + enterActive: string, + exit: string, + exitActive: string + } + @react.component @module("react-transition-group") external make: ( ~children: React.element, ~key: string, ~timeout: int, ~nodeRef: React.ref>, - ~classNames: cssTransitionGroupClassNamesT + ~classNames: t ) => React.element = "CSSTransition" } diff --git a/client/app/bundles/comments/src/bindings/Marked.res b/client/app/bundles/comments/src/bindings/Marked.res new file mode 100644 index 00000000..b753f97f --- /dev/null +++ b/client/app/bundles/comments/src/bindings/Marked.res @@ -0,0 +1,4 @@ +type markedOptions = { + gfm: bool +} +@module("marked") external marked: (string, markedOptions) => string = "marked"; diff --git a/client/app/bundles/comments/src/bindings/ReactOnRails.res b/client/app/bundles/comments/src/bindings/ReactOnRails.res new file mode 100644 index 00000000..95d4e6eb --- /dev/null +++ b/client/app/bundles/comments/src/bindings/ReactOnRails.res @@ -0,0 +1,7 @@ +type rorDefault = { + authenticityHeaders: unit => {.} +} +type rorModule = { + default: rorDefault +} +@module("react-on-rails") external ror: rorModule = "default"; diff --git a/client/app/bundles/comments/src/vars.scss b/client/app/bundles/comments/src/vars.scss index 38cb5d9d..e3516f20 100644 --- a/client/app/bundles/comments/src/vars.scss +++ b/client/app/bundles/comments/src/vars.scss @@ -7,4 +7,4 @@ $font-family-sans-serif: 'OpenSans-Light'; // apply custom font // It will be used in SASS components imported as CSS Modules $comment-author-color: blue; -$comment-text-color: purple; \ No newline at end of file +$comment-text-color: purple; diff --git a/client/app/packs/client-bundle.js b/client/app/packs/client-bundle.js index 2a1d6c9e..8c084237 100644 --- a/client/app/packs/client-bundle.js +++ b/client/app/packs/client-bundle.js @@ -10,7 +10,7 @@ import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import Footer from '../bundles/comments/components/Footer/Footer'; -import { make as RescriptPage } from '../bundles/comments/src/RescriptPage.bs.mjs'; +import RescriptPage from '../bundles/comments/src/RescriptPage.bs.mjs'; import '../assets/styles/application'; diff --git a/client/app/packs/server-bundle.js b/client/app/packs/server-bundle.js index 2679927f..5ca9f613 100644 --- a/client/app/packs/server-bundle.js +++ b/client/app/packs/server-bundle.js @@ -8,7 +8,7 @@ import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import Footer from '../bundles/comments/components/Footer/Footer'; -import { make as RescriptPage } from '../bundles/comments/src/RescriptPage.bs.mjs'; +import RescriptPage from '../bundles/comments/src/RescriptPage.bs.mjs'; ReactOnRails.register({ App, diff --git a/spec/rescript/rescript_spec.rb b/spec/rescript/rescript_spec.rb index e5dc5f4c..af474d8c 100644 --- a/spec/rescript/rescript_spec.rb +++ b/spec/rescript/rescript_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" describe "with Rescript" do - describe "tabs change on click" do + describe "tabs change on click", :tabs_check do before do visit "/rescript" end @@ -13,17 +13,17 @@ end it "stops showing horizontal tab when other tab is clicked" do - click_link("Inline Form") + find("a", text: "Inline Form", wait: 10) page.has_no_css?("form-horizontal") end it "shows inline form when Inline Form link is clicked" do - click_link("Inline Form") + find("a", text: "Inline Form", wait: 10) page.has_css?("form-inline") end it "shows stacked form when Stacked Form link is clicked" do - click_link("Stacked Form") + find("a", text: "Stacked Form", wait: 10) page.has_no_css?("form-inline") and page.has_no_css?("form-horizontal") end end @@ -31,9 +31,7 @@ describe "form submission functions" do let(:comment) { Comment.new(author: "Author", text: "This is a comment") } let(:author_field) { "comment_author" } - let(:author_error) { "Author: can't be blank" } let(:text_field) { "comment_text" } - let(:text_error) { "Text: can't be blank" } before do visit "/rescript" From 67ea623ea47a50d2de3993254f9e3e3965ace180 Mon Sep 17 00:00:00 2001 From: yassa Date: Mon, 4 Sep 2023 13:04:55 +0300 Subject: [PATCH 06/30] Remove unused tag --- spec/rescript/rescript_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/rescript/rescript_spec.rb b/spec/rescript/rescript_spec.rb index af474d8c..3ae1db28 100644 --- a/spec/rescript/rescript_spec.rb +++ b/spec/rescript/rescript_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" describe "with Rescript" do - describe "tabs change on click", :tabs_check do + describe "tabs change on click" do before do visit "/rescript" end From 147f07ee3e714ba916d62bab6810e21d2bbb9aaf Mon Sep 17 00:00:00 2001 From: yassa Date: Mon, 4 Sep 2023 17:15:02 +0300 Subject: [PATCH 07/30] Add ROR binding --- bsconfig.json | 3 ++- package.json | 1 + yarn.lock | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bsconfig.json b/bsconfig.json index 3a0e8641..d5b04b94 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -21,7 +21,8 @@ "@rescript/react", "@rescript/core", "@glennsl/rescript-fetch", - "@glennsl/rescript-json-combinators" + "@glennsl/rescript-json-combinators", + "rescript-react-on-rails" ], "jsx": { "version": 4, diff --git a/package.json b/package.json index ac7e58af..51200119 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "redux": "^4.2.1", "redux-thunk": "^2.2.0", "rescript": "^10.1.4", + "rescript-react-on-rails": "^1.0.0", "resolve-url-loader": "^2.2.0", "sanitize-html": "^2.11.0", "sass": "^1.58.3", diff --git a/yarn.lock b/yarn.lock index 4c7e987e..ff00fdd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8238,6 +8238,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +rescript-react-on-rails@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rescript-react-on-rails/-/rescript-react-on-rails-1.0.0.tgz#700ae22fa5b749e15d058f7b9732db0c4864cc04" + integrity sha512-67NJeenJsMNvDTPQL1w9Tw2sGyt/4Ycfj9rqXmEhpye84R4iISJLAlgxyWKZp2boOqbpFo3X1Yf+wBHjDnO2BA== + rescript@^10.1.4: version "10.1.4" resolved "https://registry.yarnpkg.com/rescript/-/rescript-10.1.4.tgz#0f37710d371f32a704f17b4e804f66ce3c79a305" From a54627e3f9aa4025be62442d5028466d176a7816 Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 7 Sep 2023 15:55:01 +0300 Subject: [PATCH 08/30] Apply review requested changes --- .gitignore | 2 + app/views/pages/rescript.html.erb | 2 +- .../bundles/comments/src/Actions/Actions.res | 4 +- .../bundles/comments/src/Actions/Types.res | 24 +-- .../src/CommentForm/CommentForm.bs.mjs | 14 +- .../comments/src/CommentForm/CommentForm.res | 26 +-- .../src/CommentForm/forms/HorizontalForm.res | 2 +- .../src/CommentForm/forms/InlineForm.res | 2 +- .../src/CommentForm/forms/StackedFrom.res | 2 +- .../src/CommentList/AlertError/AlertError.res | 6 +- .../src/CommentList/Comment/Comment.res | 2 +- .../src/CommentList/CommentList.bs.mjs | 4 +- .../comments/src/CommentList/CommentList.res | 4 +- ...e.module.scss => ReScriptShow.module.scss} | 0 .../{RescriptPage.res => ReScriptShow.res} | 28 ++- .../bundles/comments/src/RescriptPage.bs.mjs | 160 ------------------ .../bundles/comments/src/bindings/Axios.res | 2 +- .../bundles/comments/src/bindings/Marked.res | 2 +- .../comments/src/bindings/ReactOnRails.res | 2 +- client/app/packs/client-bundle.js | 4 +- client/app/packs/server-bundle.js | 4 +- yarn.lock | 6 +- 22 files changed, 71 insertions(+), 231 deletions(-) rename client/app/bundles/comments/src/{RescriptPage.module.scss => ReScriptShow.module.scss} (100%) rename client/app/bundles/comments/src/{RescriptPage.res => ReScriptShow.res} (85%) delete mode 100644 client/app/bundles/comments/src/RescriptPage.bs.mjs diff --git a/.gitignore b/.gitignore index 9e31d6eb..65f61da3 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,5 @@ yarn-debug.log* .yarn-integrity lib/bs + +client/app/bundles/comments/src/**/*.bs.mjs diff --git a/app/views/pages/rescript.html.erb b/app/views/pages/rescript.html.erb index c6630d13..c218d5cf 100644 --- a/app/views/pages/rescript.html.erb +++ b/app/views/pages/rescript.html.erb @@ -1 +1 @@ -<%= react_component "RescriptPage" %> +<%= react_component "RescriptShow", prerender: false %> diff --git a/client/app/bundles/comments/src/Actions/Actions.res b/client/app/bundles/comments/src/Actions/Actions.res index f1c92437..758e0e90 100644 --- a/client/app/bundles/comments/src/Actions/Actions.res +++ b/client/app/bundles/comments/src/Actions/Actions.res @@ -32,8 +32,8 @@ module Fetch = { comments: comments } - let fetchComments = async (): result => { - open Json.Decode; + let fetchComments = async (): result => { + open Json.Decode let response = await Fetch.get("comments.json") let jsonRes = await response->Fetch.Response.json diff --git a/client/app/bundles/comments/src/Actions/Types.res b/client/app/bundles/comments/src/Actions/Types.res index 97e574eb..763ce738 100644 --- a/client/app/bundles/comments/src/Actions/Types.res +++ b/client/app/bundles/comments/src/Actions/Types.res @@ -1,28 +1,28 @@ -type formDisplayT = HorizontalForm | InlineForm | StackedFrom; +type formDisplay = Horizontal | Inline | Stacked -type commentFormStateT = { +type commentFormState = { author: string, text: string, - form: formDisplayT + form: formDisplay } -type commentFormActionT = +type commentFormAction = | SetAuthor(string) | SetText(string) - | SetFormType(formDisplayT); + | SetFormType(formDisplay) -type formDataT = { +type formData = { formName: string, - formType: formDisplayT -}; + formType: formDisplay +} -type storeCommentActionT = (string, string) => unit; +type storeCommentAction = (string, string) => unit -type storeCommentDataT = { +type storeCommentData = { author: string, text: string } -type errorT = NoError | FailedToSaveComment | FailedToFetchComments; +type error = NoError | FailedToSaveComment | FailedToFetchComments -type isSavingT = Free | BusySaving; +type isSaving = Free | BusySaving diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs index 2fa22824..9111eeec 100644 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs @@ -41,7 +41,7 @@ function CommentForm(props) { var match = React.useReducer(reducer, { author: "", text: "", - form: /* HorizontalForm */0 + form: /* Horizontal */0 }); var dispatch = match[1]; var state = match[0]; @@ -66,21 +66,21 @@ function CommentForm(props) { var forms = [ { formName: "Horizontal Form", - formType: /* HorizontalForm */0 + formType: /* Horizontal */0 }, { formName: "Inline Form", - formType: /* InlineForm */1 + formType: /* Inline */1 }, { formName: "Stacked Form", - formType: /* StackedFrom */2 + formType: /* Stacked */2 } ]; var match$1 = state.form; var tmp; switch (match$1) { - case /* HorizontalForm */0 : + case /* Horizontal */0 : tmp = JsxRuntime.jsx(HorizontalForm.make, { author: state.author, handleAuthorChange: handleAuthorChange, @@ -90,7 +90,7 @@ function CommentForm(props) { isSaving: isSaving }); break; - case /* InlineForm */1 : + case /* Inline */1 : tmp = JsxRuntime.jsx(InlineForm.make, { author: state.author, handleAuthorChange: handleAuthorChange, @@ -100,7 +100,7 @@ function CommentForm(props) { isSaving: isSaving }); break; - case /* StackedFrom */2 : + case /* Stacked */2 : tmp = JsxRuntime.jsx(StackedFrom.make, { author: state.author, handleAuthorChange: handleAuthorChange, diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.res b/client/app/bundles/comments/src/CommentForm/CommentForm.res index db3997c3..41d21330 100644 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.res @@ -1,24 +1,24 @@ @module("./CommentForm.module.scss") external css: {..} = "default" let reducer = ( - state: Types.commentFormStateT, - action: Types.commentFormActionT -): Types.commentFormStateT => { + state: Types.commentFormState, + action: Types.commentFormAction +): Types.commentFormState => { switch (action) { | SetAuthor(author) => {...state, author} | SetText(text) => {...state, text} | SetFormType(form) => {...state, form: form} - }; + } } @react.component -let make = (~storeComment: Types.storeCommentActionT, ~isSaving: Types.isSavingT) => { +let make = (~storeComment: Types.storeCommentAction, ~isSaving: Types.isSaving) => { let (state, dispatch) = React.useReducer( reducer, { author: "", text: "", - form: HorizontalForm + form: Horizontal } ) @@ -37,11 +37,11 @@ let make = (~storeComment: Types.storeCommentActionT, ~isSaving: Types.isSavingT storeComment(state.author, state.text) } - let forms: array = + let forms: array = [ - {formName: "Horizontal Form", formType: HorizontalForm}, - {formName: "Inline Form", formType: InlineForm}, - {formName: "Stacked Form", formType: StackedFrom} + {formName: "Horizontal Form", formType: Horizontal}, + {formName: "Inline Form", formType: Inline}, + {formName: "Stacked Form", formType: Stacked} ]
    @@ -65,7 +65,7 @@ let make = (~storeComment: Types.storeCommentActionT, ~isSaving: Types.isSavingT
    { switch state.form { - | HorizontalForm + | Horizontal => - | StackedFrom + | Stacked => - | InlineForm + | Inline => {
    diff --git a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res index 256225fd..f6f2b601 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res +++ b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res @@ -5,7 +5,7 @@ let make = ( ~text, ~handleTextChange, ~handleSubmit, - ~isSaving: Types.isSavingT + ~isSaving: Types.isSaving ) => {
    diff --git a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res index 1b95a16f..54c558fb 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res +++ b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res @@ -5,7 +5,7 @@ let make = ( ~text, ~handleTextChange, ~handleSubmit, - ~isSaving: Types.isSavingT + ~isSaving: Types.isSaving ) => {
    diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res index c77050f5..ef9a7e6f 100644 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res @@ -1,11 +1,11 @@ @react.component -let make = (~cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t, ~error: Types.errorT) => { +let make = (~cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t, ~error: Types.error) => { let nodeRef = React.useRef(Js.Nullable.null) switch error { | FailedToSaveComment => // The 500 must correspond to the 0.5s in: - // ../../RescriptPage.module.scss:9 + // ../../RescriptShow.module.scss:9 | FailedToFetchComments => // The 500 must correspond to the 0.5s in: - // ../../RescriptPage.module.scss:9 + // ../../RescriptShow.module.scss:9 { let nodeRef = React.useRef(Js.Nullable.null) // The 500 must correspond to the 0.5s in: - // ../../RescriptPage.module.scss:9 + // ../../RescriptShow.module.scss:9 { +let make = (~comments: Actions.Fetch.comments, ~error: Types.error) => { let cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t = { enter: css["elementEnter"], enterActive: css["elementEnterActive"], diff --git a/client/app/bundles/comments/src/RescriptPage.module.scss b/client/app/bundles/comments/src/ReScriptShow.module.scss similarity index 100% rename from client/app/bundles/comments/src/RescriptPage.module.scss rename to client/app/bundles/comments/src/ReScriptShow.module.scss diff --git a/client/app/bundles/comments/src/RescriptPage.res b/client/app/bundles/comments/src/ReScriptShow.res similarity index 85% rename from client/app/bundles/comments/src/RescriptPage.res rename to client/app/bundles/comments/src/ReScriptShow.res index 43a3e29b..6ab815cb 100644 --- a/client/app/bundles/comments/src/RescriptPage.res +++ b/client/app/bundles/comments/src/ReScriptShow.res @@ -1,28 +1,28 @@ -type rescriptPageStateT = { +type state = { comments: Actions.Fetch.comments, - error: Types.errorT, - isSaving: Types.isSavingT + error: Types.error, + isSaving: Types.isSaving } -type rescriptPageActionT = +type action = | SetComments(Actions.Fetch.comments) - | SetError(Types.errorT) - | SetIsSaving(Types.isSavingT) + | SetError(Types.error) + | SetIsSaving(Types.isSaving) let reducer = ( - state: rescriptPageStateT, - action: rescriptPageActionT -): rescriptPageStateT => { + state: state, + action: action +): state => { switch (action) { | SetComments(comments) => {...state, comments} | SetError(error) => {...state, error} | SetIsSaving(isSaving) => {...state, isSaving} - }; + } } @react.component -let make = () => { +let default = () => { let (state, dispatch) = React.useReducer( reducer, { comments: ([]: Actions.Fetch.comments), @@ -53,12 +53,12 @@ let make = () => { React.useEffect1((_) => { let fetchData = async () => { - let comments = await Actions.Fetch.fetchComments(); + let comments = await Actions.Fetch.fetchComments() switch comments { | Ok(comments) => SetComments(comments)->dispatch | Error(e) => SetError(e)->dispatch } - }; + } fetchData()->ignore None @@ -80,5 +80,3 @@ let make = () => {
    } - -let default = make diff --git a/client/app/bundles/comments/src/RescriptPage.bs.mjs b/client/app/bundles/comments/src/RescriptPage.bs.mjs deleted file mode 100644 index 1db680f5..00000000 --- a/client/app/bundles/comments/src/RescriptPage.bs.mjs +++ /dev/null @@ -1,160 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Curry from "rescript/lib/es6/curry.js"; -import * as React from "react"; -import * as Header from "./Header/Header.bs.mjs"; -import * as Actions from "./Actions/Actions.bs.mjs"; -import * as CommentForm from "./CommentForm/CommentForm.bs.mjs"; -import * as CommentList from "./CommentList/CommentList.bs.mjs"; -import * as JsxRuntime from "react/jsx-runtime"; - -function reducer(state, action) { - switch (action.TAG | 0) { - case /* SetComments */0 : - return { - comments: action._0, - error: state.error, - isSaving: state.isSaving - }; - case /* SetError */1 : - return { - comments: state.comments, - error: action._0, - isSaving: state.isSaving - }; - case /* SetIsSaving */2 : - return { - comments: state.comments, - error: state.error, - isSaving: action._0 - }; - - } -} - -function RescriptPage(props) { - var match = React.useReducer(reducer, { - comments: [], - error: /* NoError */0, - isSaving: /* Free */0 - }); - var dispatch = match[1]; - var state = match[0]; - var storeComment = function (author, text) { - Curry._1(dispatch, { - TAG: /* SetError */1, - _0: /* NoError */0 - }); - Curry._1(dispatch, { - TAG: /* SetIsSaving */2, - _0: /* BusySaving */1 - }); - var saveAndFetchComments = async function (param) { - try { - await Actions.Create.storeComment({ - author: author, - text: text - }); - Curry._1(dispatch, { - TAG: /* SetIsSaving */2, - _0: /* Free */0 - }); - var comments = await Actions.Fetch.fetchComments(undefined); - if (comments.TAG === /* Ok */0) { - return Curry._1(dispatch, { - TAG: /* SetComments */0, - _0: comments._0 - }); - } else { - return Curry._1(dispatch, { - TAG: /* SetError */1, - _0: comments._0 - }); - } - } - catch (exn){ - return Curry._1(dispatch, { - TAG: /* SetError */1, - _0: /* FailedToSaveComment */1 - }); - } - }; - saveAndFetchComments(undefined); - }; - React.useEffect((function () { - var fetchData = async function (param) { - var comments = await Actions.Fetch.fetchComments(undefined); - if (comments.TAG === /* Ok */0) { - return Curry._1(dispatch, { - TAG: /* SetComments */0, - _0: comments._0 - }); - } else { - return Curry._1(dispatch, { - TAG: /* SetError */1, - _0: comments._0 - }); - } - }; - fetchData(undefined); - }), []); - return JsxRuntime.jsxs(JsxRuntime.Fragment, { - children: [ - JsxRuntime.jsxs("h2", { - children: [ - "Rescript + Rails Backend (with ", - JsxRuntime.jsx("a", { - children: "react_on_rails gem", - href: "https://github.com/shakacode/react_on_rails" - }), - ")" - ] - }), - JsxRuntime.jsx(Header.make, {}), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("h2", { - children: "Comments" - }), - JsxRuntime.jsxs("ul", { - children: [ - JsxRuntime.jsx("li", { - children: "Text supports Github Flavored Markdown." - }), - JsxRuntime.jsx("li", { - children: "Comments older than 24 hours are deleted." - }), - JsxRuntime.jsx("li", { - children: "Name is preserved. Text is reset, between submits" - }), - JsxRuntime.jsx("li", { - children: "To see Action Cable instantly update two browsers, open two browsers and submit a comment!" - }) - ] - }), - JsxRuntime.jsx(CommentForm.make, { - storeComment: storeComment, - isSaving: state.isSaving - }), - JsxRuntime.jsx(CommentList.make, { - comments: state.comments, - error: state.error - }) - ], - className: "container" - }) - ] - }); -} - -var make = RescriptPage; - -var $$default = RescriptPage; - -export { - reducer , - make , - $$default , - $$default as default, -} -/* react Not a pure module */ diff --git a/client/app/bundles/comments/src/bindings/Axios.res b/client/app/bundles/comments/src/bindings/Axios.res index 035fb91d..2d23cd55 100644 --- a/client/app/bundles/comments/src/bindings/Axios.res +++ b/client/app/bundles/comments/src/bindings/Axios.res @@ -2,4 +2,4 @@ type reqOptions = { responseType: string, headers: {.} } -@module("axios") external post: (string, Types.storeCommentDataT, reqOptions) => promise = "post"; +@module("axios") external post: (string, Types.storeCommentData, reqOptions) => promise = "post" diff --git a/client/app/bundles/comments/src/bindings/Marked.res b/client/app/bundles/comments/src/bindings/Marked.res index b753f97f..2a16a279 100644 --- a/client/app/bundles/comments/src/bindings/Marked.res +++ b/client/app/bundles/comments/src/bindings/Marked.res @@ -1,4 +1,4 @@ type markedOptions = { gfm: bool } -@module("marked") external marked: (string, markedOptions) => string = "marked"; +@module("marked") external marked: (string, markedOptions) => string = "marked" diff --git a/client/app/bundles/comments/src/bindings/ReactOnRails.res b/client/app/bundles/comments/src/bindings/ReactOnRails.res index 95d4e6eb..29d158ff 100644 --- a/client/app/bundles/comments/src/bindings/ReactOnRails.res +++ b/client/app/bundles/comments/src/bindings/ReactOnRails.res @@ -4,4 +4,4 @@ type rorDefault = { type rorModule = { default: rorDefault } -@module("react-on-rails") external ror: rorModule = "default"; +@module("react-on-rails") external ror: rorModule = "default" diff --git a/client/app/packs/client-bundle.js b/client/app/packs/client-bundle.js index 8c084237..be7d0a2c 100644 --- a/client/app/packs/client-bundle.js +++ b/client/app/packs/client-bundle.js @@ -10,7 +10,7 @@ import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import Footer from '../bundles/comments/components/Footer/Footer'; -import RescriptPage from '../bundles/comments/src/RescriptPage.bs.mjs'; +import RescriptShow from '../bundles/comments/src/ReScriptShow.bs.mjs'; import '../assets/styles/application'; @@ -26,7 +26,7 @@ ReactOnRails.register({ NavigationBarApp, SimpleCommentScreen, Footer, - RescriptPage, + RescriptShow, }); ReactOnRails.registerStore({ diff --git a/client/app/packs/server-bundle.js b/client/app/packs/server-bundle.js index 5ca9f613..98cef523 100644 --- a/client/app/packs/server-bundle.js +++ b/client/app/packs/server-bundle.js @@ -8,7 +8,7 @@ import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import Footer from '../bundles/comments/components/Footer/Footer'; -import RescriptPage from '../bundles/comments/src/RescriptPage.bs.mjs'; +import RescriptShow from '../bundles/comments/src/ReScriptShow.bs.mjs'; ReactOnRails.register({ App, @@ -16,7 +16,7 @@ ReactOnRails.register({ NavigationBarApp, SimpleCommentScreen, Footer, - RescriptPage, + RescriptShow, }); ReactOnRails.registerStore({ diff --git a/yarn.lock b/yarn.lock index ff00fdd8..9a9754f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8239,9 +8239,9 @@ requires-port@^1.0.0: integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== rescript-react-on-rails@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rescript-react-on-rails/-/rescript-react-on-rails-1.0.0.tgz#700ae22fa5b749e15d058f7b9732db0c4864cc04" - integrity sha512-67NJeenJsMNvDTPQL1w9Tw2sGyt/4Ycfj9rqXmEhpye84R4iISJLAlgxyWKZp2boOqbpFo3X1Yf+wBHjDnO2BA== + version "1.0.1" + resolved "https://registry.yarnpkg.com/rescript-react-on-rails/-/rescript-react-on-rails-1.0.1.tgz#541dffdae64ec5053a50a3792b9db8783c959d1b" + integrity sha512-sbkDNCoiEWM9rqIiu+4joAj6W92yhM64KtLZQYfvYYm578jMcG02d98xpDeBT7MxZoPZZggFIed0m6Dj8bbDYA== rescript@^10.1.4: version "10.1.4" From b3ad543f7d17f2cfd69428e19e4d937d760b5758 Mon Sep 17 00:00:00 2001 From: yassa Date: Fri, 8 Sep 2023 17:23:49 +0300 Subject: [PATCH 09/30] remove action js file --- .../comments/src/Actions/Actions.bs.mjs | 60 ------------------- 1 file changed, 60 deletions(-) delete mode 100644 client/app/bundles/comments/src/Actions/Actions.bs.mjs diff --git a/client/app/bundles/comments/src/Actions/Actions.bs.mjs b/client/app/bundles/comments/src/Actions/Actions.bs.mjs deleted file mode 100644 index a83373f6..00000000 --- a/client/app/bundles/comments/src/Actions/Actions.bs.mjs +++ /dev/null @@ -1,60 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Curry from "rescript/lib/es6/curry.js"; -import * as Axios from "axios"; -import ReactOnRails from "react-on-rails"; -import * as Json$JsonCombinators from "@glennsl/rescript-json-combinators/src/Json.bs.mjs"; -import * as Json_Decode$JsonCombinators from "@glennsl/rescript-json-combinators/src/Json_Decode.bs.mjs"; - -async function storeComment(comment) { - await Axios.post("comments.json", { - author: comment.author, - text: comment.text - }, { - responseType: "json", - headers: Curry._1(ReactOnRails.default.authenticityHeaders, undefined) - }); -} - -var Create = { - storeComment: storeComment -}; - -async function fetchComments(param) { - var response = await fetch("comments.json"); - var jsonRes = await response.json(); - var jsonComment = Json_Decode$JsonCombinators.object(function (field) { - return { - author: field.required("author", Json_Decode$JsonCombinators.string), - text: field.required("text", Json_Decode$JsonCombinators.string), - id: field.required("id", Json_Decode$JsonCombinators.$$int) - }; - }); - var jsonComments = Json_Decode$JsonCombinators.object(function (field) { - return { - comments: field.required("comments", Json_Decode$JsonCombinators.array(jsonComment)) - }; - }); - var decodedRes = Json$JsonCombinators.decode(jsonRes, jsonComments); - if (decodedRes.TAG === /* Ok */0) { - return { - TAG: /* Ok */0, - _0: decodedRes._0.comments - }; - } else { - return { - TAG: /* Error */1, - _0: /* FailedToFetchComments */2 - }; - } -} - -var Fetch = { - fetchComments: fetchComments -}; - -export { - Create , - Fetch , -} -/* axios Not a pure module */ From 0b62d785a37ec5e5944167fab97c857d3fe3ff83 Mon Sep 17 00:00:00 2001 From: yassa Date: Fri, 8 Sep 2023 17:31:31 +0300 Subject: [PATCH 10/30] Remove .mjs files --- .../bundles/comments/src/Actions/Types.bs.mjs | 2 - .../src/CommentForm/CommentForm.bs.mjs | 151 ------------------ .../CommentForm/forms/HorizontalForm.bs.mjs | 79 --------- .../src/CommentForm/forms/InlineForm.bs.mjs | 66 -------- .../src/CommentForm/forms/StackedFrom.bs.mjs | 65 -------- .../CommentList/AlertError/AlertError.bs.mjs | 30 ---- .../src/CommentList/Comment/Comment.bs.mjs | 47 ------ .../src/CommentList/CommentList.bs.mjs | 49 ------ .../bundles/comments/src/Header/Header.bs.mjs | 92 ----------- .../comments/src/bindings/Axios.bs.mjs | 2 - .../comments/src/bindings/CSSAnimation.bs.mjs | 12 -- .../comments/src/bindings/Marked.bs.mjs | 2 - .../comments/src/bindings/ReactOnRails.bs.mjs | 2 - 13 files changed, 599 deletions(-) delete mode 100644 client/app/bundles/comments/src/Actions/Types.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs delete mode 100644 client/app/bundles/comments/src/CommentList/CommentList.bs.mjs delete mode 100644 client/app/bundles/comments/src/Header/Header.bs.mjs delete mode 100644 client/app/bundles/comments/src/bindings/Axios.bs.mjs delete mode 100644 client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs delete mode 100644 client/app/bundles/comments/src/bindings/Marked.bs.mjs delete mode 100644 client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs diff --git a/client/app/bundles/comments/src/Actions/Types.bs.mjs b/client/app/bundles/comments/src/Actions/Types.bs.mjs deleted file mode 100644 index d856702b..00000000 --- a/client/app/bundles/comments/src/Actions/Types.bs.mjs +++ /dev/null @@ -1,2 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs deleted file mode 100644 index 9111eeec..00000000 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.bs.mjs +++ /dev/null @@ -1,151 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Curry from "rescript/lib/es6/curry.js"; -import * as React from "react"; -import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; -import * as InlineForm from "./forms/InlineForm.bs.mjs"; -import * as StackedFrom from "./forms/StackedFrom.bs.mjs"; -import * as HorizontalForm from "./forms/HorizontalForm.bs.mjs"; -import * as JsxRuntime from "react/jsx-runtime"; -import CommentFormModuleScss from "./CommentForm.module.scss"; - -var css = CommentFormModuleScss; - -function reducer(state, action) { - switch (action.TAG | 0) { - case /* SetAuthor */0 : - return { - author: action._0, - text: state.text, - form: state.form - }; - case /* SetText */1 : - return { - author: state.author, - text: action._0, - form: state.form - }; - case /* SetFormType */2 : - return { - author: state.author, - text: state.text, - form: action._0 - }; - - } -} - -function CommentForm(props) { - var isSaving = props.isSaving; - var storeComment = props.storeComment; - var match = React.useReducer(reducer, { - author: "", - text: "", - form: /* Horizontal */0 - }); - var dispatch = match[1]; - var state = match[0]; - var handleAuthorChange = function ($$event) { - var value = $$event.currentTarget.value; - Curry._1(dispatch, { - TAG: /* SetAuthor */0, - _0: value - }); - }; - var handleTextChange = function ($$event) { - var value = $$event.currentTarget.value; - Curry._1(dispatch, { - TAG: /* SetText */1, - _0: value - }); - }; - var handleSubmit = function ($$event) { - $$event.preventDefault(); - Curry._2(storeComment, state.author, state.text); - }; - var forms = [ - { - formName: "Horizontal Form", - formType: /* Horizontal */0 - }, - { - formName: "Inline Form", - formType: /* Inline */1 - }, - { - formName: "Stacked Form", - formType: /* Stacked */2 - } - ]; - var match$1 = state.form; - var tmp; - switch (match$1) { - case /* Horizontal */0 : - tmp = JsxRuntime.jsx(HorizontalForm.make, { - author: state.author, - handleAuthorChange: handleAuthorChange, - text: state.text, - handleTextChange: handleTextChange, - handleSubmit: handleSubmit, - isSaving: isSaving - }); - break; - case /* Inline */1 : - tmp = JsxRuntime.jsx(InlineForm.make, { - author: state.author, - handleAuthorChange: handleAuthorChange, - text: state.text, - handleTextChange: handleTextChange, - handleSubmit: handleSubmit, - isSaving: isSaving - }); - break; - case /* Stacked */2 : - tmp = JsxRuntime.jsx(StackedFrom.make, { - author: state.author, - handleAuthorChange: handleAuthorChange, - text: state.text, - handleTextChange: handleTextChange, - handleSubmit: handleSubmit, - isSaving: isSaving - }); - break; - - } - return JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("ul", { - children: Belt_Array.map(forms, (function (form) { - return JsxRuntime.jsx("li", { - children: JsxRuntime.jsx("a", { - children: form.formName, - className: css.anchorButton - }), - className: "nav-item " + ( - state.form === form.formType ? "active" : "" - ), - role: "presentation", - onClick: (function ($$event) { - Curry._1(dispatch, { - TAG: /* SetFormType */2, - _0: form.formType - }); - }) - }, "form_" + form.formName); - })), - className: "nav nav-pills" - }), - JsxRuntime.jsx("hr", {}), - tmp - ] - }); -} - -var make = CommentForm; - -export { - css , - reducer , - make , -} -/* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs deleted file mode 100644 index c013deff..00000000 --- a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.bs.mjs +++ /dev/null @@ -1,79 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JsxRuntime from "react/jsx-runtime"; - -function HorizontalForm(props) { - return JsxRuntime.jsxs("form", { - children: [ - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("label", { - children: "Name", - className: "form-label pull-right" - }), - className: "col-sm-2" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "form-control", - id: "comment_author", - name: "comment_author", - placeholder: "Your Name", - type: "text", - value: props.author, - onChange: props.handleAuthorChange - }), - className: "col-sm-10" - }) - ], - className: "form-group" - }), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("label", { - children: "Text", - className: "form-label pull-right" - }), - className: "col-sm-2" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "form-control", - id: "comment_text", - name: "comment_text", - placeholder: "Say something using markdown...", - type: "text", - value: props.text, - onChange: props.handleTextChange - }), - className: "col-sm-10" - }) - ], - className: "form-group" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "btn btn-primary", - type: "submit", - value: "Post" - }), - className: "col-sm-10 col-sm-offset-2" - }), - className: "form-group" - }) - ], - className: "form-horizontal", - disabled: props.isSaving === /* BusySaving */1, - onSubmit: props.handleSubmit - }); -} - -var make = HorizontalForm; - -export { - make , -} -/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs deleted file mode 100644 index 6adaad89..00000000 --- a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.bs.mjs +++ /dev/null @@ -1,66 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JsxRuntime from "react/jsx-runtime"; - -function InlineForm(props) { - var handleSubmit = props.handleSubmit; - return JsxRuntime.jsxs("form", { - children: [ - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Name", - className: "form-label mr-15" - }), - JsxRuntime.jsx("input", { - className: "form-control", - id: "comment_author", - name: "comment_author", - placeholder: "Your Name", - type: "text", - value: props.author, - onChange: props.handleAuthorChange - }) - ], - className: "form-group" - }), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Text", - className: "form-label mr-15" - }), - JsxRuntime.jsx("input", { - className: "form-control w-50", - id: "comment_text", - name: "comment_text", - placeholder: "Say something using markdown...", - type: "text", - value: props.text, - onChange: props.handleTextChange - }) - ], - className: "form-group ml-15 mr-15" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "btn btn-primary", - type: "submit", - value: "Post", - onSubmit: handleSubmit - }), - className: "form-group" - }) - ], - className: "form-inline", - disabled: props.isSaving === /* BusySaving */1, - onSubmit: handleSubmit - }); -} - -var make = InlineForm; - -export { - make , -} -/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs deleted file mode 100644 index 07c196cc..00000000 --- a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.bs.mjs +++ /dev/null @@ -1,65 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JsxRuntime from "react/jsx-runtime"; - -function StackedFrom(props) { - var handleSubmit = props.handleSubmit; - return JsxRuntime.jsxs("form", { - children: [ - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Name", - className: "form-label" - }), - JsxRuntime.jsx("input", { - className: "form-control", - id: "comment_author", - name: "comment_author", - placeholder: "Your Name", - type: "text", - value: props.author, - onChange: props.handleAuthorChange - }) - ], - className: "form-group" - }), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("label", { - children: "Name", - className: "form-label" - }), - JsxRuntime.jsx("input", { - className: "form-control", - id: "comment_text", - name: "comment_text", - placeholder: "Say something using markdown...", - type: "text", - value: props.text, - onChange: props.handleTextChange - }) - ], - className: "form-group" - }), - JsxRuntime.jsx("div", { - children: JsxRuntime.jsx("input", { - className: "btn btn-primary", - type: "submit", - value: "Post", - onSubmit: handleSubmit - }), - className: "form-group" - }) - ], - disabled: props.isSaving === /* BusySaving */1, - onSubmit: handleSubmit - }); -} - -var make = StackedFrom; - -export { - make , -} -/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs deleted file mode 100644 index d7999652..00000000 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.bs.mjs +++ /dev/null @@ -1,30 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as React from 'react'; -import * as JsxRuntime from 'react/jsx-runtime'; -import * as ReactTransitionGroup from 'react-transition-group'; - -function AlertError(props) { - var cssTransitionGroupClassNames = props.cssTransitionGroupClassNames; - var nodeRef = React.useRef(null); - return JsxRuntime.jsx( - ReactTransitionGroup.CSSTransition, - { - children: JsxRuntime.jsx('div', { - children: JsxRuntime.jsx('strong', { - children: 'Your comment was not saved!', - }), - className: 'alert alert-danger', - }), - timeout: 500, - nodeRef: nodeRef, - classNames: props.cssTransitionGroupClassNames, - }, - 'commentFetchError', - ); -} - -var make = AlertError; - -export { make }; -/* react Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs b/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs deleted file mode 100644 index 1bbb8b55..00000000 --- a/client/app/bundles/comments/src/CommentList/Comment/Comment.bs.mjs +++ /dev/null @@ -1,47 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as React from "react"; -import * as Marked from "marked"; -import * as Caml_option from "rescript/lib/es6/caml_option.js"; -import * as JsxRuntime from "react/jsx-runtime"; -import CommentModuleScss from "./Comment.module.scss"; -import * as ReactTransitionGroup from "react-transition-group"; - -var css = CommentModuleScss; - -function $$Comment(props) { - var comment = props.comment; - var rawMarkup = Marked.marked(comment.text, { - gfm: true - }); - var innerHTML = { - __html: rawMarkup - }; - var nodeRef = React.useRef(null); - return JsxRuntime.jsx(ReactTransitionGroup.CSSTransition, { - children: JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("h2", { - children: comment.author, - className: css.commentAuthor - }), - JsxRuntime.jsx("span", { - dangerouslySetInnerHTML: Caml_option.some(innerHTML) - }) - ], - ref: Caml_option.some(nodeRef), - className: css.comment - }), - timeout: 500, - nodeRef: nodeRef, - classNames: props.cssTransitionGroupClassNames - }, "component_" + String(comment.id)); -} - -var make = $$Comment; - -export { - css , - make , -} -/* css Not a pure module */ diff --git a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs b/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs deleted file mode 100644 index 85a2bc48..00000000 --- a/client/app/bundles/comments/src/CommentList/CommentList.bs.mjs +++ /dev/null @@ -1,49 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as $$Comment from "./Comment/Comment.bs.mjs"; -import * as AlertError from "./AlertError/AlertError.bs.mjs"; -import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; -import * as JsxRuntime from "react/jsx-runtime"; -import * as ReactTransitionGroup from "react-transition-group"; -import RescriptShowModuleScss from "../RescriptShow.module.scss"; - -var css = RescriptShowModuleScss; - -function CommentList(props) { - var cssTransitionGroupClassNames_enter = css.elementEnter; - var cssTransitionGroupClassNames_enterActive = css.elementEnterActive; - var cssTransitionGroupClassNames_exit = css.elementLeave; - var cssTransitionGroupClassNames_exitActive = css.elementLeaveActive; - var cssTransitionGroupClassNames = { - enter: cssTransitionGroupClassNames_enter, - enterActive: cssTransitionGroupClassNames_enterActive, - exit: cssTransitionGroupClassNames_exit, - exitActive: cssTransitionGroupClassNames_exitActive - }; - return JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx(AlertError.make, { - cssTransitionGroupClassNames: cssTransitionGroupClassNames, - error: props.error - }), - JsxRuntime.jsx(ReactTransitionGroup.TransitionGroup, { - children: Belt_Array.map(props.comments, (function (comment) { - return JsxRuntime.jsx($$Comment.make, { - comment: comment, - cssTransitionGroupClassNames: cssTransitionGroupClassNames - }, "comment_" + String(comment.id)); - })), - className: "commentList", - component: "div" - }) - ] - }); -} - -var make = CommentList; - -export { - css , - make , -} -/* css Not a pure module */ diff --git a/client/app/bundles/comments/src/Header/Header.bs.mjs b/client/app/bundles/comments/src/Header/Header.bs.mjs deleted file mode 100644 index 5fe7b1d6..00000000 --- a/client/app/bundles/comments/src/Header/Header.bs.mjs +++ /dev/null @@ -1,92 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JsxRuntime from "react/jsx-runtime"; - -function Header(props) { - return JsxRuntime.jsxs(JsxRuntime.Fragment, { - children: [ - JsxRuntime.jsxs("ul", { - children: [ - JsxRuntime.jsxs("li", { - children: [ - JsxRuntime.jsx("a", { - children: "Can ShakaCode Help You? ", - href: "https://blog.shakacode.com/can-shakacode-help-you-4a5b1e5a8a63#.jex6tg9w9" - }), - "We're actively seeking new projects with React, React-Native, or Ruby on Rails." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "See the ", - JsxRuntime.jsx("a", { - children: "github.com/shakacode/react-webpack-rails-tutorial/README.md ", - href: "https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/README.md" - }), - "for details of how this example site was built." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "Read ", - JsxRuntime.jsx("a", { - children: "Documentation for React on Rails", - href: "https://shakacode.gitbooks.io/react-on-rails/content/" - }), - JsxRuntime.jsx("a", { - children: "The React on Rails Doctrine.", - href: "https://www.shakacode.com/blog/the-react-on-rails-doctrine" - }) - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "See our React Native Client: ", - JsxRuntime.jsx("a", { - children: "shakacode/react-native-tutorial", - href: "https://github.com/shakacode/react-native-tutorial" - }), - "." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "Watch the ", - JsxRuntime.jsx("a", { - children: "React On Rails Tutorial Series", - href: "https://www.youtube.com/playlist?list=PL5VAKH-U1M6dj84BApfUtvBjvF-0-JfEU" - }), - "." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - JsxRuntime.jsx("a", { - children: "ShakaCode", - href: "http://www.shakacode.com" - }), - " is doing support for React on Rails, \ - including a private Slack channel, \ - source code reviews, and pair programming sessions. ", - JsxRuntime.jsx("b", { - children: JsxRuntime.jsx("a", { - children: "Click here", - href: "http://www.shakacode.com/work/index.html" - }) - }), - " for more information." - ] - }) - ] - }), - JsxRuntime.jsx("hr", {}) - ] - }); -} - -var make = Header; - -export { - make , -} -/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/bindings/Axios.bs.mjs b/client/app/bundles/comments/src/bindings/Axios.bs.mjs deleted file mode 100644 index d856702b..00000000 --- a/client/app/bundles/comments/src/bindings/Axios.bs.mjs +++ /dev/null @@ -1,2 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs b/client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs deleted file mode 100644 index 455b477e..00000000 --- a/client/app/bundles/comments/src/bindings/CSSAnimation.bs.mjs +++ /dev/null @@ -1,12 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - - -var TransitionGroup = {}; - -var CSSTransition = {}; - -export { - TransitionGroup , - CSSTransition , -} -/* No side effect */ diff --git a/client/app/bundles/comments/src/bindings/Marked.bs.mjs b/client/app/bundles/comments/src/bindings/Marked.bs.mjs deleted file mode 100644 index d856702b..00000000 --- a/client/app/bundles/comments/src/bindings/Marked.bs.mjs +++ /dev/null @@ -1,2 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ diff --git a/client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs b/client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs deleted file mode 100644 index d856702b..00000000 --- a/client/app/bundles/comments/src/bindings/ReactOnRails.bs.mjs +++ /dev/null @@ -1,2 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE -/* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */ From 51a41d9dd5ded159e6abca994062930eb4508db2 Mon Sep 17 00:00:00 2001 From: yassa Date: Sat, 9 Sep 2023 00:44:21 +0300 Subject: [PATCH 11/30] Compile rescript files before running js tests --- .github/workflows/js_test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/js_test.yml b/.github/workflows/js_test.yml index ba98a766..c8cf2cd2 100644 --- a/.github/workflows/js_test.yml +++ b/.github/workflows/js_test.yml @@ -44,5 +44,8 @@ jobs: - name: Build i18n libraries run: bundle exec rake react_on_rails:locale + - name: Compile Rescript files + run: yarn res:build + - name: Run js tests run: bundle exec rake ci:js From 32e632dbf2553767919c53d279430c5da068c1dc Mon Sep 17 00:00:00 2001 From: yassa Date: Sat, 9 Sep 2023 00:57:17 +0300 Subject: [PATCH 12/30] Build recript files before test --- .github/workflows/js_test.yml | 3 --- lib/tasks/ci.rake | 11 ++++++++--- lib/tasks/linters.rake | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/js_test.yml b/.github/workflows/js_test.yml index c8cf2cd2..ba98a766 100644 --- a/.github/workflows/js_test.yml +++ b/.github/workflows/js_test.yml @@ -44,8 +44,5 @@ jobs: - name: Build i18n libraries run: bundle exec rake react_on_rails:locale - - name: Compile Rescript files - run: yarn res:build - - name: Run js tests run: bundle exec rake ci:js diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index dcea8e00..29a4dc04 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -13,10 +13,15 @@ if Rails.env.development? || Rails.env.test? sh "rspec" end + task build_rescript: :environment do + puts Rainbow("Building ReScript files").green + sh "yarn res:build" + end + namespace :ci do desc "Run all audits and tests" # rspec_tests must be before lint and js_tests to build the locale files - task all: %i[environment rspec_tests lint js_tests] do + task all: %i[environment build_rescript rspec_tests lint js_tests] do puts "All CI tasks" puts Rainbow("PASSED").green puts "" @@ -28,7 +33,7 @@ if Rails.env.development? || Rails.env.test? end desc "Run CI rspec tests" - task rspec: %i[environment rspec_tests] do + task rspec: %i[environment build_rescript rspec_tests] do puts "CI rspec tests" puts Rainbow("PASSED").green puts "" @@ -40,7 +45,7 @@ if Rails.env.development? || Rails.env.test? end desc "Run CI js_tests" - task js: %i[environment js_tests] do + task js: %i[environment build_rescript js_tests] do puts "CI js_tests" puts Rainbow("PASSED").green puts "" diff --git a/lib/tasks/linters.rake b/lib/tasks/linters.rake index de6637dc..e8035ce6 100644 --- a/lib/tasks/linters.rake +++ b/lib/tasks/linters.rake @@ -50,7 +50,7 @@ if %w[development test].include? Rails.env desc "See docs for task 'scss_lint'" task scss: :scss_lint - task lint: %i[rubocop js scss] do + task lint: %i[build_rescript rubocop js scss] do puts "Completed all linting" end end From 24e6a6a93f82981d0d0b72186656308aeab1e963 Mon Sep 17 00:00:00 2001 From: Yassa-hue Date: Thu, 5 Oct 2023 03:59:17 +0300 Subject: [PATCH 13/30] minor change --- client/app/bundles/comments/src/CommentList/CommentList.res | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/app/bundles/comments/src/CommentList/CommentList.res b/client/app/bundles/comments/src/CommentList/CommentList.res index 704b8b12..deb723ab 100644 --- a/client/app/bundles/comments/src/CommentList/CommentList.res +++ b/client/app/bundles/comments/src/CommentList/CommentList.res @@ -1,4 +1,4 @@ -@module("../RescriptShow.module.scss") external css: {..} = "default" +@module("../ReScriptShow.module.scss") external css: {..} = "default" @react.component let make = (~comments: Actions.Fetch.comments, ~error: Types.error) => { From 26f9bdec75f2586bd4dc30f093a995b5fbcc8322 Mon Sep 17 00:00:00 2001 From: Yassa-hue Date: Thu, 19 Oct 2023 02:39:49 +0300 Subject: [PATCH 14/30] remove react-on-rails binding --- bsconfig.json | 10 +++------- package.json | 1 - yarn.lock | 5 ----- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/bsconfig.json b/bsconfig.json index d5b04b94..cd4effa0 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -12,20 +12,16 @@ "in-source": true } ], - "bsc-flags": [ - "-open JsonCombinators", - "-open Belt" - ], + "bsc-flags": ["-open JsonCombinators", "-open Belt"], "suffix": ".bs.mjs", "bs-dependencies": [ "@rescript/react", "@rescript/core", "@glennsl/rescript-fetch", - "@glennsl/rescript-json-combinators", - "rescript-react-on-rails" + "@glennsl/rescript-json-combinators" ], "jsx": { - "version": 4, + "version": 4, "mode": "automatic" } } diff --git a/package.json b/package.json index 51200119..ac7e58af 100644 --- a/package.json +++ b/package.json @@ -87,7 +87,6 @@ "redux": "^4.2.1", "redux-thunk": "^2.2.0", "rescript": "^10.1.4", - "rescript-react-on-rails": "^1.0.0", "resolve-url-loader": "^2.2.0", "sanitize-html": "^2.11.0", "sass": "^1.58.3", diff --git a/yarn.lock b/yarn.lock index 9a9754f0..4c7e987e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8238,11 +8238,6 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -rescript-react-on-rails@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rescript-react-on-rails/-/rescript-react-on-rails-1.0.1.tgz#541dffdae64ec5053a50a3792b9db8783c959d1b" - integrity sha512-sbkDNCoiEWM9rqIiu+4joAj6W92yhM64KtLZQYfvYYm578jMcG02d98xpDeBT7MxZoPZZggFIed0m6Dj8bbDYA== - rescript@^10.1.4: version "10.1.4" resolved "https://registry.yarnpkg.com/rescript/-/rescript-10.1.4.tgz#0f37710d371f32a704f17b4e804f66ce3c79a305" From 73792117b681e4f137dc91e95245f7ce54a52a5c Mon Sep 17 00:00:00 2001 From: Yassa-hue Date: Thu, 19 Oct 2023 20:53:22 +0300 Subject: [PATCH 15/30] migrate to tailwind --- .../comments/src/CommentForm/CommentForm.res | 17 +++---- .../src/CommentForm/forms/HorizontalForm.res | 49 ++++++++++++------- .../src/CommentForm/forms/InlineForm.res | 45 +++++++++++++---- .../src/CommentForm/forms/StackedFrom.res | 44 +++++++++++++---- .../src/CommentList/AlertError/AlertError.res | 4 +- .../src/CommentList/Comment/Comment.res | 8 ++- .../bundles/comments/src/Header/Header.res | 6 +-- .../bundles/comments/src/ReScriptShow.bs.mjs | 4 +- .../app/bundles/comments/src/ReScriptShow.res | 6 +-- 9 files changed, 121 insertions(+), 62 deletions(-) diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.res b/client/app/bundles/comments/src/CommentForm/CommentForm.res index 41d21330..7b86f136 100644 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/src/CommentForm/CommentForm.res @@ -1,5 +1,3 @@ -@module("./CommentForm.module.scss") external css: {..} = "default" - let reducer = ( state: Types.commentFormState, action: Types.commentFormAction @@ -45,23 +43,22 @@ let make = (~storeComment: Types.storeCommentAction, ~isSaving: Types.isSaving) ]
    -
      +
      { forms ->Belt.Array.map(form => ( -
    • SetFormType(form.formType)->dispatch} - role="presentation" > - {form.formName->React.string} -
    • + {form.formName->React.string} + ) )->React.array } -
    +

    { switch state.form { diff --git a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res index a80604e1..84905374 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res +++ b/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res @@ -7,27 +7,38 @@ let make = ( ~handleSubmit, ~isSaving: Types.isSaving ) => { - -
    -
    - -
    -
    - -
    + +
    + +
    -
    -
    - -
    -
    - -
    + +
    + +
    -
    -
    - -
    + +
    +
    +
    } diff --git a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res index f6f2b601..e27dd521 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res +++ b/client/app/bundles/comments/src/CommentForm/forms/InlineForm.res @@ -7,17 +7,44 @@ let make = ( ~handleSubmit, ~isSaving: Types.isSaving ) => { -
    -
    - - + +
    + +
    -
    - - + +
    + +
    -
    - + +
    +
    } diff --git a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res index 54c558fb..6eda6a98 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res +++ b/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res @@ -7,17 +7,43 @@ let make = ( ~handleSubmit, ~isSaving: Types.isSaving ) => { -
    -
    - - + +
    + +
    -
    - - + +
    + +
    -
    - + +
    +
    } diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res index ef9a7e6f..90f9516f 100644 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res +++ b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res @@ -12,7 +12,7 @@ let make = (~cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t, ~error: timeout={500} classNames={cssTransitionGroupClassNames} > -
    +
    {"Your comment was not saved!"->React.string}
    @@ -25,7 +25,7 @@ let make = (~cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t, ~error: timeout={500} classNames={cssTransitionGroupClassNames} > -
    +
    {"Can't fetch the comments!"->React.string}
    diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.res b/client/app/bundles/comments/src/CommentList/Comment/Comment.res index 97e38f67..aa3086ea 100644 --- a/client/app/bundles/comments/src/CommentList/Comment/Comment.res +++ b/client/app/bundles/comments/src/CommentList/Comment/Comment.res @@ -1,5 +1,3 @@ -@module("./Comment.module.scss") external css: {..} = "default" - @react.component let make = (~comment: Actions.Fetch.t, ~cssTransitionGroupClassNames) => { let rawMarkup = Marked.marked(comment.text, {gfm: true}) @@ -14,9 +12,9 @@ let make = (~comment: Actions.Fetch.t, ~cssTransitionGroupClassNames) => { nodeRef={nodeRef} classNames=cssTransitionGroupClassNames > -
    -

    {comment.author->React.string}

    - +
    +

    {comment.author->React.string}

    +
    diff --git a/client/app/bundles/comments/src/Header/Header.res b/client/app/bundles/comments/src/Header/Header.res index 299c832a..2da60bdd 100644 --- a/client/app/bundles/comments/src/Header/Header.res +++ b/client/app/bundles/comments/src/Header/Header.res @@ -1,6 +1,6 @@ @react.component let make = () => { - <> + } diff --git a/client/app/bundles/comments/src/ReScriptShow.bs.mjs b/client/app/bundles/comments/src/ReScriptShow.bs.mjs index 12722aed..a4c581f3 100644 --- a/client/app/bundles/comments/src/ReScriptShow.bs.mjs +++ b/client/app/bundles/comments/src/ReScriptShow.bs.mjs @@ -98,7 +98,7 @@ function ReScriptShow$default(props) { }; fetchData(undefined); }), []); - return JsxRuntime.jsxs(JsxRuntime.Fragment, { + return JsxRuntime.jsxs("div", { children: [ JsxRuntime.jsxs("h2", { children: [ @@ -141,7 +141,7 @@ function ReScriptShow$default(props) { error: state.error }) ], - className: "container" + className: "prose max-w-none prose-a:text-sky-700 prose-li:my-0" }) ] }); diff --git a/client/app/bundles/comments/src/ReScriptShow.res b/client/app/bundles/comments/src/ReScriptShow.res index 6ab815cb..14a4ea01 100644 --- a/client/app/bundles/comments/src/ReScriptShow.res +++ b/client/app/bundles/comments/src/ReScriptShow.res @@ -64,10 +64,10 @@ let default = () => { None }, []) - <> +

    {"Rescript + Rails Backend (with "->React.string}{"react_on_rails gem"->React.string}{")"->React.string}

    -
    +

    {"Comments"->React.string}

    • {"Text supports Github Flavored Markdown."->React.string}
    • @@ -78,5 +78,5 @@ let default = () => {
    - +
    } From c259cbb4ce528dad1dde084e7092dc57b0f3c714 Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 19 Oct 2023 21:13:30 +0300 Subject: [PATCH 16/30] remove bs.mjs files --- .../bundles/comments/src/ReScriptShow.bs.mjs | 157 ------------------ 1 file changed, 157 deletions(-) delete mode 100644 client/app/bundles/comments/src/ReScriptShow.bs.mjs diff --git a/client/app/bundles/comments/src/ReScriptShow.bs.mjs b/client/app/bundles/comments/src/ReScriptShow.bs.mjs deleted file mode 100644 index a4c581f3..00000000 --- a/client/app/bundles/comments/src/ReScriptShow.bs.mjs +++ /dev/null @@ -1,157 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as Curry from "rescript/lib/es6/curry.js"; -import * as React from "react"; -import * as Header from "./Header/Header.bs.mjs"; -import * as Actions from "./Actions/Actions.bs.mjs"; -import * as CommentForm from "./CommentForm/CommentForm.bs.mjs"; -import * as CommentList from "./CommentList/CommentList.bs.mjs"; -import * as JsxRuntime from "react/jsx-runtime"; - -function reducer(state, action) { - switch (action.TAG | 0) { - case /* SetComments */0 : - return { - comments: action._0, - error: state.error, - isSaving: state.isSaving - }; - case /* SetError */1 : - return { - comments: state.comments, - error: action._0, - isSaving: state.isSaving - }; - case /* SetIsSaving */2 : - return { - comments: state.comments, - error: state.error, - isSaving: action._0 - }; - - } -} - -function ReScriptShow$default(props) { - var match = React.useReducer(reducer, { - comments: [], - error: /* NoError */0, - isSaving: /* Free */0 - }); - var dispatch = match[1]; - var state = match[0]; - var storeComment = function (author, text) { - Curry._1(dispatch, { - TAG: /* SetError */1, - _0: /* NoError */0 - }); - Curry._1(dispatch, { - TAG: /* SetIsSaving */2, - _0: /* BusySaving */1 - }); - var saveAndFetchComments = async function (param) { - try { - await Actions.Create.storeComment({ - author: author, - text: text - }); - Curry._1(dispatch, { - TAG: /* SetIsSaving */2, - _0: /* Free */0 - }); - var comments = await Actions.Fetch.fetchComments(undefined); - if (comments.TAG === /* Ok */0) { - return Curry._1(dispatch, { - TAG: /* SetComments */0, - _0: comments._0 - }); - } else { - return Curry._1(dispatch, { - TAG: /* SetError */1, - _0: comments._0 - }); - } - } - catch (exn){ - return Curry._1(dispatch, { - TAG: /* SetError */1, - _0: /* FailedToSaveComment */1 - }); - } - }; - saveAndFetchComments(undefined); - }; - React.useEffect((function () { - var fetchData = async function (param) { - var comments = await Actions.Fetch.fetchComments(undefined); - if (comments.TAG === /* Ok */0) { - return Curry._1(dispatch, { - TAG: /* SetComments */0, - _0: comments._0 - }); - } else { - return Curry._1(dispatch, { - TAG: /* SetError */1, - _0: comments._0 - }); - } - }; - fetchData(undefined); - }), []); - return JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsxs("h2", { - children: [ - "Rescript + Rails Backend (with ", - JsxRuntime.jsx("a", { - children: "react_on_rails gem", - href: "https://github.com/shakacode/react_on_rails" - }), - ")" - ] - }), - JsxRuntime.jsx(Header.make, {}), - JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsx("h2", { - children: "Comments" - }), - JsxRuntime.jsxs("ul", { - children: [ - JsxRuntime.jsx("li", { - children: "Text supports Github Flavored Markdown." - }), - JsxRuntime.jsx("li", { - children: "Comments older than 24 hours are deleted." - }), - JsxRuntime.jsx("li", { - children: "Name is preserved. Text is reset, between submits" - }), - JsxRuntime.jsx("li", { - children: "To see Action Cable instantly update two browsers, open two browsers and submit a comment!" - }) - ] - }), - JsxRuntime.jsx(CommentForm.make, { - storeComment: storeComment, - isSaving: state.isSaving - }), - JsxRuntime.jsx(CommentList.make, { - comments: state.comments, - error: state.error - }) - ], - className: "prose max-w-none prose-a:text-sky-700 prose-li:my-0" - }) - ] - }); -} - -var $$default = ReScriptShow$default; - -export { - reducer , - $$default , - $$default as default, -} -/* react Not a pure module */ From 7bde5fc1d3883b1b1a4a48e6263fcb243284a16a Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 19 Oct 2023 21:16:17 +0300 Subject: [PATCH 17/30] remove unused scss files --- .../components/NavigationBar/NavigationBar.jsx | 8 ++++++++ .../comments/src/CommentForm/CommentForm.module.scss | 11 ----------- .../src/CommentList/Comment/Comment.module.scss | 11 ----------- client/app/bundles/comments/src/vars.scss | 10 ---------- 4 files changed, 8 insertions(+), 32 deletions(-) delete mode 100644 client/app/bundles/comments/src/CommentForm/CommentForm.module.scss delete mode 100644 client/app/bundles/comments/src/CommentList/Comment/Comment.module.scss delete mode 100644 client/app/bundles/comments/src/vars.scss diff --git a/client/app/bundles/comments/components/NavigationBar/NavigationBar.jsx b/client/app/bundles/comments/components/NavigationBar/NavigationBar.jsx index 52e3a477..65dc3b40 100644 --- a/client/app/bundles/comments/components/NavigationBar/NavigationBar.jsx +++ b/client/app/bundles/comments/components/NavigationBar/NavigationBar.jsx @@ -97,6 +97,14 @@ function NavigationBar(props) { Classic Rails +
  • + + Rescript + +
  • Date: Thu, 19 Oct 2023 21:32:43 +0300 Subject: [PATCH 18/30] fix rescript spec tests --- spec/rescript/rescript_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/rescript/rescript_spec.rb b/spec/rescript/rescript_spec.rb index 3ae1db28..aedc5aa9 100644 --- a/spec/rescript/rescript_spec.rb +++ b/spec/rescript/rescript_spec.rb @@ -13,17 +13,17 @@ end it "stops showing horizontal tab when other tab is clicked" do - find("a", text: "Inline Form", wait: 10) + find("button", text: "Inline Form") page.has_no_css?("form-horizontal") end it "shows inline form when Inline Form link is clicked" do - find("a", text: "Inline Form", wait: 10) + find("button", text: "Inline Form", wait: 10) page.has_css?("form-inline") end it "shows stacked form when Stacked Form link is clicked" do - find("a", text: "Stacked Form", wait: 10) + find("button", text: "Stacked Form") page.has_no_css?("form-inline") and page.has_no_css?("form-horizontal") end end From 3af072d5b207ce5c7351572e29f4ebc3928137ab Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 19 Oct 2023 21:49:12 +0300 Subject: [PATCH 19/30] build rescript before test --- .github/workflows/rspec_test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/rspec_test.yml b/.github/workflows/rspec_test.yml index 928c1663..45551db7 100644 --- a/.github/workflows/rspec_test.yml +++ b/.github/workflows/rspec_test.yml @@ -73,6 +73,9 @@ jobs: - name: Build i18n libraries run: bundle exec rake react_on_rails:locale + - name: Build Rescript components + run: yarn res:build + - name: Build shakapacker chunks run: NODE_ENV=development bundle exec bin/shakapacker From 310fdb571575587695b5f2bc108b51084b209be0 Mon Sep 17 00:00:00 2001 From: Yassa-hue Date: Wed, 1 Nov 2023 16:31:44 +0200 Subject: [PATCH 20/30] refactor rescript src --- .gitignore | 3 +- bsconfig.json | 4 +- .../{src => rescript}/Actions/Actions.res | 6 +- .../{src => rescript}/Actions/Types.res | 2 - .../CommentForm/CommentForm.res | 14 ++- .../CommentForm/forms/HorizontalForm.res | 4 +- .../CommentForm/forms/InlineForm.res | 4 +- .../CommentForm/forms/StackedFrom.res | 4 +- .../CommentList/AlertError/AlertError.res | 26 +++++ .../CommentList/Comment/Comment.res | 6 +- .../CommentList/CommentList.res | 14 +-- .../comments/rescript/Header/Header.bs.mjs | 95 +++++++++++++++++++ .../{src => rescript}/Header/Header.res | 0 .../ReScriptShow.module.scss | 0 .../{src => rescript}/ReScriptShow.res | 47 +++++---- .../{src => rescript}/bindings/Axios.res | 0 .../{src => rescript}/bindings/Marked.res | 0 .../bindings/ReactOnRails.res | 0 .../bindings/ReactTransitionGroup.res} | 0 .../src/CommentList/AlertError/AlertError.res | 34 ------- client/app/packs/client-bundle.js | 2 +- client/app/packs/server-bundle.js | 2 +- package.json | 1 + yarn.lock | 5 + 24 files changed, 191 insertions(+), 82 deletions(-) rename client/app/bundles/comments/{src => rescript}/Actions/Actions.res (88%) rename client/app/bundles/comments/{src => rescript}/Actions/Types.res (93%) rename client/app/bundles/comments/{src => rescript}/CommentForm/CommentForm.res (88%) rename client/app/bundles/comments/{src => rescript}/CommentForm/forms/HorizontalForm.res (94%) rename client/app/bundles/comments/{src => rescript}/CommentForm/forms/InlineForm.res (94%) rename client/app/bundles/comments/{src => rescript}/CommentForm/forms/StackedFrom.res (95%) create mode 100644 client/app/bundles/comments/rescript/CommentList/AlertError/AlertError.res rename client/app/bundles/comments/{src => rescript}/CommentList/Comment/Comment.res (83%) rename client/app/bundles/comments/{src => rescript}/CommentList/CommentList.res (51%) create mode 100644 client/app/bundles/comments/rescript/Header/Header.bs.mjs rename client/app/bundles/comments/{src => rescript}/Header/Header.res (100%) rename client/app/bundles/comments/{src => rescript}/ReScriptShow.module.scss (100%) rename client/app/bundles/comments/{src => rescript}/ReScriptShow.res (57%) rename client/app/bundles/comments/{src => rescript}/bindings/Axios.res (100%) rename client/app/bundles/comments/{src => rescript}/bindings/Marked.res (100%) rename client/app/bundles/comments/{src => rescript}/bindings/ReactOnRails.res (100%) rename client/app/bundles/comments/{src/bindings/CSSAnimation.res => rescript/bindings/ReactTransitionGroup.res} (100%) delete mode 100644 client/app/bundles/comments/src/CommentList/AlertError/AlertError.res diff --git a/.gitignore b/.gitignore index 65f61da3..42b8d30f 100644 --- a/.gitignore +++ b/.gitignore @@ -49,5 +49,6 @@ yarn-debug.log* .yarn-integrity lib/bs +/lib/ocaml -client/app/bundles/comments/src/**/*.bs.mjs +client/app/bundles/comments/rescript/**/*.bs.js diff --git a/bsconfig.json b/bsconfig.json index cd4effa0..93fd3dae 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -2,7 +2,7 @@ "name": "react-webpack-rails-tutorial", "sources": [ { - "dir": "client/app/bundles/comments/src", + "dir": "client/app/bundles/comments/rescript", "subdirs": true } ], @@ -13,7 +13,7 @@ } ], "bsc-flags": ["-open JsonCombinators", "-open Belt"], - "suffix": ".bs.mjs", + "suffix": ".bs.js", "bs-dependencies": [ "@rescript/react", "@rescript/core", diff --git a/client/app/bundles/comments/src/Actions/Actions.res b/client/app/bundles/comments/rescript/Actions/Actions.res similarity index 88% rename from client/app/bundles/comments/src/Actions/Actions.res rename to client/app/bundles/comments/rescript/Actions/Actions.res index 758e0e90..251759fa 100644 --- a/client/app/bundles/comments/src/Actions/Actions.res +++ b/client/app/bundles/comments/rescript/Actions/Actions.res @@ -28,11 +28,11 @@ module Fetch = { type comments = array - type commentsResT = { + type commentsRes = { comments: comments } - let fetchComments = async (): result => { + let fetchComments = async (): result => { open Json.Decode let response = await Fetch.get("comments.json") @@ -50,7 +50,7 @@ module Fetch = { switch jsonRes->Json.decode(jsonComments) { | Ok(decodedRes) => Ok(decodedRes.comments) - | Error(_) => Error(FailedToFetchComments) + | Error(e) => Error(e) } } } diff --git a/client/app/bundles/comments/src/Actions/Types.res b/client/app/bundles/comments/rescript/Actions/Types.res similarity index 93% rename from client/app/bundles/comments/src/Actions/Types.res rename to client/app/bundles/comments/rescript/Actions/Types.res index 763ce738..ea88b078 100644 --- a/client/app/bundles/comments/src/Actions/Types.res +++ b/client/app/bundles/comments/rescript/Actions/Types.res @@ -24,5 +24,3 @@ type storeCommentData = { } type error = NoError | FailedToSaveComment | FailedToFetchComments - -type isSaving = Free | BusySaving diff --git a/client/app/bundles/comments/src/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res similarity index 88% rename from client/app/bundles/comments/src/CommentForm/CommentForm.res rename to client/app/bundles/comments/rescript/CommentForm/CommentForm.res index 7b86f136..865ddf97 100644 --- a/client/app/bundles/comments/src/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -11,7 +11,7 @@ let reducer = ( @react.component -let make = (~storeComment: Types.storeCommentAction, ~isSaving: Types.isSaving) => { +let make = (~storeComment: Types.storeCommentAction, ~disabled: bool, ~storeCommentError: bool) => { let (state, dispatch) = React.useReducer( reducer, { author: "", @@ -46,7 +46,7 @@ let make = (~storeComment: Types.storeCommentAction, ~isSaving: Types.isSaving)
    { forms - ->Belt.Array.map(form + ->Array.map(form => (
    } diff --git a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res b/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res similarity index 94% rename from client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res rename to client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res index 84905374..8f9bfd6d 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/HorizontalForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res @@ -5,9 +5,9 @@ let make = ( ~text, ~handleTextChange, ~handleSubmit, - ~isSaving: Types.isSaving + ~disabled ) => { -
    +
    {
    diff --git a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res b/client/app/bundles/comments/rescript/CommentForm/forms/StackedFrom.res similarity index 95% rename from client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res rename to client/app/bundles/comments/rescript/CommentForm/forms/StackedFrom.res index 6eda6a98..af535f85 100644 --- a/client/app/bundles/comments/src/CommentForm/forms/StackedFrom.res +++ b/client/app/bundles/comments/rescript/CommentForm/forms/StackedFrom.res @@ -5,11 +5,11 @@ let make = ( ~text, ~handleTextChange, ~handleSubmit, - ~isSaving: Types.isSaving + ~disabled ) => {
    diff --git a/client/app/bundles/comments/rescript/CommentList/AlertError/AlertError.res b/client/app/bundles/comments/rescript/CommentList/AlertError/AlertError.res new file mode 100644 index 00000000..18d8212f --- /dev/null +++ b/client/app/bundles/comments/rescript/CommentList/AlertError/AlertError.res @@ -0,0 +1,26 @@ +@module("../../ReScriptShow.module.scss") external css: {..} = "default" + +@react.component +let make = (~errorMsg: string) => { + let nodeRef = React.useRef(Js.Nullable.null) + + let cssTransitionGroupClassNames: ReactTransitionGroup.CSSTransition.t = { + enter: css["elementEnter"], + enterActive: css["elementEnterActive"], + exit: css["elementLeave"], + exitActive: css["elementLeaveActive"] + } + + // The 500 must correspond to the 0.5s in: + // ../../RescriptShow.module.scss:9 + +
    + {errorMsg->React.string} +
    +
    +} diff --git a/client/app/bundles/comments/src/CommentList/Comment/Comment.res b/client/app/bundles/comments/rescript/CommentList/Comment/Comment.res similarity index 83% rename from client/app/bundles/comments/src/CommentList/Comment/Comment.res rename to client/app/bundles/comments/rescript/CommentList/Comment/Comment.res index aa3086ea..19a26862 100644 --- a/client/app/bundles/comments/src/CommentList/Comment/Comment.res +++ b/client/app/bundles/comments/rescript/CommentList/Comment/Comment.res @@ -6,8 +6,8 @@ let make = (~comment: Actions.Fetch.t, ~cssTransitionGroupClassNames) => { // The 500 must correspond to the 0.5s in: // ../../RescriptShow.module.scss:9 - {

    {comment.author->React.string}

    - + } diff --git a/client/app/bundles/comments/src/CommentList/CommentList.res b/client/app/bundles/comments/rescript/CommentList/CommentList.res similarity index 51% rename from client/app/bundles/comments/src/CommentList/CommentList.res rename to client/app/bundles/comments/rescript/CommentList/CommentList.res index deb723ab..499ed258 100644 --- a/client/app/bundles/comments/src/CommentList/CommentList.res +++ b/client/app/bundles/comments/rescript/CommentList/CommentList.res @@ -1,8 +1,8 @@ @module("../ReScriptShow.module.scss") external css: {..} = "default" @react.component -let make = (~comments: Actions.Fetch.comments, ~error: Types.error) => { - let cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t = { +let make = (~comments: Actions.Fetch.comments, ~fetchCommentsError: bool) => { + let cssTransitionGroupClassNames: ReactTransitionGroup.CSSTransition.t = { enter: css["elementEnter"], enterActive: css["elementEnterActive"], exit: css["elementLeave"], @@ -11,21 +11,21 @@ let make = (~comments: Actions.Fetch.comments, ~error: Types.error) => {
    { - + fetchCommentsError ? : React.null } - + { - comments->Belt.Array.map( + comments->Array.map( comment => Belt.Int.toString + "comment_" ++ comment.id->Int.toString } /> )->React.array } - +
    } diff --git a/client/app/bundles/comments/rescript/Header/Header.bs.mjs b/client/app/bundles/comments/rescript/Header/Header.bs.mjs new file mode 100644 index 00000000..45c9f2a1 --- /dev/null +++ b/client/app/bundles/comments/rescript/Header/Header.bs.mjs @@ -0,0 +1,95 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as JsxRuntime from "react/jsx-runtime"; + +function Header(props) { + return JsxRuntime.jsxs("div", { + children: [ + JsxRuntime.jsxs("ul", { + children: [ + JsxRuntime.jsxs("li", { + children: [ + JsxRuntime.jsx("a", { + children: "Can ShakaCode Help You? ", + href: "https://blog.shakacode.com/can-shakacode-help-you-4a5b1e5a8a63#.jex6tg9w9" + }), + "We're actively seeking new projects with React, React-Native, or Ruby on Rails." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "See the ", + JsxRuntime.jsx("a", { + children: "github.com/shakacode/react-webpack-rails-tutorial/README.md ", + href: "https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/README.md" + }), + "for details of how this example site was built." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "Read ", + JsxRuntime.jsx("a", { + children: "Documentation for React on Rails", + href: "https://shakacode.gitbooks.io/react-on-rails/content/" + }), + JsxRuntime.jsx("a", { + children: "The React on Rails Doctrine.", + href: "https://www.shakacode.com/blog/the-react-on-rails-doctrine" + }) + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "See our React Native Client: ", + JsxRuntime.jsx("a", { + children: "shakacode/react-native-tutorial", + href: "https://github.com/shakacode/react-native-tutorial" + }), + "." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + "Watch the ", + JsxRuntime.jsx("a", { + children: "React On Rails Tutorial Series", + href: "https://www.youtube.com/playlist?list=PL5VAKH-U1M6dj84BApfUtvBjvF-0-JfEU" + }), + "." + ] + }), + JsxRuntime.jsxs("li", { + children: [ + JsxRuntime.jsx("a", { + children: "ShakaCode", + href: "http://www.shakacode.com" + }), + " is doing support for React on Rails, \ + including a private Slack channel, \ + source code reviews, and pair programming sessions. ", + JsxRuntime.jsx("b", { + children: JsxRuntime.jsx("a", { + children: "Click here", + href: "http://www.shakacode.com/work/index.html" + }) + }), + " for more information." + ] + }) + ] + }), + JsxRuntime.jsx("hr", { + className: "border-t my-8" + }) + ], + className: "prose max-w-full prose-a:text-sky-700 prose-li:my-0 prose-code:text-rose-600 prose-code:bg-yellow-100 prose-headings:text-gray-700" + }); +} + +var make = Header; + +export { + make , +} +/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/src/Header/Header.res b/client/app/bundles/comments/rescript/Header/Header.res similarity index 100% rename from client/app/bundles/comments/src/Header/Header.res rename to client/app/bundles/comments/rescript/Header/Header.res diff --git a/client/app/bundles/comments/src/ReScriptShow.module.scss b/client/app/bundles/comments/rescript/ReScriptShow.module.scss similarity index 100% rename from client/app/bundles/comments/src/ReScriptShow.module.scss rename to client/app/bundles/comments/rescript/ReScriptShow.module.scss diff --git a/client/app/bundles/comments/src/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res similarity index 57% rename from client/app/bundles/comments/src/ReScriptShow.res rename to client/app/bundles/comments/rescript/ReScriptShow.res index 14a4ea01..322edf33 100644 --- a/client/app/bundles/comments/src/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,13 +1,21 @@ +type savingStatus = Free | BusySaving + +type status = { + commentsFetchError: bool, + commentStoreError: bool, + saving: savingStatus +} + type state = { comments: Actions.Fetch.comments, - error: Types.error, - isSaving: Types.isSaving + status: status } type action = | SetComments(Actions.Fetch.comments) - | SetError(Types.error) - | SetIsSaving(Types.isSaving) + | SetFetchError(bool) + | SetStoreError(bool) + | SetSavingStatus(savingStatus) let reducer = ( @@ -15,9 +23,10 @@ let reducer = ( action: action ): state => { switch (action) { - | SetComments(comments) => {...state, comments} - | SetError(error) => {...state, error} - | SetIsSaving(isSaving) => {...state, isSaving} + | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: true}} + | SetFetchError(error) => {...state, status: {...state.status, commentsFetchError: error}} + | SetStoreError(error) => {...state, status: {...state.status, commentStoreError: error}} + | SetSavingStatus(saving) => {...state, status: {...state.status, saving: saving}} } } @@ -26,26 +35,29 @@ let default = () => { let (state, dispatch) = React.useReducer( reducer, { comments: ([]: Actions.Fetch.comments), - error: NoError, - isSaving: Free + status: { + commentsFetchError: false, + commentStoreError: false, + saving: Free + } } ) let storeComment = (author, text) => { - SetError(NoError)->dispatch - SetIsSaving(BusySaving)->dispatch + SetStoreError(false)->dispatch + SetSavingStatus(BusySaving)->dispatch let saveAndFetchComments = async () => { try { let _ = await Actions.Create.storeComment({author, text}) - SetIsSaving(Free)->dispatch + SetSavingStatus(Free)->dispatch let comments = await Actions.Fetch.fetchComments() switch comments { | Ok(comments) => SetComments(comments)->dispatch - | Error(e) => SetError(e)->dispatch + | Error(_) => SetFetchError(true)->dispatch } } catch { - | _ => SetError(FailedToSaveComment)->dispatch + | _ => SetStoreError(true)->dispatch } } saveAndFetchComments()->ignore @@ -56,7 +68,7 @@ let default = () => { let comments = await Actions.Fetch.fetchComments() switch comments { | Ok(comments) => SetComments(comments)->dispatch - | Error(e) => SetError(e)->dispatch + | Error(_) => SetFetchError(true)->dispatch } } @@ -75,8 +87,9 @@ let default = () => {
  • {"Name is preserved. Text is reset, between submits"->React.string}
  • {"To see Action Cable instantly update two browsers, open two browsers and submit a comment!"->React.string}
  • - - + true; | Free => false}} storeCommentError={state.status.commentStoreError} /> +
    } diff --git a/client/app/bundles/comments/src/bindings/Axios.res b/client/app/bundles/comments/rescript/bindings/Axios.res similarity index 100% rename from client/app/bundles/comments/src/bindings/Axios.res rename to client/app/bundles/comments/rescript/bindings/Axios.res diff --git a/client/app/bundles/comments/src/bindings/Marked.res b/client/app/bundles/comments/rescript/bindings/Marked.res similarity index 100% rename from client/app/bundles/comments/src/bindings/Marked.res rename to client/app/bundles/comments/rescript/bindings/Marked.res diff --git a/client/app/bundles/comments/src/bindings/ReactOnRails.res b/client/app/bundles/comments/rescript/bindings/ReactOnRails.res similarity index 100% rename from client/app/bundles/comments/src/bindings/ReactOnRails.res rename to client/app/bundles/comments/rescript/bindings/ReactOnRails.res diff --git a/client/app/bundles/comments/src/bindings/CSSAnimation.res b/client/app/bundles/comments/rescript/bindings/ReactTransitionGroup.res similarity index 100% rename from client/app/bundles/comments/src/bindings/CSSAnimation.res rename to client/app/bundles/comments/rescript/bindings/ReactTransitionGroup.res diff --git a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res b/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res deleted file mode 100644 index 90f9516f..00000000 --- a/client/app/bundles/comments/src/CommentList/AlertError/AlertError.res +++ /dev/null @@ -1,34 +0,0 @@ -@react.component -let make = (~cssTransitionGroupClassNames: CSSAnimation.CSSTransition.t, ~error: Types.error) => { - let nodeRef = React.useRef(Js.Nullable.null) - - switch error { - | FailedToSaveComment => - // The 500 must correspond to the 0.5s in: - // ../../RescriptShow.module.scss:9 - -
    - {"Your comment was not saved!"->React.string} -
    -
    - | FailedToFetchComments => - // The 500 must correspond to the 0.5s in: - // ../../RescriptShow.module.scss:9 - -
    - {"Can't fetch the comments!"->React.string} -
    -
    - | NoError => React.null - } -} diff --git a/client/app/packs/client-bundle.js b/client/app/packs/client-bundle.js index be7d0a2c..2675009a 100644 --- a/client/app/packs/client-bundle.js +++ b/client/app/packs/client-bundle.js @@ -10,7 +10,7 @@ import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import Footer from '../bundles/comments/components/Footer/Footer'; -import RescriptShow from '../bundles/comments/src/ReScriptShow.bs.mjs'; +import RescriptShow from '../bundles/comments/rescript/ReScriptShow.bs.js'; import '../assets/styles/application'; diff --git a/client/app/packs/server-bundle.js b/client/app/packs/server-bundle.js index 98cef523..96b56491 100644 --- a/client/app/packs/server-bundle.js +++ b/client/app/packs/server-bundle.js @@ -8,7 +8,7 @@ import NavigationBarApp from '../bundles/comments/startup/NavigationBarApp'; import routerCommentsStore from '../bundles/comments/store/routerCommentsStore'; import commentsStore from '../bundles/comments/store/commentsStore'; import Footer from '../bundles/comments/components/Footer/Footer'; -import RescriptShow from '../bundles/comments/src/ReScriptShow.bs.mjs'; +import RescriptShow from '../bundles/comments/rescript/ReScriptShow.bs.js'; ReactOnRails.register({ App, diff --git a/package.json b/package.json index ac7e58af..d35356c7 100644 --- a/package.json +++ b/package.json @@ -87,6 +87,7 @@ "redux": "^4.2.1", "redux-thunk": "^2.2.0", "rescript": "^10.1.4", + "rescript-react-on-rails": "^1.0.1", "resolve-url-loader": "^2.2.0", "sanitize-html": "^2.11.0", "sass": "^1.58.3", diff --git a/yarn.lock b/yarn.lock index 4c7e987e..efbbf832 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8238,6 +8238,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +rescript-react-on-rails@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rescript-react-on-rails/-/rescript-react-on-rails-1.0.1.tgz#541dffdae64ec5053a50a3792b9db8783c959d1b" + integrity sha512-sbkDNCoiEWM9rqIiu+4joAj6W92yhM64KtLZQYfvYYm578jMcG02d98xpDeBT7MxZoPZZggFIed0m6Dj8bbDYA== + rescript@^10.1.4: version "10.1.4" resolved "https://registry.yarnpkg.com/rescript/-/rescript-10.1.4.tgz#0f37710d371f32a704f17b4e804f66ce3c79a305" From ef879b151ecd11f6897fe0a3741be5823026467e Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 2 Nov 2023 23:37:03 +0200 Subject: [PATCH 21/30] fix add commit fail bug --- bsconfig.json | 3 ++- client/app/bundles/comments/rescript/Actions/Actions.res | 5 ++++- .../bundles/comments/rescript/CommentForm/CommentForm.res | 2 +- client/app/bundles/comments/rescript/ReScriptShow.res | 4 ++-- client/app/bundles/comments/rescript/bindings/Axios.res | 5 ++++- .../bundles/comments/rescript/bindings/ReactOnRails.res | 7 ------- 6 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 client/app/bundles/comments/rescript/bindings/ReactOnRails.res diff --git a/bsconfig.json b/bsconfig.json index 93fd3dae..1f842dce 100644 --- a/bsconfig.json +++ b/bsconfig.json @@ -18,7 +18,8 @@ "@rescript/react", "@rescript/core", "@glennsl/rescript-fetch", - "@glennsl/rescript-json-combinators" + "@glennsl/rescript-json-combinators", + "rescript-react-on-rails" ], "jsx": { "version": 4, diff --git a/client/app/bundles/comments/rescript/Actions/Actions.res b/client/app/bundles/comments/rescript/Actions/Actions.res index 251759fa..d8a200a4 100644 --- a/client/app/bundles/comments/rescript/Actions/Actions.res +++ b/client/app/bundles/comments/rescript/Actions/Actions.res @@ -13,7 +13,10 @@ module Create = { }, { responseType: "json", - headers: ReactOnRails.ror.default.authenticityHeaders() + headers: { + "X-CSRF-Token": ReactOnRails.authenticityToken(), + "X-Requested-With": "XMLHttpRequest", + } } ) } diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index 865ddf97..b03b8933 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -93,7 +93,7 @@ let make = (~storeComment: Types.storeCommentAction, ~disabled: bool, ~storeComm } { - storeCommentError ? : React.null + storeCommentError ? : React.null }
  • } diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index 322edf33..f7229efa 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -23,7 +23,7 @@ let reducer = ( action: action ): state => { switch (action) { - | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: true}} + | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: false}} | SetFetchError(error) => {...state, status: {...state.status, commentsFetchError: error}} | SetStoreError(error) => {...state, status: {...state.status, commentStoreError: error}} | SetSavingStatus(saving) => {...state, status: {...state.status, saving: saving}} @@ -51,7 +51,7 @@ let default = () => { let _ = await Actions.Create.storeComment({author, text}) SetSavingStatus(Free)->dispatch - let comments = await Actions.Fetch.fetchComments() + let comments = await Actions.Fetch.fetchComments() switch comments { | Ok(comments) => SetComments(comments)->dispatch | Error(_) => SetFetchError(true)->dispatch diff --git a/client/app/bundles/comments/rescript/bindings/Axios.res b/client/app/bundles/comments/rescript/bindings/Axios.res index 2d23cd55..326503a4 100644 --- a/client/app/bundles/comments/rescript/bindings/Axios.res +++ b/client/app/bundles/comments/rescript/bindings/Axios.res @@ -1,5 +1,8 @@ type reqOptions = { responseType: string, - headers: {.} + headers: { + "X-CSRF-Token": option, + "X-Requested-With": string + } } @module("axios") external post: (string, Types.storeCommentData, reqOptions) => promise = "post" diff --git a/client/app/bundles/comments/rescript/bindings/ReactOnRails.res b/client/app/bundles/comments/rescript/bindings/ReactOnRails.res deleted file mode 100644 index 29d158ff..00000000 --- a/client/app/bundles/comments/rescript/bindings/ReactOnRails.res +++ /dev/null @@ -1,7 +0,0 @@ -type rorDefault = { - authenticityHeaders: unit => {.} -} -type rorModule = { - default: rorDefault -} -@module("react-on-rails") external ror: rorModule = "default" From 9a848f9238e245c5e9d3440d78fb2796f04db709 Mon Sep 17 00:00:00 2001 From: yassa Date: Fri, 3 Nov 2023 13:35:12 +0200 Subject: [PATCH 22/30] refactor the types --- .eslintignore | 2 +- .../comments/rescript/Actions/Actions.res | 2 +- .../rescript/CommentForm/CommentForm.res | 12 ++++---- .../CommentFormTypes.res} | 23 +++++--------- .../comments/rescript/ReScriptShow.res | 30 ++++--------------- .../comments/rescript/ReScriptShowTypes.res | 20 +++++++++++++ .../comments/rescript/bindings/Axios.res | 8 ++++- 7 files changed, 47 insertions(+), 50 deletions(-) rename client/app/bundles/comments/rescript/{Actions/Types.res => CommentForm/CommentFormTypes.res} (51%) create mode 100644 client/app/bundles/comments/rescript/ReScriptShowTypes.res diff --git a/.eslintignore b/.eslintignore index 9d1f596b..726bf604 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,4 @@ public/ client/app/libs/i18n/translations.js client/app/libs/i18n/default.js postcss.config.js -client/app/bundles/comments/src/ +client/app/bundles/comments/rescript/ diff --git a/client/app/bundles/comments/rescript/Actions/Actions.res b/client/app/bundles/comments/rescript/Actions/Actions.res index d8a200a4..a72e0168 100644 --- a/client/app/bundles/comments/rescript/Actions/Actions.res +++ b/client/app/bundles/comments/rescript/Actions/Actions.res @@ -13,7 +13,7 @@ module Create = { }, { responseType: "json", - headers: { + 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", } diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index b03b8933..4df2a97f 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -1,7 +1,7 @@ let reducer = ( - state: Types.commentFormState, - action: Types.commentFormAction -): Types.commentFormState => { + state: CommentFormTypes.state, + action: CommentFormTypes.action +): CommentFormTypes.state => { switch (action) { | SetAuthor(author) => {...state, author} | SetText(text) => {...state, text} @@ -11,7 +11,7 @@ let reducer = ( @react.component -let make = (~storeComment: Types.storeCommentAction, ~disabled: bool, ~storeCommentError: bool) => { +let make = (~storeComment: ReScriptShowTypes.storeComment, ~disabled: bool, ~storeCommentError: bool) => { let (state, dispatch) = React.useReducer( reducer, { author: "", @@ -32,10 +32,10 @@ let make = (~storeComment: Types.storeCommentAction, ~disabled: bool, ~storeComm let handleSubmit = (event) => { ReactEvent.Form.preventDefault(event) - storeComment(state.author, state.text) + storeComment({author: state.author, text: state.text}) } - let forms: array = + let forms: array = [ {formName: "Horizontal Form", formType: Horizontal}, {formName: "Inline Form", formType: Inline}, diff --git a/client/app/bundles/comments/rescript/Actions/Types.res b/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res similarity index 51% rename from client/app/bundles/comments/rescript/Actions/Types.res rename to client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res index ea88b078..60c7e8b3 100644 --- a/client/app/bundles/comments/rescript/Actions/Types.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res @@ -1,26 +1,17 @@ type formDisplay = Horizontal | Inline | Stacked -type commentFormState = { - author: string, - text: string, - form: formDisplay -} - -type commentFormAction = - | SetAuthor(string) - | SetText(string) - | SetFormType(formDisplay) - type formData = { formName: string, formType: formDisplay } -type storeCommentAction = (string, string) => unit - -type storeCommentData = { +type state = { author: string, - text: string + text: string, + form: formDisplay } -type error = NoError | FailedToSaveComment | FailedToFetchComments +type action = + | SetAuthor(string) + | SetText(string) + | SetFormType(formDisplay) diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index f7229efa..107070a8 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,27 +1,7 @@ -type savingStatus = Free | BusySaving - -type status = { - commentsFetchError: bool, - commentStoreError: bool, - saving: savingStatus -} - -type state = { - comments: Actions.Fetch.comments, - status: status -} - -type action = - | SetComments(Actions.Fetch.comments) - | SetFetchError(bool) - | SetStoreError(bool) - | SetSavingStatus(savingStatus) - - let reducer = ( - state: state, - action: action -): state => { + state: ReScriptShowTypes.state, + action: ReScriptShowTypes.action +): ReScriptShowTypes.state => { switch (action) { | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: false}} | SetFetchError(error) => {...state, status: {...state.status, commentsFetchError: error}} @@ -43,12 +23,12 @@ let default = () => { } ) - let storeComment = (author, text) => { + let storeComment: ReScriptShowTypes.storeComment = (newComment: Actions.Create.t) => { SetStoreError(false)->dispatch SetSavingStatus(BusySaving)->dispatch let saveAndFetchComments = async () => { try { - let _ = await Actions.Create.storeComment({author, text}) + let _ = await Actions.Create.storeComment(newComment) SetSavingStatus(Free)->dispatch let comments = await Actions.Fetch.fetchComments() diff --git a/client/app/bundles/comments/rescript/ReScriptShowTypes.res b/client/app/bundles/comments/rescript/ReScriptShowTypes.res new file mode 100644 index 00000000..407c3b94 --- /dev/null +++ b/client/app/bundles/comments/rescript/ReScriptShowTypes.res @@ -0,0 +1,20 @@ +type savingStatus = Free | BusySaving + +type status = { + commentsFetchError: bool, + commentStoreError: bool, + saving: savingStatus +} + +type state = { + comments: Actions.Fetch.comments, + status: status +} + +type action = + | SetComments(Actions.Fetch.comments) + | SetFetchError(bool) + | SetStoreError(bool) + | SetSavingStatus(savingStatus) + +type storeComment = (Actions.Create.t) => unit diff --git a/client/app/bundles/comments/rescript/bindings/Axios.res b/client/app/bundles/comments/rescript/bindings/Axios.res index 326503a4..39fa3cd3 100644 --- a/client/app/bundles/comments/rescript/bindings/Axios.res +++ b/client/app/bundles/comments/rescript/bindings/Axios.res @@ -5,4 +5,10 @@ type reqOptions = { "X-Requested-With": string } } -@module("axios") external post: (string, Types.storeCommentData, reqOptions) => promise = "post" + +type commentData = { + author: string, + text: string +} + +@module("axios") external post: (string, commentData, reqOptions) => promise = "post" From e7bde797971ad9043f31808dcb84cc3dcb9fdfbd Mon Sep 17 00:00:00 2001 From: yassa Date: Fri, 3 Nov 2023 15:11:04 +0200 Subject: [PATCH 23/30] format rescript files --- app/views/pages/rescript.html.erb | 2 +- .../comments/rescript/Actions/Actions.res | 25 ++-- .../rescript/CommentForm/CommentForm.res | 124 +++++++++--------- .../rescript/CommentForm/CommentFormTypes.res | 10 +- .../CommentForm/forms/HorizontalForm.res | 29 ++-- .../rescript/CommentForm/forms/InlineForm.res | 16 +-- .../CommentForm/forms/StackedFrom.res | 26 +--- .../CommentList/AlertError/AlertError.res | 10 +- .../rescript/CommentList/Comment/Comment.res | 12 +- .../rescript/CommentList/CommentList.res | 25 ++-- .../comments/rescript/Header/Header.res | 14 +- .../comments/rescript/ReScriptShow.res | 55 +++++--- .../comments/rescript/ReScriptShowTypes.res | 6 +- .../comments/rescript/bindings/Axios.res | 7 +- .../comments/rescript/bindings/Marked.res | 4 +- .../bindings/ReactTransitionGroup.res | 14 +- package.json | 1 + 17 files changed, 175 insertions(+), 205 deletions(-) diff --git a/app/views/pages/rescript.html.erb b/app/views/pages/rescript.html.erb index c218d5cf..8afe2d40 100644 --- a/app/views/pages/rescript.html.erb +++ b/app/views/pages/rescript.html.erb @@ -1 +1 @@ -<%= react_component "RescriptShow", prerender: false %> +<%= react_component "RescriptShow", prerender: true %> diff --git a/client/app/bundles/comments/rescript/Actions/Actions.res b/client/app/bundles/comments/rescript/Actions/Actions.res index a72e0168..c9da26e3 100644 --- a/client/app/bundles/comments/rescript/Actions/Actions.res +++ b/client/app/bundles/comments/rescript/Actions/Actions.res @@ -1,7 +1,7 @@ module Create = { type t = { author: string, - text: string + text: string, } let storeComment = async (comment: t) => { @@ -9,15 +9,16 @@ module Create = { "comments.json", { author: comment.author, - text: comment.text + text: comment.text, }, { responseType: "json", - headers: { // see https://github.com/shakacode/react_on_rails/blob/249c69812474e0f532df432581bf5e618df0e1ec/node_package/src/Authenticity.ts#L13C1-L18C1 + 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", - } - } + }, + }, ) } } @@ -26,25 +27,23 @@ module Fetch = { type t = { author: string, text: string, - id: int + id: int, } type comments = array - type commentsRes = { - comments: comments - } + type commentsRes = {comments: comments} let fetchComments = async (): result => { 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) + id: field.required(. "id", int), }) let jsonComments = Json.Decode.object(field => { @@ -52,8 +51,8 @@ module Fetch = { }) switch jsonRes->Json.decode(jsonComments) { - | Ok(decodedRes) => Ok(decodedRes.comments) - | Error(e) => Error(e) + | Ok(decodedRes) => Ok(decodedRes.comments) + | Error(e) => Error(e) } } } diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index 4df2a97f..a7319291 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -1,99 +1,95 @@ let reducer = ( - state: CommentFormTypes.state, - action: CommentFormTypes.action + state: CommentFormTypes.state, + action: CommentFormTypes.action, ): CommentFormTypes.state => { - switch (action) { + switch action { | SetAuthor(author) => {...state, author} | SetText(text) => {...state, text} - | SetFormType(form) => {...state, form: form} + | SetFormType(form) => {...state, form} } } - @react.component -let make = (~storeComment: ReScriptShowTypes.storeComment, ~disabled: bool, ~storeCommentError: bool) => { +let make = ( + ~storeComment: ReScriptShowTypes.storeComment, + ~disabled: bool, + ~storeCommentError: bool, +) => { let (state, dispatch) = React.useReducer( - reducer, { + reducer, + { author: "", text: "", - form: Horizontal - } + form: Horizontal, + }, ) - let handleAuthorChange = (event) => { + let handleAuthorChange = event => { let value = ReactEvent.Form.currentTarget(event)["value"] SetAuthor(value)->dispatch } - let handleTextChange = (event) => { + let handleTextChange = event => { let value = ReactEvent.Form.currentTarget(event)["value"] SetText(value)->dispatch } - let handleSubmit = (event) => { + let handleSubmit = event => { ReactEvent.Form.preventDefault(event) storeComment({author: state.author, text: state.text}) } - let forms: array = - [ + let forms: array = [ {formName: "Horizontal Form", formType: Horizontal}, {formName: "Inline Form", formType: Inline}, - {formName: "Stacked Form", formType: Stacked} + {formName: "Stacked Form", formType: Stacked}, ]
    - { - forms - ->Array.map(form - => ( - - ) - )->React.array - } + {forms + ->Array.map(form => + + ) + ->React.array}

    - { - switch state.form { - | Horizontal - => - | Stacked - => - | Inline - => - } - } - - { - storeCommentError ? : React.null - } + {switch state.form { + | Horizontal => + + | Stacked => + + | Inline => + + }} + {storeCommentError ? : React.null}
    } diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res b/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res index 60c7e8b3..94bf2c83 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res @@ -2,16 +2,16 @@ type formDisplay = Horizontal | Inline | Stacked type formData = { formName: string, - formType: formDisplay + formType: formDisplay, } type state = { author: string, text: string, - form: formDisplay + form: formDisplay, } type action = - | SetAuthor(string) - | SetText(string) - | SetFormType(formDisplay) + | SetAuthor(string) + | SetText(string) + | SetFormType(formDisplay) diff --git a/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res b/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res index 8f9bfd6d..8c4bbab9 100644 --- a/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/forms/HorizontalForm.res @@ -1,40 +1,33 @@ @react.component -let make = ( - ~author, - ~handleAuthorChange, - ~text, - ~handleTextChange, - ~handleSubmit, - ~disabled - ) => { - +let make = (~author, ~handleAuthorChange, ~text, ~handleTextChange, ~handleSubmit, ~disabled) => { +
    - - {"Name"->React.string} +
    -
    - +
    -
    -
    - + { - { + + disabled>
    -
    -
    { - +let make = (~author, ~handleAuthorChange, ~text, ~handleTextChange, ~handleSubmit, ~disabled) => { +
    - - {"Name"->React.string} +
    -
    - +
    -
    { enter: css["elementEnter"], enterActive: css["elementEnterActive"], exit: css["elementLeave"], - exitActive: css["elementLeaveActive"] + exitActive: css["elementLeaveActive"], } // The 500 must correspond to the 0.5s in: @@ -17,10 +17,10 @@ let make = (~errorMsg: string) => { key="commentFetchError" nodeRef={nodeRef} timeout={500} - classNames={cssTransitionGroupClassNames} - > -
    - {errorMsg->React.string} + classNames={cssTransitionGroupClassNames}> +
    + {errorMsg->React.string}
    } diff --git a/client/app/bundles/comments/rescript/CommentList/Comment/Comment.res b/client/app/bundles/comments/rescript/CommentList/Comment/Comment.res index 19a26862..817fe6b1 100644 --- a/client/app/bundles/comments/rescript/CommentList/Comment/Comment.res +++ b/client/app/bundles/comments/rescript/CommentList/Comment/Comment.res @@ -1,21 +1,19 @@ @react.component let make = (~comment: Actions.Fetch.t, ~cssTransitionGroupClassNames) => { let rawMarkup = Marked.marked(comment.text, {gfm: true}) - let innerHTML = { "__html": rawMarkup } + let innerHTML = {"__html": rawMarkup} let nodeRef = React.useRef(Js.Nullable.null) - + // The 500 must correspond to the 0.5s in: // ../../RescriptShow.module.scss:9 + classNames=cssTransitionGroupClassNames>
    -

    {comment.author->React.string}

    +

    {comment.author->React.string}

    - } diff --git a/client/app/bundles/comments/rescript/CommentList/CommentList.res b/client/app/bundles/comments/rescript/CommentList/CommentList.res index 499ed258..f190d0b2 100644 --- a/client/app/bundles/comments/rescript/CommentList/CommentList.res +++ b/client/app/bundles/comments/rescript/CommentList/CommentList.res @@ -6,26 +6,19 @@ let make = (~comments: Actions.Fetch.comments, ~fetchCommentsError: bool) => { enter: css["elementEnter"], enterActive: css["elementEnterActive"], exit: css["elementLeave"], - exitActive: css["elementLeaveActive"] + exitActive: css["elementLeaveActive"], }
    - { - fetchCommentsError ? : React.null - } + {fetchCommentsError ? : React.null} - { - comments->Array.map( - comment => - Int.toString - } - /> - )->React.array - } + {comments + ->Array.map(comment => + Int.toString} + /> + ) + ->React.array}
    } diff --git a/client/app/bundles/comments/rescript/Header/Header.res b/client/app/bundles/comments/rescript/Header/Header.res index 2da60bdd..8c794489 100644 --- a/client/app/bundles/comments/rescript/Header/Header.res +++ b/client/app/bundles/comments/rescript/Header/Header.res @@ -1,6 +1,7 @@ @react.component let make = () => { -
    + } diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index 107070a8..2e2975aa 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,30 +1,31 @@ let reducer = ( - state: ReScriptShowTypes.state, - action: ReScriptShowTypes.action + state: ReScriptShowTypes.state, + action: ReScriptShowTypes.action, ): ReScriptShowTypes.state => { - switch (action) { + switch action { | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: false}} | SetFetchError(error) => {...state, status: {...state.status, commentsFetchError: error}} | SetStoreError(error) => {...state, status: {...state.status, commentStoreError: error}} - | SetSavingStatus(saving) => {...state, status: {...state.status, saving: saving}} + | SetSavingStatus(saving) => {...state, status: {...state.status, saving}} } } @react.component let default = () => { let (state, dispatch) = React.useReducer( - reducer, { + reducer, + { comments: ([]: Actions.Fetch.comments), status: { commentsFetchError: false, commentStoreError: false, - saving: Free - } - } + saving: Free, + }, + }, ) let storeComment: ReScriptShowTypes.storeComment = (newComment: Actions.Create.t) => { - SetStoreError(false)->dispatch + SetStoreError(false)->dispatch SetSavingStatus(BusySaving)->dispatch let saveAndFetchComments = async () => { try { @@ -37,13 +38,13 @@ let default = () => { | Error(_) => SetFetchError(true)->dispatch } } catch { - | _ => SetStoreError(true)->dispatch + | _ => SetStoreError(true)->dispatch } } saveAndFetchComments()->ignore } - React.useEffect1((_) => { + React.useEffect1(_ => { let fetchData = async () => { let comments = await Actions.Fetch.fetchComments() switch comments { @@ -55,20 +56,34 @@ let default = () => { fetchData()->ignore None }, []) - +
    -

    {"Rescript + Rails Backend (with "->React.string}{"react_on_rails gem"->React.string}{")"->React.string}

    +

    + {"Rescript + Rails Backend (with "->React.string} + + {"react_on_rails gem"->React.string} + + {")"->React.string} +

    -

    {"Comments"->React.string}

    +

    {"Comments"->React.string}

      -
    • {"Text supports Github Flavored Markdown."->React.string}
    • -
    • {"Comments older than 24 hours are deleted."->React.string}
    • -
    • {"Name is preserved. Text is reset, between submits"->React.string}
    • -
    • {"To see Action Cable instantly update two browsers, open two browsers and submit a comment!"->React.string}
    • +
    • {"Text supports Github Flavored Markdown."->React.string}
    • +
    • {"Comments older than 24 hours are deleted."->React.string}
    • +
    • {"Name is preserved. Text is reset, between submits"->React.string}
    • +
    • + {"To see Action Cable instantly update two browsers, open two browsers and submit a comment!"->React.string} +
    - true; | Free => false}} storeCommentError={state.status.commentStoreError} /> + true + | Free => false + }} + storeCommentError={state.status.commentStoreError} + />
    diff --git a/client/app/bundles/comments/rescript/ReScriptShowTypes.res b/client/app/bundles/comments/rescript/ReScriptShowTypes.res index 407c3b94..52838c41 100644 --- a/client/app/bundles/comments/rescript/ReScriptShowTypes.res +++ b/client/app/bundles/comments/rescript/ReScriptShowTypes.res @@ -3,12 +3,12 @@ type savingStatus = Free | BusySaving type status = { commentsFetchError: bool, commentStoreError: bool, - saving: savingStatus + saving: savingStatus, } type state = { comments: Actions.Fetch.comments, - status: status + status: status, } type action = @@ -17,4 +17,4 @@ type action = | SetStoreError(bool) | SetSavingStatus(savingStatus) -type storeComment = (Actions.Create.t) => unit +type storeComment = Actions.Create.t => unit diff --git a/client/app/bundles/comments/rescript/bindings/Axios.res b/client/app/bundles/comments/rescript/bindings/Axios.res index 39fa3cd3..fd330d96 100644 --- a/client/app/bundles/comments/rescript/bindings/Axios.res +++ b/client/app/bundles/comments/rescript/bindings/Axios.res @@ -1,14 +1,11 @@ type reqOptions = { responseType: string, - headers: { - "X-CSRF-Token": option, - "X-Requested-With": string - } + headers: {"X-CSRF-Token": option, "X-Requested-With": string}, } type commentData = { author: string, - text: string + text: string, } @module("axios") external post: (string, commentData, reqOptions) => promise = "post" diff --git a/client/app/bundles/comments/rescript/bindings/Marked.res b/client/app/bundles/comments/rescript/bindings/Marked.res index 2a16a279..782b00be 100644 --- a/client/app/bundles/comments/rescript/bindings/Marked.res +++ b/client/app/bundles/comments/rescript/bindings/Marked.res @@ -1,4 +1,2 @@ -type markedOptions = { - gfm: bool -} +type markedOptions = {gfm: bool} @module("marked") external marked: (string, markedOptions) => string = "marked" diff --git a/client/app/bundles/comments/rescript/bindings/ReactTransitionGroup.res b/client/app/bundles/comments/rescript/bindings/ReactTransitionGroup.res index d84b327b..5acdd747 100644 --- a/client/app/bundles/comments/rescript/bindings/ReactTransitionGroup.res +++ b/client/app/bundles/comments/rescript/bindings/ReactTransitionGroup.res @@ -3,7 +3,7 @@ module TransitionGroup = { external make: ( ~children: React.element, ~className: string, - ~component: string + ~component: string, ) => React.element = "TransitionGroup" } @@ -12,15 +12,15 @@ module CSSTransition = { enter: string, enterActive: string, exit: string, - exitActive: string + exitActive: string, } @react.component @module("react-transition-group") external make: ( - ~children: React.element, - ~key: string, - ~timeout: int, - ~nodeRef: React.ref>, - ~classNames: t + ~children: React.element, + ~key: string, + ~timeout: int, + ~nodeRef: React.ref>, + ~classNames: t, ) => React.element = "CSSTransition" } diff --git a/package.json b/package.json index d35356c7..f8fbf322 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "homepage": "https://github.com/shakacode/react-webpack-rails-tutorial", "scripts": { "res:clean": "rescript clean", + "res:format": "rescript format -all", "res:dev": "yarn res:clean && rescript build -w", "res:build": "yarn res:clean && rescript build", "lint:eslint": "yarn eslint client --ext \".js,.jsx,.ts\"", From e328420b13d9d70084b892bd5f06ece8b0bbb380 Mon Sep 17 00:00:00 2001 From: yassa Date: Fri, 3 Nov 2023 23:50:43 +0200 Subject: [PATCH 24/30] remove the types files --- .../rescript/CommentForm/CommentForm.res | 33 +++++++++++++------ .../rescript/CommentForm/CommentFormTypes.res | 17 ---------- .../comments/rescript/ReScriptShow.res | 26 ++++++++++++--- .../comments/rescript/ReScriptShowTypes.res | 20 ----------- 4 files changed, 44 insertions(+), 52 deletions(-) delete mode 100644 client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res delete mode 100644 client/app/bundles/comments/rescript/ReScriptShowTypes.res diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index a7319291..51cbcc95 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -1,7 +1,24 @@ -let reducer = ( - state: CommentFormTypes.state, - action: CommentFormTypes.action, -): CommentFormTypes.state => { +type storeComment = Actions.Create.t => unit + +type formDisplay = Horizontal | Inline | Stacked + +type formData = { + formName: string, + formType: formDisplay, +} + +type state = { + author: string, + text: string, + form: formDisplay, +} + +type action = + | SetAuthor(string) + | SetText(string) + | SetFormType(formDisplay) + +let reducer = (state: state, action: action): state => { switch action { | SetAuthor(author) => {...state, author} | SetText(text) => {...state, text} @@ -10,11 +27,7 @@ let reducer = ( } @react.component -let make = ( - ~storeComment: ReScriptShowTypes.storeComment, - ~disabled: bool, - ~storeCommentError: bool, -) => { +let make = (~storeComment: storeComment, ~disabled: bool, ~storeCommentError: bool) => { let (state, dispatch) = React.useReducer( reducer, { @@ -39,7 +52,7 @@ let make = ( storeComment({author: state.author, text: state.text}) } - let forms: array = [ + let forms: array = [ {formName: "Horizontal Form", formType: Horizontal}, {formName: "Inline Form", formType: Inline}, {formName: "Stacked Form", formType: Stacked}, diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res b/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res deleted file mode 100644 index 94bf2c83..00000000 --- a/client/app/bundles/comments/rescript/CommentForm/CommentFormTypes.res +++ /dev/null @@ -1,17 +0,0 @@ -type formDisplay = Horizontal | Inline | Stacked - -type formData = { - formName: string, - formType: formDisplay, -} - -type state = { - author: string, - text: string, - form: formDisplay, -} - -type action = - | SetAuthor(string) - | SetText(string) - | SetFormType(formDisplay) diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index 2e2975aa..e4d9fd14 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,7 +1,23 @@ -let reducer = ( - state: ReScriptShowTypes.state, - action: ReScriptShowTypes.action, -): ReScriptShowTypes.state => { +type savingStatus = Free | BusySaving + +type status = { + commentsFetchError: bool, + commentStoreError: bool, + saving: savingStatus, +} + +type state = { + comments: Actions.Fetch.comments, + status: status, +} + +type action = + | SetComments(Actions.Fetch.comments) + | SetFetchError(bool) + | SetStoreError(bool) + | SetSavingStatus(savingStatus) + +let reducer = (state: state, action: action): state => { switch action { | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: false}} | SetFetchError(error) => {...state, status: {...state.status, commentsFetchError: error}} @@ -24,7 +40,7 @@ let default = () => { }, ) - let storeComment: ReScriptShowTypes.storeComment = (newComment: Actions.Create.t) => { + let storeComment: CommentForm.storeComment = (newComment: Actions.Create.t) => { SetStoreError(false)->dispatch SetSavingStatus(BusySaving)->dispatch let saveAndFetchComments = async () => { diff --git a/client/app/bundles/comments/rescript/ReScriptShowTypes.res b/client/app/bundles/comments/rescript/ReScriptShowTypes.res deleted file mode 100644 index 52838c41..00000000 --- a/client/app/bundles/comments/rescript/ReScriptShowTypes.res +++ /dev/null @@ -1,20 +0,0 @@ -type savingStatus = Free | BusySaving - -type status = { - commentsFetchError: bool, - commentStoreError: bool, - saving: savingStatus, -} - -type state = { - comments: Actions.Fetch.comments, - status: status, -} - -type action = - | SetComments(Actions.Fetch.comments) - | SetFetchError(bool) - | SetStoreError(bool) - | SetSavingStatus(savingStatus) - -type storeComment = Actions.Create.t => unit From b50e9e39a14de4e074ea94af74231d5fdf8ee74c Mon Sep 17 00:00:00 2001 From: yassa Date: Fri, 10 Nov 2023 12:44:48 +0200 Subject: [PATCH 25/30] update error rescript page state design --- .../comments/rescript/Actions/Actions.res | 9 +- .../comments/rescript/Header/Header.bs.mjs | 95 ------------------- .../comments/rescript/ReScriptShow.res | 73 +++++++------- .../comments/rescript/bindings/Axios.res | 12 +-- 4 files changed, 47 insertions(+), 142 deletions(-) delete mode 100644 client/app/bundles/comments/rescript/Header/Header.bs.mjs diff --git a/client/app/bundles/comments/rescript/Actions/Actions.res b/client/app/bundles/comments/rescript/Actions/Actions.res index c9da26e3..d6b15713 100644 --- a/client/app/bundles/comments/rescript/Actions/Actions.res +++ b/client/app/bundles/comments/rescript/Actions/Actions.res @@ -1,3 +1,4 @@ +// TODO : use only one way to make http requests either Axios or Fetch module Create = { type t = { author: string, @@ -8,12 +9,12 @@ module Create = { let _ = await Axios.post( "comments.json", { - author: comment.author, - text: comment.text, + "author": comment.author, + "text": comment.text, }, { - responseType: "json", - headers: { + "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", diff --git a/client/app/bundles/comments/rescript/Header/Header.bs.mjs b/client/app/bundles/comments/rescript/Header/Header.bs.mjs deleted file mode 100644 index 45c9f2a1..00000000 --- a/client/app/bundles/comments/rescript/Header/Header.bs.mjs +++ /dev/null @@ -1,95 +0,0 @@ -// Generated by ReScript, PLEASE EDIT WITH CARE - -import * as JsxRuntime from "react/jsx-runtime"; - -function Header(props) { - return JsxRuntime.jsxs("div", { - children: [ - JsxRuntime.jsxs("ul", { - children: [ - JsxRuntime.jsxs("li", { - children: [ - JsxRuntime.jsx("a", { - children: "Can ShakaCode Help You? ", - href: "https://blog.shakacode.com/can-shakacode-help-you-4a5b1e5a8a63#.jex6tg9w9" - }), - "We're actively seeking new projects with React, React-Native, or Ruby on Rails." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "See the ", - JsxRuntime.jsx("a", { - children: "github.com/shakacode/react-webpack-rails-tutorial/README.md ", - href: "https://github.com/shakacode/react-webpack-rails-tutorial/blob/master/README.md" - }), - "for details of how this example site was built." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "Read ", - JsxRuntime.jsx("a", { - children: "Documentation for React on Rails", - href: "https://shakacode.gitbooks.io/react-on-rails/content/" - }), - JsxRuntime.jsx("a", { - children: "The React on Rails Doctrine.", - href: "https://www.shakacode.com/blog/the-react-on-rails-doctrine" - }) - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "See our React Native Client: ", - JsxRuntime.jsx("a", { - children: "shakacode/react-native-tutorial", - href: "https://github.com/shakacode/react-native-tutorial" - }), - "." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - "Watch the ", - JsxRuntime.jsx("a", { - children: "React On Rails Tutorial Series", - href: "https://www.youtube.com/playlist?list=PL5VAKH-U1M6dj84BApfUtvBjvF-0-JfEU" - }), - "." - ] - }), - JsxRuntime.jsxs("li", { - children: [ - JsxRuntime.jsx("a", { - children: "ShakaCode", - href: "http://www.shakacode.com" - }), - " is doing support for React on Rails, \ - including a private Slack channel, \ - source code reviews, and pair programming sessions. ", - JsxRuntime.jsx("b", { - children: JsxRuntime.jsx("a", { - children: "Click here", - href: "http://www.shakacode.com/work/index.html" - }) - }), - " for more information." - ] - }) - ] - }), - JsxRuntime.jsx("hr", { - className: "border-t my-8" - }) - ], - className: "prose max-w-full prose-a:text-sky-700 prose-li:my-0 prose-code:text-rose-600 prose-code:bg-yellow-100 prose-headings:text-gray-700" - }); -} - -var make = Header; - -export { - make , -} -/* react/jsx-runtime Not a pure module */ diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index e4d9fd14..a6752470 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,28 +1,28 @@ -type savingStatus = Free | BusySaving +type commentsStoreStatus = NotStarted | BusyLoading | StoreError -type status = { - commentsFetchError: bool, - commentStoreError: bool, - saving: savingStatus, -} +type commentsFetchStatus = + | FetchError + | CommentsFetched(Actions.Fetch.comments) type state = { - comments: Actions.Fetch.comments, - status: status, + commentsFetchStatus: commentsFetchStatus, + commentsStoreStatus: commentsStoreStatus, } type action = | SetComments(Actions.Fetch.comments) - | SetFetchError(bool) - | SetStoreError(bool) - | SetSavingStatus(savingStatus) + | SetFetchError + | SetStoreError + | ClearStoreError + | SetStoreStatusLoading let reducer = (state: state, action: action): state => { switch action { - | SetComments(comments) => {comments, status: {...state.status, commentsFetchError: false}} - | SetFetchError(error) => {...state, status: {...state.status, commentsFetchError: error}} - | SetStoreError(error) => {...state, status: {...state.status, commentStoreError: error}} - | SetSavingStatus(saving) => {...state, status: {...state.status, saving}} + | SetComments(comments) => {...state, commentsFetchStatus: CommentsFetched(comments)} + | SetFetchError => {...state, commentsFetchStatus: FetchError} + | SetStoreError => {...state, commentsStoreStatus: StoreError} + | ClearStoreError => {...state, commentsStoreStatus: NotStarted} + | SetStoreStatusLoading => {...state, commentsStoreStatus: BusyLoading} } } @@ -31,30 +31,25 @@ let default = () => { let (state, dispatch) = React.useReducer( reducer, { - comments: ([]: Actions.Fetch.comments), - status: { - commentsFetchError: false, - commentStoreError: false, - saving: Free, - }, + commentsFetchStatus: CommentsFetched(([]: Actions.Fetch.comments)), + commentsStoreStatus: NotStarted, }, ) let storeComment: CommentForm.storeComment = (newComment: Actions.Create.t) => { - SetStoreError(false)->dispatch - SetSavingStatus(BusySaving)->dispatch + SetStoreStatusLoading->dispatch let saveAndFetchComments = async () => { try { let _ = await Actions.Create.storeComment(newComment) - SetSavingStatus(Free)->dispatch + ClearStoreError->dispatch let comments = await Actions.Fetch.fetchComments() switch comments { | Ok(comments) => SetComments(comments)->dispatch - | Error(_) => SetFetchError(true)->dispatch + | Error(_) => SetFetchError->dispatch } } catch { - | _ => SetStoreError(true)->dispatch + | _ => SetStoreError->dispatch } } saveAndFetchComments()->ignore @@ -65,7 +60,7 @@ let default = () => { let comments = await Actions.Fetch.fetchComments() switch comments { | Ok(comments) => SetComments(comments)->dispatch - | Error(_) => SetFetchError(true)->dispatch + | Error(_) => SetFetchError->dispatch } } @@ -94,13 +89,27 @@ let default = () => { true - | Free => false + disabled={switch state.commentsStoreStatus { + | BusyLoading => true + | _ => false + }} + storeCommentError={switch state.commentsStoreStatus { + | StoreError => true + | _ => false + }} + /> + comments + | _ => [] + }} + fetchCommentsError={switch state.commentsFetchStatus { + | FetchError => true + | _ => false }} - storeCommentError={state.status.commentStoreError} /> -
    } diff --git a/client/app/bundles/comments/rescript/bindings/Axios.res b/client/app/bundles/comments/rescript/bindings/Axios.res index fd330d96..932abc48 100644 --- a/client/app/bundles/comments/rescript/bindings/Axios.res +++ b/client/app/bundles/comments/rescript/bindings/Axios.res @@ -1,11 +1 @@ -type reqOptions = { - responseType: string, - headers: {"X-CSRF-Token": option, "X-Requested-With": string}, -} - -type commentData = { - author: string, - text: string, -} - -@module("axios") external post: (string, commentData, reqOptions) => promise = "post" +@module("axios") external post: (string, {..}, {..}) => promise = "post" From 9b8e357091bd1c9bafce7a721e7283c5ce4f93b7 Mon Sep 17 00:00:00 2001 From: yassa Date: Mon, 13 Nov 2023 16:43:02 +0200 Subject: [PATCH 26/30] refactor switch statements --- .../bundles/comments/rescript/ReScriptShow.res | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index a6752470..bcb7101f 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,4 +1,4 @@ -type commentsStoreStatus = NotStarted | BusyLoading | StoreError +type commentsStoreStatus = Idle | BusyLoading | StoreError type commentsFetchStatus = | FetchError @@ -21,7 +21,7 @@ let reducer = (state: state, action: action): state => { | SetComments(comments) => {...state, commentsFetchStatus: CommentsFetched(comments)} | SetFetchError => {...state, commentsFetchStatus: FetchError} | SetStoreError => {...state, commentsStoreStatus: StoreError} - | ClearStoreError => {...state, commentsStoreStatus: NotStarted} + | ClearStoreError => {...state, commentsStoreStatus: Idle} | SetStoreStatusLoading => {...state, commentsStoreStatus: BusyLoading} } } @@ -32,7 +32,7 @@ let default = () => { reducer, { commentsFetchStatus: CommentsFetched(([]: Actions.Fetch.comments)), - commentsStoreStatus: NotStarted, + commentsStoreStatus: Idle, }, ) @@ -91,11 +91,13 @@ let default = () => { storeComment disabled={switch state.commentsStoreStatus { | BusyLoading => true - | _ => false + | Idle + | StoreError => false }} storeCommentError={switch state.commentsStoreStatus { | StoreError => true - | _ => false + | Idle + | BusyLoading => false }} /> { // to either render an error messege or the comment list not both comments={switch state.commentsFetchStatus { | CommentsFetched(comments) => comments - | _ => [] + | FetchError => [] }} fetchCommentsError={switch state.commentsFetchStatus { | FetchError => true - | _ => false + | CommentsFetched(_) => false }} />
    From 1a22a4566af97832eec91d48e4691d95641f15f5 Mon Sep 17 00:00:00 2001 From: yassa Date: Tue, 14 Nov 2023 11:16:27 +0200 Subject: [PATCH 27/30] move store comment state to the form component --- .../rescript/CommentForm/CommentForm.res | 41 +++++++++- .../rescript/CommentList/CommentList.res | 3 +- .../comments/rescript/ReScriptShow.res | 75 ++++--------------- 3 files changed, 51 insertions(+), 68 deletions(-) diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index 51cbcc95..2819042b 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -1,7 +1,7 @@ -type storeComment = Actions.Create.t => unit - type formDisplay = Horizontal | Inline | Stacked +type commentsStoreStatus = Idle | BusyLoading | StoreError + type formData = { formName: string, formType: formDisplay, @@ -11,32 +11,61 @@ type state = { author: string, text: string, form: formDisplay, + commentsStoreStatus: commentsStoreStatus, } type action = | SetAuthor(string) | SetText(string) | SetFormType(formDisplay) + | SetStoreError + | ClearStoreError + | SetStoreStatusLoading let reducer = (state: state, action: action): state => { switch action { | SetAuthor(author) => {...state, author} | SetText(text) => {...state, text} | SetFormType(form) => {...state, form} + | SetStoreError => {...state, commentsStoreStatus: StoreError} + | ClearStoreError => {...state, commentsStoreStatus: Idle} + | SetStoreStatusLoading => {...state, commentsStoreStatus: BusyLoading} } } @react.component -let make = (~storeComment: storeComment, ~disabled: bool, ~storeCommentError: bool) => { +let make = ( ~fetchData ) => { let (state, dispatch) = React.useReducer( reducer, { author: "", text: "", form: Horizontal, + commentsStoreStatus: Idle, }, ) + let disabled = React.useMemo1(() => {switch state.commentsStoreStatus { + | BusyLoading => true + | Idle + | StoreError => false + }}, [state.commentsStoreStatus]) + + let storeComment = (newComment: Actions.Create.t) => { + SetStoreStatusLoading->dispatch + let saveAndFetchComments = async () => { + try { + let _ = await Actions.Create.storeComment(newComment) + ClearStoreError->dispatch + + await fetchData(); + } catch { + | _ => SetStoreError->dispatch + } + } + saveAndFetchComments()->ignore + } + let handleAuthorChange = event => { let value = ReactEvent.Form.currentTarget(event)["value"] SetAuthor(value)->dispatch @@ -103,6 +132,10 @@ let make = (~storeComment: storeComment, ~disabled: bool, ~storeCommentError: bo disabled /> }} - {storeCommentError ? : React.null} + {switch state.commentsStoreStatus { + | StoreError => + | Idle + | BusyLoading => React.null + }}
    } diff --git a/client/app/bundles/comments/rescript/CommentList/CommentList.res b/client/app/bundles/comments/rescript/CommentList/CommentList.res index f190d0b2..1a433257 100644 --- a/client/app/bundles/comments/rescript/CommentList/CommentList.res +++ b/client/app/bundles/comments/rescript/CommentList/CommentList.res @@ -1,7 +1,7 @@ @module("../ReScriptShow.module.scss") external css: {..} = "default" @react.component -let make = (~comments: Actions.Fetch.comments, ~fetchCommentsError: bool) => { +let make = (~comments: Actions.Fetch.comments) => { let cssTransitionGroupClassNames: ReactTransitionGroup.CSSTransition.t = { enter: css["elementEnter"], enterActive: css["elementEnterActive"], @@ -10,7 +10,6 @@ let make = (~comments: Actions.Fetch.comments, ~fetchCommentsError: bool) => { }
    - {fetchCommentsError ? : React.null} {comments ->Array.map(comment => diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index bcb7101f..c1d8003f 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -1,28 +1,19 @@ -type commentsStoreStatus = Idle | BusyLoading | StoreError - type commentsFetchStatus = | FetchError | CommentsFetched(Actions.Fetch.comments) type state = { commentsFetchStatus: commentsFetchStatus, - commentsStoreStatus: commentsStoreStatus, } type action = | SetComments(Actions.Fetch.comments) | SetFetchError - | SetStoreError - | ClearStoreError - | SetStoreStatusLoading -let reducer = (state: state, action: action): state => { +let reducer = (_, action: action): state => { switch action { - | SetComments(comments) => {...state, commentsFetchStatus: CommentsFetched(comments)} - | SetFetchError => {...state, commentsFetchStatus: FetchError} - | SetStoreError => {...state, commentsStoreStatus: StoreError} - | ClearStoreError => {...state, commentsStoreStatus: Idle} - | SetStoreStatusLoading => {...state, commentsStoreStatus: BusyLoading} + | SetComments(comments) => {commentsFetchStatus: CommentsFetched(comments)} + | SetFetchError => {commentsFetchStatus: FetchError} } } @@ -32,38 +23,18 @@ let default = () => { reducer, { commentsFetchStatus: CommentsFetched(([]: Actions.Fetch.comments)), - commentsStoreStatus: Idle, }, ) - let storeComment: CommentForm.storeComment = (newComment: Actions.Create.t) => { - SetStoreStatusLoading->dispatch - let saveAndFetchComments = async () => { - try { - let _ = await Actions.Create.storeComment(newComment) - ClearStoreError->dispatch - - let comments = await Actions.Fetch.fetchComments() - switch comments { - | Ok(comments) => SetComments(comments)->dispatch - | Error(_) => SetFetchError->dispatch - } - } catch { - | _ => SetStoreError->dispatch - } + let fetchData = async () => { + let comments = await Actions.Fetch.fetchComments() + switch comments { + | Ok(comments) => SetComments(comments)->dispatch + | Error(_) => SetFetchError->dispatch } - saveAndFetchComments()->ignore } React.useEffect1(_ => { - let fetchData = async () => { - let comments = await Actions.Fetch.fetchComments() - switch comments { - | Ok(comments) => SetComments(comments)->dispatch - | Error(_) => SetFetchError->dispatch - } - } - fetchData()->ignore None }, []) @@ -87,31 +58,11 @@ let default = () => { {"To see Action Cable instantly update two browsers, open two browsers and submit a comment!"->React.string} - true - | Idle - | StoreError => false - }} - storeCommentError={switch state.commentsStoreStatus { - | StoreError => true - | Idle - | BusyLoading => false - }} - /> - comments - | FetchError => [] - }} - fetchCommentsError={switch state.commentsFetchStatus { - | FetchError => true - | CommentsFetched(_) => false - }} - /> + + {switch state.commentsFetchStatus { + | FetchError => + | CommentsFetched(comments) => + }}
    } From 0edbefdf35023c6405dcf203dae0d3513b21ab13 Mon Sep 17 00:00:00 2001 From: yassa Date: Tue, 14 Nov 2023 11:19:26 +0200 Subject: [PATCH 28/30] format rescript --- .../rescript/CommentForm/CommentForm.res | 16 +++++++++------- .../bundles/comments/rescript/ReScriptShow.res | 4 +--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index 2819042b..9dc7062a 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -34,7 +34,7 @@ let reducer = (state: state, action: action): state => { } @react.component -let make = ( ~fetchData ) => { +let make = (~fetchData) => { let (state, dispatch) = React.useReducer( reducer, { @@ -45,11 +45,13 @@ let make = ( ~fetchData ) => { }, ) - let disabled = React.useMemo1(() => {switch state.commentsStoreStatus { - | BusyLoading => true - | Idle - | StoreError => false - }}, [state.commentsStoreStatus]) + let disabled = React.useMemo1(() => { + switch state.commentsStoreStatus { + | BusyLoading => true + | Idle + | StoreError => false + } + }, [state.commentsStoreStatus]) let storeComment = (newComment: Actions.Create.t) => { SetStoreStatusLoading->dispatch @@ -58,7 +60,7 @@ let make = ( ~fetchData ) => { let _ = await Actions.Create.storeComment(newComment) ClearStoreError->dispatch - await fetchData(); + await fetchData() } catch { | _ => SetStoreError->dispatch } diff --git a/client/app/bundles/comments/rescript/ReScriptShow.res b/client/app/bundles/comments/rescript/ReScriptShow.res index c1d8003f..4c64f8b2 100644 --- a/client/app/bundles/comments/rescript/ReScriptShow.res +++ b/client/app/bundles/comments/rescript/ReScriptShow.res @@ -2,9 +2,7 @@ type commentsFetchStatus = | FetchError | CommentsFetched(Actions.Fetch.comments) -type state = { - commentsFetchStatus: commentsFetchStatus, -} +type state = {commentsFetchStatus: commentsFetchStatus} type action = | SetComments(Actions.Fetch.comments) From 7ff850696b912d12e3a11af11be694303fb682ce Mon Sep 17 00:00:00 2001 From: yassa Date: Wed, 15 Nov 2023 12:40:16 +0200 Subject: [PATCH 29/30] rename the saving state --- .../rescript/CommentForm/CommentForm.res | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res index 9dc7062a..db964269 100644 --- a/client/app/bundles/comments/rescript/CommentForm/CommentForm.res +++ b/client/app/bundles/comments/rescript/CommentForm/CommentForm.res @@ -1,6 +1,12 @@ -type formDisplay = Horizontal | Inline | Stacked +type formDisplay = + | Horizontal + | Inline + | Stacked -type commentsStoreStatus = Idle | BusyLoading | StoreError +type savingStatus = + | Idle + | Saving + | Error type formData = { formName: string, @@ -11,25 +17,25 @@ type state = { author: string, text: string, form: formDisplay, - commentsStoreStatus: commentsStoreStatus, + savingStatus: savingStatus, } type action = | SetAuthor(string) | SetText(string) | SetFormType(formDisplay) - | SetStoreError - | ClearStoreError - | SetStoreStatusLoading + | SetSavingError + | ClearSavingError + | SetStoreStatusSaving let reducer = (state: state, action: action): state => { switch action { | SetAuthor(author) => {...state, author} | SetText(text) => {...state, text} | SetFormType(form) => {...state, form} - | SetStoreError => {...state, commentsStoreStatus: StoreError} - | ClearStoreError => {...state, commentsStoreStatus: Idle} - | SetStoreStatusLoading => {...state, commentsStoreStatus: BusyLoading} + | SetSavingError => {...state, savingStatus: Error} + | ClearSavingError => {...state, savingStatus: Idle} + | SetStoreStatusSaving => {...state, savingStatus: Saving} } } @@ -41,28 +47,28 @@ let make = (~fetchData) => { author: "", text: "", form: Horizontal, - commentsStoreStatus: Idle, + savingStatus: Idle, }, ) let disabled = React.useMemo1(() => { - switch state.commentsStoreStatus { - | BusyLoading => true + switch state.savingStatus { + | Saving => true | Idle - | StoreError => false + | Error => false } - }, [state.commentsStoreStatus]) + }, [state.savingStatus]) let storeComment = (newComment: Actions.Create.t) => { - SetStoreStatusLoading->dispatch + SetStoreStatusSaving->dispatch let saveAndFetchComments = async () => { try { let _ = await Actions.Create.storeComment(newComment) - ClearStoreError->dispatch + ClearSavingError->dispatch await fetchData() } catch { - | _ => SetStoreError->dispatch + | _ => SetSavingError->dispatch } } saveAndFetchComments()->ignore @@ -134,10 +140,10 @@ let make = (~fetchData) => { disabled /> }} - {switch state.commentsStoreStatus { - | StoreError => + {switch state.savingStatus { + | Error => | Idle - | BusyLoading => React.null + | Saving => React.null }}
    } From 4b107733854127b7bdba5c47a1b8da743e9db43a Mon Sep 17 00:00:00 2001 From: yassa Date: Thu, 16 Nov 2023 12:22:43 +0200 Subject: [PATCH 30/30] empty commit