├── .editorconfig
├── .gitignore
├── README.md
├── bun.lockb
├── index.html
├── netlify.toml
├── package.json
├── postcss.config.cjs
├── public
├── kiise.png
└── layered-waves.svg
├── relay.config.cjs
├── rescript.json
├── schema.graphql
├── src
├── App.js
├── App.res
├── Base64.js
├── Base64.res
├── Colophon.js
├── Colophon.res
├── Comment.js
├── Comment.res
├── CommentInput.js
├── CommentInput.res
├── CommentRow.js
├── CommentRow.res
├── CommentSection.js
├── CommentSection.res
├── DateFormat.js
├── DateFormat.res
├── EditCategories.js
├── EditCategories.res
├── ErrorBoundary.js
├── ErrorBoundary.res
├── Exc.js
├── Exc.res
├── Firebase.js
├── Firebase.res
├── FooterContainer.js
├── FooterContainer.res
├── Heroicons.js
├── Heroicons.res
├── HideUs.js
├── HideUs.res
├── Home.js
├── Home.res
├── HomeJargonListSection.js
├── HomeJargonListSection.res
├── Hooks.js
├── Hooks.res
├── Index.js
├── Index.res
├── InfiniteScroll.js
├── InfiniteScroll.res
├── Jargon.js
├── Jargon.res
├── JargonCard.js
├── JargonCard.res
├── JargonList.js
├── JargonList.res
├── JargonPost.js
├── JargonPost.res
├── JargonRandomList.js
├── JargonRandomList.res
├── LazyComponents.js
├── LazyComponents.res
├── Loader.js
├── Loader.res
├── MathJax.js
├── MathJax.res
├── MathJaxContext.js
├── MathJaxContext.res
├── MultiValueLabel.js
├── MultiValueLabel.res
├── Navbar.js
├── Navbar.res
├── NavbarContainer.js
├── NavbarContainer.res
├── NewJargon.js
├── NewJargon.res
├── NewTranslation.js
├── NewTranslation.res
├── NewlineText.js
├── NewlineText.res
├── Profile.js
├── Profile.res
├── ReactIcons.js
├── ReactIcons.res
├── ReactSocialLoginButtons.js
├── ReactSocialLoginButtons.res
├── RelatedJargons.js
├── RelatedJargons.res
├── RelayWrapper.js
├── RelayWrapper.res
├── SearchBar.js
├── SearchBar.res
├── Select.js
├── Select.res
├── SignIn.js
├── SignIn.res
├── SignInContext.js
├── SignInContext.res
├── SignInWrapper.js
├── SignInWrapper.res
├── SignOut.js
├── SignOut.res
├── Tips.js
├── Tips.res
├── TokenContext.js
├── TokenContext.res
├── Translation.js
├── Translation.res
├── Translator.js
├── Translator.res
├── Util.js
├── Util.res
├── Why.js
├── Why.res
├── Window.js
├── Window.res
├── __generated__
│ ├── ColophonQuery_graphql.js
│ ├── ColophonQuery_graphql.res
│ ├── CommentInputMutation_graphql.js
│ ├── CommentInputMutation_graphql.res
│ ├── CommentRowMutation_graphql.js
│ ├── CommentRowMutation_graphql.res
│ ├── CommentSection_jargon_graphql.js
│ ├── CommentSection_jargon_graphql.res
│ ├── EditCategoriesCategoryQuery_graphql.js
│ ├── EditCategoriesCategoryQuery_graphql.res
│ ├── EditCategoriesJargonQuery_graphql.js
│ ├── EditCategoriesJargonQuery_graphql.res
│ ├── EditCategoriesMutation_graphql.js
│ ├── EditCategoriesMutation_graphql.res
│ ├── HomeCategoryQuery_graphql.js
│ ├── HomeCategoryQuery_graphql.res
│ ├── HomeJargonListSectionQuery_graphql.js
│ ├── HomeJargonListSectionQuery_graphql.res
│ ├── JargonCard_jargon_graphql.js
│ ├── JargonCard_jargon_graphql.res
│ ├── JargonListOrderQuery_graphql.js
│ ├── JargonListOrderQuery_graphql.res
│ ├── JargonListOrderRefetchQuery_graphql.js
│ ├── JargonListOrderRefetchQuery_graphql.res
│ ├── JargonPostQuery_graphql.js
│ ├── JargonPostQuery_graphql.res
│ ├── JargonRandomListOrderQuery_graphql.js
│ ├── JargonRandomListOrderQuery_graphql.res
│ ├── NewJargonCategoryQuery_graphql.js
│ ├── NewJargonCategoryQuery_graphql.res
│ ├── NewJargonMutation_graphql.js
│ ├── NewJargonMutation_graphql.res
│ ├── NewJargonWithoutTranslationMutation_graphql.js
│ ├── NewJargonWithoutTranslationMutation_graphql.res
│ ├── NewTranslationJargonQuery_graphql.js
│ ├── NewTranslationJargonQuery_graphql.res
│ ├── NewTranslationMutation_graphql.js
│ ├── NewTranslationMutation_graphql.res
│ ├── ProfileDisplayNameMutation_graphql.js
│ ├── ProfileDisplayNameMutation_graphql.res
│ ├── RelatedJargons_jargon_graphql.js
│ ├── RelatedJargons_jargon_graphql.res
│ ├── RelaySchemaAssets_graphql.js
│ ├── RelaySchemaAssets_graphql.res
│ ├── TipsQuery_graphql.js
│ ├── TipsQuery_graphql.res
│ ├── Translation_jargon_graphql.js
│ ├── Translation_jargon_graphql.res
│ ├── WhyQuery_graphql.js
│ └── WhyQuery_graphql.res
├── firebaseConfig.js
├── main.css
├── uuid.js
└── uuid.res
├── tailwind.config.cjs
└── vite.config.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 |
7 | [*.{js,json,yml}]
8 | charset = utf-8
9 | indent_style = space
10 | indent_size = 2
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .graphql_ppx_cache
2 | .env.local
3 | .bsb.lock
4 | .merlin
5 |
6 | # Created by https://www.toptal.com/developers/gitignore/api/macOS,React,ReasonML,Emacs,yarn
7 | # Edit at https://www.toptal.com/developers/gitignore?templates=macOS,React,ReasonML,Emacs,yarn
8 |
9 | ### Emacs ###
10 | # -*- mode: gitignore; -*-
11 | *~
12 | \#*\#
13 | /.emacs.desktop
14 | /.emacs.desktop.lock
15 | *.elc
16 | auto-save-list
17 | tramp
18 | .\#*
19 |
20 | # Org-mode
21 | .org-id-locations
22 | *_archive
23 |
24 | # flymake-mode
25 | *_flymake.*
26 |
27 | # eshell files
28 | /eshell/history
29 | /eshell/lastdir
30 |
31 | # elpa packages
32 | /elpa/
33 |
34 | # reftex files
35 | *.rel
36 |
37 | # AUCTeX auto folder
38 | /auto/
39 |
40 | # cask packages
41 | .cask/
42 | dist/
43 |
44 | # Flycheck
45 | flycheck_*.el
46 |
47 | # server auth directory
48 | /server/
49 |
50 | # projectiles files
51 | .projectile
52 |
53 | # directory configuration
54 | .dir-locals.el
55 |
56 | # network security
57 | /network-security.data
58 |
59 |
60 | ### macOS ###
61 | # General
62 | .DS_Store
63 | .AppleDouble
64 | .LSOverride
65 |
66 | # Icon must end with two
67 | Icon
68 |
69 | # Thumbnails
70 | ._*
71 |
72 | # Files that might appear in the root of a volume
73 | .DocumentRevisions-V100
74 | .fseventsd
75 | .Spotlight-V100
76 | .TemporaryItems
77 | .Trashes
78 | .VolumeIcon.icns
79 | .com.apple.timemachine.donotpresent
80 |
81 | # Directories potentially created on remote AFP share
82 | .AppleDB
83 | .AppleDesktop
84 | Network Trash Folder
85 | Temporary Items
86 | .apdisk
87 |
88 | ### macOS Patch ###
89 | # iCloud generated files
90 | *.icloud
91 |
92 | ### react ###
93 | .DS_*
94 | *.log
95 | logs
96 | **/*.backup.*
97 | **/*.back.*
98 |
99 | node_modules
100 | bower_components
101 |
102 | *.sublime*
103 |
104 | psd
105 | thumb
106 | sketch
107 |
108 | ### Reasonml ###
109 | /lib
110 |
111 | ### yarn ###
112 | # https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
113 |
114 | .yarn/*
115 | !.yarn/releases
116 | !.yarn/patches
117 | !.yarn/plugins
118 | !.yarn/sdks
119 | !.yarn/versions
120 |
121 | # if you are NOT using Zero-installs, then:
122 | # comment the following lines
123 | !.yarn/cache
124 |
125 | # and uncomment the following lines
126 | # .pnp.*
127 |
128 | # End of https://www.toptal.com/developers/gitignore/api/macOS,React,ReasonML,Emacs,yarn
129 | n
130 |
131 | # Local Netlify folder
132 | .netlify
133 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # easyword.kr
2 |
3 | [](https://app.netlify.com/sites/easykoreanjargon/deploys)
4 |
5 | ## Installation
6 |
7 | ```sh
8 | bun install
9 | ```
10 |
11 | ## Build
12 |
13 | - Build: `bun build:deps`
14 | - Clean: `bun clean`
15 | - Build & watch: `bun build:watch`
16 |
17 | ## Run
18 |
19 | ```sh
20 | bun start
21 | ```
22 |
--------------------------------------------------------------------------------
/bun.lockb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zeta611/easyword/6e1414bc2cc895af2a00bb42bff1add164eec4c9/bun.lockb
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 쉬운 전문용어
9 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [[redirects]]
2 | from = "https://cse-easyword.netlify.app/*"
3 | to = "https://easyword.kr/:splat"
4 | status = 301
5 | force = true
6 |
7 | [[redirects]]
8 | from = "/*"
9 | to = "/index.html"
10 | status = 200
11 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "easyword.kr",
3 | "version": "1.0.0",
4 | "type": "module",
5 | "scripts": {
6 | "start": "concurrently \"bun run build:watch\" \"bun run relay:watch\" \"bun run dev\"",
7 | "build": "rescript",
8 | "build:deps": "rescript build -with-deps",
9 | "build:watch": "rescript build -w",
10 | "relay": "rescript-relay-compiler",
11 | "relay:watch": "rescript-relay-compiler --watch",
12 | "relay:fmt": "rescript-relay-cli format-all-graphql",
13 | "clean": "rescript clean -with-deps",
14 | "dev": "bunx --bun vite",
15 | "preview": "vite preview",
16 | "release": "vite build"
17 | },
18 | "keywords": [
19 | "rescript"
20 | ],
21 | "author": "Jay Lee ",
22 | "license": "MIT",
23 | "packageManager": "bun@1.1.3",
24 | "browserslist": [
25 | "last 2 versions",
26 | "not dead",
27 | "> 0.2% in KR",
28 | "iOS >= 12.5"
29 | ],
30 | "dependencies": {
31 | "@glennsl/rescript-fetch": "^0.2.1",
32 | "@heroicons/react": "^2.1.5",
33 | "@rescript/core": "^1.5.2",
34 | "@rescript/react": "^0.12.2",
35 | "better-react-mathjax": "^2.0.3",
36 | "daisyui": "^4.12.10",
37 | "firebase": "^9.23.0",
38 | "react": "18.2.0",
39 | "react-dom": "18.2.0",
40 | "react-error-boundary": "^4.0.13",
41 | "react-icons": "^5.3.0",
42 | "react-infinite-scroll-component": "^6.1.0",
43 | "react-relay": "18.2.0",
44 | "react-select": "^5.8.0",
45 | "react-social-login-buttons": "^4.1.0",
46 | "reactfire": "^4.2.3",
47 | "relay-runtime": "18.2.0",
48 | "rescript-relay": "^3.1.0",
49 | "rescript-webapi": "^0.9.1",
50 | "uuid": "^9.0.1"
51 | },
52 | "devDependencies": {
53 | "@tailwindcss/forms": "^0.5.7",
54 | "@tailwindcss/typography": "^0.5.14",
55 | "@vitejs/plugin-react-swc": "^3.7.0",
56 | "autoprefixer": "^10.4.20",
57 | "concurrently": "^5.3.0",
58 | "lightningcss": "^1.26.0",
59 | "postcss": "^8.4.41",
60 | "postcss-preset-env": "^9.6.0",
61 | "rescript": "^11.1.3",
62 | "tailwindcss": "^3.4.10",
63 | "terser": "^5.31.6",
64 | "vite": "^5.4.0",
65 | "@vitejs/plugin-legacy": "^5.4.1"
66 | },
67 | "trustedDependencies": [
68 | "@swc/core",
69 | "core-js",
70 | "esbuild",
71 | "protobufjs",
72 | "rescript",
73 | "rescript-relay"
74 | ]
75 | }
76 |
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | "postcss-preset-env": {},
6 | },
7 | }
8 |
--------------------------------------------------------------------------------
/public/kiise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Zeta611/easyword/6e1414bc2cc895af2a00bb42bff1add164eec4c9/public/kiise.png
--------------------------------------------------------------------------------
/public/layered-waves.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/relay.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | src: "./src",
3 | schema: "./schema.graphql",
4 | artifactDirectory: "./src/__generated__",
5 | customScalarTypes: {
6 | timestamptz: "string",
7 | uuid: "string",
8 | seed_float: "string",
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/rescript.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eko",
3 | "version": "0.0.1",
4 | "sources": {
5 | "dir": "src",
6 | "subdirs": true
7 | },
8 | "package-specs": {
9 | "module": "esmodule",
10 | "in-source": true
11 | },
12 | "suffix": ".js",
13 | "jsx": { "version": 4, "mode": "automatic" },
14 | "bs-dependencies": [
15 | "@rescript/core",
16 | "@rescript/react",
17 | "rescript-relay",
18 | "rescript-webapi",
19 | "@glennsl/rescript-fetch"
20 | ],
21 | "warnings": {
22 | "error": "+101"
23 | },
24 | "bsc-flags": ["-open RescriptCore"],
25 | "ppx-flags": ["rescript-relay/ppx"]
26 | }
27 |
--------------------------------------------------------------------------------
/src/App.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = () => {
3 | open Firebase
4 |
5 | let app = useFirebaseApp()
6 | let auth = app->Auth.getAuth
7 |
8 | // let () = %raw(`self.FIREBASE_APPCHECK_DEBUG_TOKEN = true`)
9 |
10 | let appCheck = initializeAppCheck(
11 | app,
12 | {
13 | provider: createReCaptchaV3Provider(appCheckToken),
14 | isTokenAutoRefreshEnabled: true,
15 | },
16 | )
17 |
18 | let {status, data: firestore} = useInitFirestore(async app => app->getFirestore)
19 |
20 | let mathJaxConfig = {
21 | "loader": {"load": ["[tex]/bussproofs"]},
22 | "tex": {
23 | "packages": {"[+]": ["bussproofs"]},
24 | "inlineMath": [["$", "$"], ["\\(", "\\)"]],
25 | "displayMath": [["$$", "$$"], ["\\[", "\\]"]],
26 | },
27 | }
28 |
29 | let url = RescriptReactRouter.useUrl()
30 |
31 | switch status {
32 | | #loading =>
33 |
34 |
35 |
36 |
37 | | #success =>
38 | switch firestore {
39 | | None => React.null
40 | | Some(firestore) =>
41 |
42 |
43 |
44 |
45 |
46 |
48 |
49 | }>
50 | {
51 | open LazyComponents
52 | switch url.path {
53 | | list{"login"} =>
54 | | list{"logout"} =>
55 |
56 | | path =>
57 |
58 |
59 | {switch path {
60 | | list{} =>
61 | {
63 | Console.error(error)
64 | React.null
65 | }}>
66 |
69 |
70 | }>
71 |
72 |
73 |
74 | | list{"profile"} =>
75 | | list{"new-jargon"} =>
76 | | list{"new-translation", jargonID} =>
77 | | list{"edit-categories", jargonID} =>
78 | | list{"jargon", jargonID} =>
79 | {
81 |
82 | {"앗! 404"->React.string}
83 |
84 | }}>
85 |
86 |
87 |
88 |
89 |
90 | | list{"trans"} =>
91 | | list{"tips"} =>
92 | | list{"why"} =>
93 | | list{"colophon"} =>
94 |
95 | | _ => React.string("404")
96 | }}
97 |
98 |
99 | }
100 | }
101 |
102 |
103 |
104 |
105 |
106 |
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Base64.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Js_exn from "rescript/lib/es6/js_exn.js";
4 | import * as Core__JSON from "@rescript/core/src/Core__JSON.js";
5 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
6 | import * as Caml_js_exceptions from "rescript/lib/es6/caml_js_exceptions.js";
7 |
8 | function retrieveOriginalID(id) {
9 | try {
10 | var decoded = Core__JSON.Decode.array(JSON.parse(atob(id)));
11 | if (decoded !== undefined) {
12 | return decoded[3];
13 | } else {
14 | return ;
15 | }
16 | }
17 | catch (raw_exn){
18 | var exn = Caml_js_exceptions.internalToOCamlException(raw_exn);
19 | if (exn.RE_EXN_ID === Js_exn.$$Error) {
20 | console.error("Error decoding ID: " + id);
21 | return ;
22 | }
23 | throw exn;
24 | }
25 | }
26 |
27 | function retrieveOriginalIDString(id) {
28 | var originalID = retrieveOriginalID(id);
29 | if (originalID !== undefined) {
30 | return Core__JSON.Decode.string(originalID);
31 | }
32 |
33 | }
34 |
35 | function retrieveOriginalIDInt(id) {
36 | var originalID = retrieveOriginalID(id);
37 | if (originalID !== undefined) {
38 | return Core__Option.map(Core__JSON.Decode.$$float(originalID), (function (n) {
39 | return n | 0;
40 | }));
41 | }
42 |
43 | }
44 |
45 | export {
46 | retrieveOriginalID ,
47 | retrieveOriginalIDString ,
48 | retrieveOriginalIDInt ,
49 | }
50 | /* No side effect */
51 |
--------------------------------------------------------------------------------
/src/Base64.res:
--------------------------------------------------------------------------------
1 | @val external encode: string => string = "btoa"
2 | @val external decode: string => string = "atob"
3 |
4 | let retrieveOriginalID = id => {
5 | try {
6 | switch id->decode->JSON.parseExn->JSON.Decode.array {
7 | | Some(decoded) => decoded[3]
8 | | None => None
9 | }
10 | } catch {
11 | | Exn.Error(_) => {
12 | Js.Console.error(`Error decoding ID: ${id}`)
13 | None
14 | }
15 | }
16 | }
17 |
18 | let retrieveOriginalIDString = id => {
19 | switch id->retrieveOriginalID {
20 | | Some(originalID) => originalID->JSON.Decode.string
21 | | None => None
22 | }
23 | }
24 |
25 | let retrieveOriginalIDInt = id => {
26 | switch id->retrieveOriginalID {
27 | | Some(originalID) => originalID->JSON.Decode.float->Option.map(n => n->Float.toInt)
28 | | None => None
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Colophon.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
4 | import * as JsxRuntime from "react/jsx-runtime";
5 | import * as RescriptRelay_Query from "rescript-relay/src/RescriptRelay_Query.js";
6 | import * as ColophonQuery_graphql from "./__generated__/ColophonQuery_graphql.js";
7 |
8 | var convertVariables = ColophonQuery_graphql.Internal.convertVariables;
9 |
10 | var convertResponse = ColophonQuery_graphql.Internal.convertResponse;
11 |
12 | var convertWrapRawResponse = ColophonQuery_graphql.Internal.convertWrapRawResponse;
13 |
14 | var use = RescriptRelay_Query.useQuery(convertVariables, ColophonQuery_graphql.node, convertResponse);
15 |
16 | var useLoader = RescriptRelay_Query.useLoader(convertVariables, ColophonQuery_graphql.node, (function (prim) {
17 | return prim;
18 | }));
19 |
20 | var usePreloaded = RescriptRelay_Query.usePreloaded(ColophonQuery_graphql.node, convertResponse, (function (prim) {
21 | return prim;
22 | }));
23 |
24 | var $$fetch = RescriptRelay_Query.$$fetch(ColophonQuery_graphql.node, convertResponse, convertVariables);
25 |
26 | var fetchPromised = RescriptRelay_Query.fetchPromised(ColophonQuery_graphql.node, convertResponse, convertVariables);
27 |
28 | var retain = RescriptRelay_Query.retain(ColophonQuery_graphql.node, convertVariables);
29 |
30 | var ColophonQuery = {
31 | Operation: undefined,
32 | Types: undefined,
33 | convertVariables: convertVariables,
34 | convertResponse: convertResponse,
35 | convertWrapRawResponse: convertWrapRawResponse,
36 | use: use,
37 | useLoader: useLoader,
38 | usePreloaded: usePreloaded,
39 | $$fetch: $$fetch,
40 | fetchPromised: fetchPromised,
41 | retain: retain
42 | };
43 |
44 | function Colophon(props) {
45 | var match = use(undefined, undefined, undefined, undefined);
46 | var data = Core__Option.map(match.html_connection.edges[0], (function (edge) {
47 | return edge.node.data;
48 | }));
49 | if (data !== undefined) {
50 | return JsxRuntime.jsxs("article", {
51 | children: [
52 | JsxRuntime.jsx("h1", {
53 | children: "제작기"
54 | }),
55 | JsxRuntime.jsx("div", {
56 | children: JsxRuntime.jsx("a", {
57 | children: "서울대학교 프로그래밍 연구실 이재호",
58 | href: "http://ropas.snu.ac.kr/~jhlee/"
59 | }),
60 | className: "text-right text-sm"
61 | }),
62 | JsxRuntime.jsx("div", {
63 | className: "divider"
64 | }),
65 | JsxRuntime.jsx("div", {
66 | dangerouslySetInnerHTML: {
67 | __html: data
68 | }
69 | })
70 | ],
71 | className: "px-6 py-12 max-w-xl mx-auto md:max-w-4xl prose"
72 | });
73 | } else {
74 | return null;
75 | }
76 | }
77 |
78 | var make = Colophon;
79 |
80 | export {
81 | ColophonQuery ,
82 | make ,
83 | }
84 | /* use Not a pure module */
85 |
--------------------------------------------------------------------------------
/src/Colophon.res:
--------------------------------------------------------------------------------
1 | module ColophonQuery = %relay(`
2 | query ColophonQuery {
3 | html_connection(where: { id: { _eq: 3 } }) {
4 | edges {
5 | node {
6 | data
7 | }
8 | }
9 | }
10 | }
11 | `)
12 |
13 | @react.component
14 | let make = () => {
15 | let {html_connection: {edges: htmlEdges}} = ColophonQuery.use(~variables=())
16 | let data = htmlEdges[0]->Option.map(edge => edge.node.data)
17 | switch data {
18 | | Some(data) =>
19 |
20 | {"제작기"->React.string}
21 |
26 |
27 |
28 |
29 | | None => React.null
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Comment.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Core__List from "@rescript/core/src/Core__List.js";
4 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
5 |
6 | function constructForest(comments) {
7 | var roots = {
8 | contents: /* [] */0
9 | };
10 | var commentNodeTable = new Map();
11 | comments.forEach(function (comment) {
12 | var node = {
13 | comment: comment,
14 | parent: undefined,
15 | children: /* [] */0
16 | };
17 | commentNodeTable.set(comment.id, node);
18 | if (Core__Option.isNone(comment.parent)) {
19 | roots.contents = Core__List.add(roots.contents, node);
20 | return ;
21 | }
22 |
23 | });
24 | commentNodeTable.forEach(function (node) {
25 | var parent = node.comment.parent;
26 | if (parent === undefined) {
27 | return ;
28 | }
29 | var parentNode = Core__Option.getExn(commentNodeTable.get(parent), undefined);
30 | parentNode.children = Core__List.add(parentNode.children, node);
31 | node.parent = parentNode;
32 | });
33 | return roots;
34 | }
35 |
36 | function countDescendents(children) {
37 | if (!children) {
38 | return 0;
39 | }
40 | var children$1 = children.hd.children;
41 | return (1 + countDescendents(children$1) | 0) + countDescendents(children.tl) | 0;
42 | }
43 |
44 | export {
45 | constructForest ,
46 | countDescendents ,
47 | }
48 | /* No side effect */
49 |
--------------------------------------------------------------------------------
/src/Comment.res:
--------------------------------------------------------------------------------
1 | type t = {
2 | id: string,
3 | content: string,
4 | userDisplayName: string,
5 | userPhotoURL: option,
6 | timestamp: Date.t,
7 | parent: option,
8 | translation: option,
9 | }
10 |
11 | type rec node = {
12 | comment: t,
13 | mutable parent: option,
14 | mutable children: list,
15 | }
16 |
17 | type write = {
18 | jargonID: string,
19 | content: string,
20 | parent: string,
21 | }
22 |
23 | let constructForest = comments => {
24 | let roots: ref> = ref(list{})
25 | let commentNodeTable = Map.make()
26 |
27 | // Store comments in the lookupComment hash map & add roots as well
28 | comments->Array.forEach(comment => {
29 | let node = {comment, parent: None, children: list{}}
30 | commentNodeTable->Map.set(comment.id, node)
31 | if comment.parent->Option.isNone {
32 | roots := roots.contents->List.add(node)
33 | }
34 | })
35 |
36 | // Iterate through the array and link the nodes
37 | commentNodeTable->Map.forEach(({comment} as node) => {
38 | switch comment.parent {
39 | | Some(parent) => {
40 | let parentNode = commentNodeTable->Map.get(parent)->Option.getExn
41 | parentNode.children = parentNode.children->List.add(node)
42 | node.parent = Some(parentNode)
43 | }
44 | | None => ()
45 | }
46 | })
47 |
48 | roots
49 | }
50 |
51 | let rec countDescendents = children => {
52 | switch children {
53 | | list{} => 0
54 | | list{{children}, ...tl} => 1 + countDescendents(children) + countDescendents(tl)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/CommentInput.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 | import * as Base64 from "./Base64.js";
5 | import * as SignInContext from "./SignInContext.js";
6 | import * as JsxRuntime from "react/jsx-runtime";
7 | import * as RescriptRelay_Mutation from "rescript-relay/src/RescriptRelay_Mutation.js";
8 | import * as CommentInputMutation_graphql from "./__generated__/CommentInputMutation_graphql.js";
9 |
10 | var convertVariables = CommentInputMutation_graphql.Internal.convertVariables;
11 |
12 | var convertResponse = CommentInputMutation_graphql.Internal.convertResponse;
13 |
14 | var convertWrapRawResponse = CommentInputMutation_graphql.Internal.convertWrapRawResponse;
15 |
16 | var commitMutation = RescriptRelay_Mutation.commitMutation(convertVariables, CommentInputMutation_graphql.node, convertResponse, convertWrapRawResponse);
17 |
18 | var use = RescriptRelay_Mutation.useMutation(convertVariables, CommentInputMutation_graphql.node, convertResponse, convertWrapRawResponse);
19 |
20 | var CommentMutation = {
21 | Operation: undefined,
22 | Types: undefined,
23 | convertVariables: convertVariables,
24 | convertResponse: convertResponse,
25 | convertWrapRawResponse: convertWrapRawResponse,
26 | commitMutation: commitMutation,
27 | use: use
28 | };
29 |
30 | function CommentInput(props) {
31 | var jargonID = props.jargonID;
32 | var match = React.useContext(SignInContext.context);
33 | var user = match.user;
34 | var match$1 = React.useState(function () {
35 | return "";
36 | });
37 | var setContent = match$1[1];
38 | var content = match$1[0];
39 | var handleInputChange = function ($$event) {
40 | var value = $$event.currentTarget.value;
41 | setContent(function (param) {
42 | return value;
43 | });
44 | };
45 | var match$2 = use();
46 | var mutate = match$2[0];
47 | var handleSubmit = function ($$event) {
48 | $$event.preventDefault();
49 | if (content.length < 3) {
50 | window.alert("댓글은 세 글자 이상이어야 해요");
51 | return ;
52 | }
53 | var jargonID$1 = Base64.retrieveOriginalIDString(jargonID);
54 | if (user == null) {
55 | window.alert("로그인해야 합니다");
56 | } else if (jargonID$1 !== undefined) {
57 | mutate({
58 | authorID: user.uid,
59 | content: content,
60 | jargonID: jargonID$1,
61 | now: new Date().toISOString()
62 | }, undefined, undefined, undefined, (function (_response, _errors) {
63 | ((window.location.reload()));
64 | }), (function (error) {
65 | console.error(error);
66 | }), undefined);
67 | } else {
68 | window.alert("현재 댓글을 달 수 없어요");
69 | }
70 | };
71 | return JsxRuntime.jsx("form", {
72 | children: JsxRuntime.jsxs("div", {
73 | children: [
74 | JsxRuntime.jsx("textarea", {
75 | className: "textarea textarea-ghost textarea-sm focus:outline-0 focus:border-transparent place-self-stretch",
76 | id: "comment",
77 | name: "comment",
78 | placeholder: "여러분의 생각은 어떠신가요?",
79 | value: content,
80 | onChange: handleInputChange
81 | }),
82 | JsxRuntime.jsx("input", {
83 | className: "btn btn-neutral btn-sm ml-1 mb-1 disabled:loading",
84 | disabled: match$2[1],
85 | type: "submit",
86 | value: "댓글"
87 | })
88 | ],
89 | className: "rounded-lg border-2 border-zinc-300 focus-within:border-zinc-400 bg-white gap-1 grid grid-cols-1 place-items-start"
90 | }),
91 | onSubmit: handleSubmit
92 | });
93 | }
94 |
95 | var make = CommentInput;
96 |
97 | export {
98 | CommentMutation ,
99 | make ,
100 | }
101 | /* commitMutation Not a pure module */
102 |
--------------------------------------------------------------------------------
/src/CommentInput.res:
--------------------------------------------------------------------------------
1 | module CommentMutation = %relay(`
2 | mutation CommentInputMutation(
3 | $authorID: String!
4 | $content: String!
5 | $jargonID: uuid!
6 | $now: timestamptz!
7 | ) {
8 | insert_comment_one(
9 | object: { author_id: $authorID, content: $content, jargon_id: $jargonID }
10 | ) {
11 | id
12 | }
13 | update_jargon_by_pk(
14 | pk_columns: { id: $jargonID }
15 | _set: { updated_at: $now }
16 | ) {
17 | id
18 | }
19 | }
20 | `)
21 |
22 | @react.component
23 | let make = (~jargonID) => {
24 | let {user} = React.useContext(SignInContext.context)
25 |
26 | // For handling the comment textarea
27 | let (content, setContent) = React.useState(() => "")
28 | let handleInputChange = event => {
29 | let value = ReactEvent.Form.currentTarget(event)["value"]
30 | setContent(_ => value)
31 | }
32 |
33 | let (mutate, isMutating) = CommentMutation.use()
34 |
35 | let handleSubmit = event => {
36 | // Prevent a page refresh, we are already listening for updates
37 | ReactEvent.Form.preventDefault(event)
38 |
39 | if content->String.length < 3 {
40 | Window.alert("댓글은 세 글자 이상이어야 해요")
41 | } else {
42 | let jargonID = jargonID->Base64.retrieveOriginalIDString
43 | switch (user->Nullable.toOption, jargonID) {
44 | | (Some(user), Some(jargonID)) =>
45 | mutate(
46 | ~variables={
47 | authorID: user.uid,
48 | content,
49 | jargonID,
50 | now: Date.make()->Date.toISOString,
51 | },
52 | ~onError=error => {
53 | Console.error(error)
54 | },
55 | ~onCompleted=(_response, _errors) => {
56 | // TODO: Make relay understand the update
57 | %raw(`window.location.reload()`)
58 | },
59 | )->ignore
60 | | (Some(_), _) => Window.alert("현재 댓글을 달 수 없어요")
61 | | (None, _) => Window.alert("로그인해야 합니다")
62 | }
63 | }
64 | }
65 |
66 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/CommentSection.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as $$Comment from "./Comment.js";
4 | import * as CommentRow from "./CommentRow.js";
5 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
6 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
7 | import * as JsxRuntime from "react/jsx-runtime";
8 | import * as RescriptRelay_Fragment from "rescript-relay/src/RescriptRelay_Fragment.js";
9 | import * as CommentSection_jargon_graphql from "./__generated__/CommentSection_jargon_graphql.js";
10 |
11 | var convertFragment = CommentSection_jargon_graphql.Internal.convertFragment;
12 |
13 | function waitForFragmentData(environment, fRef) {
14 | return RescriptRelay_Fragment.waitForFragmentData(environment, CommentSection_jargon_graphql.node, convertFragment, fRef);
15 | }
16 |
17 | function use(fRef) {
18 | return RescriptRelay_Fragment.useFragment(CommentSection_jargon_graphql.node, convertFragment, fRef);
19 | }
20 |
21 | function useOpt(fRef) {
22 | return RescriptRelay_Fragment.useFragmentOpt(fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(fRef)) : undefined, CommentSection_jargon_graphql.node, convertFragment);
23 | }
24 |
25 | function readResolverFragment(fRef) {
26 | return RescriptRelay_Fragment.read(CommentSection_jargon_graphql.node, convertFragment, fRef);
27 | }
28 |
29 | var CommentFragment = {
30 | Types: undefined,
31 | Operation: undefined,
32 | convertFragment: convertFragment,
33 | waitForFragmentData: waitForFragmentData,
34 | use: use,
35 | useOpt: useOpt,
36 | readResolverFragment: readResolverFragment
37 | };
38 |
39 | function CommentSection(props) {
40 | var match = use(props.commentRefs);
41 | var roots = $$Comment.constructForest(match.comments_connection.edges.map(function (param) {
42 | var x = param.node;
43 | return {
44 | id: x.id,
45 | content: x.content,
46 | userDisplayName: x.author.display_name,
47 | userPhotoURL: x.author.photo_url,
48 | timestamp: new Date(x.created_at),
49 | parent: Core__Option.map(x.parent, (function (x) {
50 | return x.id;
51 | })),
52 | translation: Core__Option.map(x.translation, (function (x) {
53 | return x.name;
54 | }))
55 | };
56 | }));
57 | return JsxRuntime.jsx(CommentRow.make, {
58 | jargonID: props.jargonID,
59 | siblings: roots.contents
60 | });
61 | }
62 |
63 | var make = CommentSection;
64 |
65 | export {
66 | CommentFragment ,
67 | make ,
68 | }
69 | /* CommentRow Not a pure module */
70 |
--------------------------------------------------------------------------------
/src/CommentSection.res:
--------------------------------------------------------------------------------
1 | module CommentFragment = %relay(`
2 | fragment CommentSection_jargon on jargon {
3 | __id
4 | comments_connection {
5 | edges {
6 | node {
7 | id
8 | content
9 | created_at
10 | parent {
11 | id
12 | }
13 | author {
14 | photo_url
15 | display_name
16 | }
17 | translation {
18 | id
19 | name
20 | }
21 | }
22 | }
23 | }
24 | }
25 | `)
26 |
27 | @react.component
28 | let make = (~jargonID, ~commentRefs) => {
29 | let {comments_connection: {edges: comments}, __id} = CommentFragment.use(commentRefs)
30 |
31 | let roots = Comment.constructForest(
32 | comments->Array.map(({node: x}) => {
33 | Comment.id: x.id,
34 | content: x.content,
35 | userDisplayName: x.author.display_name,
36 | userPhotoURL: x.author.photo_url,
37 | timestamp: x.created_at->Date.fromString,
38 | parent: x.parent->Option.map(x => x.id),
39 | translation: x.translation->Option.map(x => x.name),
40 | }),
41 | )
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/DateFormat.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 |
4 | function timeAgo(date) {
5 | var seconds = (Date.now() - date.getTime()) / 1000 | 0;
6 | var minutes = seconds / 60 | 0;
7 | var hours = minutes / 60 | 0;
8 | var days = hours / 24 | 0;
9 | var months = days / 30 | 0;
10 | var years = months / 12 | 0;
11 | if (seconds < 60) {
12 | return "방금 전";
13 | } else if (minutes < 60) {
14 | return minutes.toString() + "분 전";
15 | } else if (hours < 24) {
16 | return hours.toString() + "시간 전";
17 | } else if (days < 30) {
18 | return days.toString() + "일 전";
19 | } else if (months < 12) {
20 | return months.toString() + "달 전";
21 | } else {
22 | return years.toString() + "년 전";
23 | }
24 | }
25 |
26 | export {
27 | timeAgo ,
28 | }
29 | /* No side effect */
30 |
--------------------------------------------------------------------------------
/src/DateFormat.res:
--------------------------------------------------------------------------------
1 | let timeAgo = date => {
2 | let seconds = ((Date.now() -. date->Date.getTime) /. 1000.)->Float.toInt
3 | let minutes = seconds / 60
4 | let hours = minutes / 60
5 | let days = hours / 24
6 | let months = days / 30
7 | let years = months / 12
8 |
9 | if seconds < 60 {
10 | "방금 전"
11 | } else if minutes < 60 {
12 | `${minutes->Int.toString}분 전`
13 | } else if hours < 24 {
14 | `${hours->Int.toString}시간 전`
15 | } else if days < 30 {
16 | `${days->Int.toString}일 전`
17 | } else if months < 12 {
18 | `${months->Int.toString}달 전`
19 | } else {
20 | `${years->Int.toString}년 전`
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/ErrorBoundary.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/ErrorBoundary.res:
--------------------------------------------------------------------------------
1 | type error = {message: string}
2 | type fallbackRenderProps = {error: error, resetErrorBoundary: unit => unit}
3 |
4 | @module("react-error-boundary") @react.component
5 | external make: (
6 | ~children: React.element,
7 | ~fallbackRender: fallbackRenderProps => React.element,
8 | ~onReset: 'a => unit=?,
9 | ) => React.element = "ErrorBoundary"
10 |
--------------------------------------------------------------------------------
/src/Exc.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Caml_exceptions from "rescript/lib/es6/caml_exceptions.js";
4 |
5 | var GraphQLError = /* @__PURE__ */Caml_exceptions.create("Exc.GraphQLError");
6 |
7 | var HTTPError = /* @__PURE__ */Caml_exceptions.create("Exc.HTTPError");
8 |
9 | export {
10 | GraphQLError ,
11 | HTTPError ,
12 | }
13 | /* No side effect */
14 |
--------------------------------------------------------------------------------
/src/Exc.res:
--------------------------------------------------------------------------------
1 | exception GraphQLError(string)
2 | exception HTTPError(int, string)
3 |
--------------------------------------------------------------------------------
/src/Firebase.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as FirebaseConfig from "./firebaseConfig";
4 |
5 | var firebaseConfig = FirebaseConfig.firebaseConfig;
6 |
7 | var FirebaseAppProvider = {};
8 |
9 | var FirebaseOptions = {};
10 |
11 | var FirebaseApp = {};
12 |
13 | var FirestoreProvider = {};
14 |
15 | function uid(param) {
16 | return param.uid;
17 | }
18 |
19 | function providerId(param) {
20 | return param.providerId;
21 | }
22 |
23 | function displayName(param) {
24 | return param.displayName;
25 | }
26 |
27 | function email(param) {
28 | return param.email;
29 | }
30 |
31 | var User = {
32 | uid: uid,
33 | providerId: providerId,
34 | displayName: displayName,
35 | email: email
36 | };
37 |
38 | var AuthUser = {};
39 |
40 | var EmailAuthProvider = {
41 | providerID: "password"
42 | };
43 |
44 | var GithubAuthProvider = {
45 | providerID: "github.com"
46 | };
47 |
48 | var GoogleAuthProvider = {
49 | providerID: "google.com"
50 | };
51 |
52 | var FederatedAuthProvider = {};
53 |
54 | var Auth = {
55 | AuthUser: AuthUser,
56 | EmailAuthProvider: EmailAuthProvider,
57 | GithubAuthProvider: GithubAuthProvider,
58 | GoogleAuthProvider: GoogleAuthProvider,
59 | FederatedAuthProvider: FederatedAuthProvider
60 | };
61 |
62 | var AuthProvider = {};
63 |
64 | var appCheckToken = FirebaseConfig.APP_CHECK_TOKEN;
65 |
66 | var AppCheckProvider = {};
67 |
68 | export {
69 | firebaseConfig ,
70 | FirebaseAppProvider ,
71 | FirebaseOptions ,
72 | FirebaseApp ,
73 | FirestoreProvider ,
74 | User ,
75 | Auth ,
76 | AuthProvider ,
77 | appCheckToken ,
78 | AppCheckProvider ,
79 | }
80 | /* firebaseConfig Not a pure module */
81 |
--------------------------------------------------------------------------------
/src/FooterContainer.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function FooterContainer(props) {
6 | return JsxRuntime.jsxs("div", {
7 | children: [
8 | JsxRuntime.jsx("div", {
9 | children: props.children,
10 | className: "flex-grow"
11 | }),
12 | JsxRuntime.jsxs("footer", {
13 | children: [
14 | JsxRuntime.jsx("a", {
15 | children: JsxRuntime.jsx("img", {
16 | className: "object-contain h-10",
17 | alt: "KIISE",
18 | src: "/kiise.png"
19 | }),
20 | href: "https://kiise.or.kr",
21 | rel: "noreferrer noopener",
22 | target: "_blank"
23 | }),
24 | JsxRuntime.jsx("p", {
25 | children: "한국정보과학회 쉬운전문용어 제정위원회 지원을 받았습니다.",
26 | className: "align-middle"
27 | })
28 | ],
29 | className: "footer bg-base-300 text-base-content p-4 gap-1 items-center"
30 | })
31 | ],
32 | className: "flex flex-col min-h-screen"
33 | });
34 | }
35 |
36 | var make = FooterContainer;
37 |
38 | export {
39 | make ,
40 | }
41 | /* react/jsx-runtime Not a pure module */
42 |
--------------------------------------------------------------------------------
/src/FooterContainer.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~children: React.element) => {
3 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/Heroicons.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 |
4 | var CalendarDaysIcon = {};
5 |
6 | var ChevronDownIcon = {};
7 |
8 | var ArrowDownIcon = {};
9 |
10 | var ArrowUpIcon = {};
11 |
12 | var Bars3Icon = {};
13 |
14 | var StarIcon = {};
15 |
16 | var Solid = {
17 | CalendarDaysIcon: CalendarDaysIcon,
18 | ChevronDownIcon: ChevronDownIcon,
19 | ArrowDownIcon: ArrowDownIcon,
20 | ArrowUpIcon: ArrowUpIcon,
21 | Bars3Icon: Bars3Icon,
22 | StarIcon: StarIcon
23 | };
24 |
25 | var LanguageIcon = {};
26 |
27 | var ClockIcon = {};
28 |
29 | var ListBulletIcon = {};
30 |
31 | var UserCircleIcon = {};
32 |
33 | var ChatBubbleLeftIcon = {};
34 |
35 | var ChatBubbleLeftRightIcon = {};
36 |
37 | var ChartBarSquareIcon = {};
38 |
39 | var FunnelIcon = {};
40 |
41 | var HomeIcon = {};
42 |
43 | var LightBulbIcon = {};
44 |
45 | var PencilSquareIcon = {};
46 |
47 | var WrenchIcon = {};
48 |
49 | var Outline = {
50 | LanguageIcon: LanguageIcon,
51 | ClockIcon: ClockIcon,
52 | ListBulletIcon: ListBulletIcon,
53 | UserCircleIcon: UserCircleIcon,
54 | ChatBubbleLeftIcon: ChatBubbleLeftIcon,
55 | ChatBubbleLeftRightIcon: ChatBubbleLeftRightIcon,
56 | ChartBarSquareIcon: ChartBarSquareIcon,
57 | FunnelIcon: FunnelIcon,
58 | HomeIcon: HomeIcon,
59 | LightBulbIcon: LightBulbIcon,
60 | PencilSquareIcon: PencilSquareIcon,
61 | WrenchIcon: WrenchIcon
62 | };
63 |
64 | export {
65 | Solid ,
66 | Outline ,
67 | }
68 | /* No side effect */
69 |
--------------------------------------------------------------------------------
/src/Heroicons.res:
--------------------------------------------------------------------------------
1 | module Solid = {
2 | module CalendarDaysIcon = {
3 | @module("@heroicons/react/24/solid") @react.component
4 | external make: (~className: string=?) => React.element = "CalendarDaysIcon"
5 | }
6 |
7 | module ChevronDownIcon = {
8 | @module("@heroicons/react/24/solid") @react.component
9 | external make: (~className: string=?) => React.element = "ChevronDownIcon"
10 | }
11 |
12 | module ArrowDownIcon = {
13 | @module("@heroicons/react/24/solid") @react.component
14 | external make: (~className: string=?) => React.element = "ArrowDownIcon"
15 | }
16 | module ArrowUpIcon = {
17 | @module("@heroicons/react/24/solid") @react.component
18 | external make: (~className: string=?) => React.element = "ArrowUpIcon"
19 | }
20 |
21 | module Bars3Icon = {
22 | @module("@heroicons/react/24/solid") @react.component
23 | external make: (~className: string=?) => React.element = "Bars3Icon"
24 | }
25 |
26 | module StarIcon = {
27 | @module("@heroicons/react/24/solid") @react.component
28 | external make: (~className: string=?) => React.element = "StarIcon"
29 | }
30 | }
31 |
32 | module Outline = {
33 | module LanguageIcon = {
34 | @module("@heroicons/react/24/outline") @react.component
35 | external make: (~className: string=?) => React.element = "LanguageIcon"
36 | }
37 |
38 | module ClockIcon = {
39 | @module("@heroicons/react/24/outline") @react.component
40 | external make: (~className: string=?) => React.element = "ClockIcon"
41 | }
42 |
43 | module ListBulletIcon = {
44 | @module("@heroicons/react/24/outline") @react.component
45 | external make: (~className: string=?) => React.element = "ListBulletIcon"
46 | }
47 |
48 | module UserCircleIcon = {
49 | @module("@heroicons/react/24/outline") @react.component
50 | external make: (~className: string=?) => React.element = "UserCircleIcon"
51 | }
52 |
53 | module ChatBubbleLeftIcon = {
54 | @module("@heroicons/react/24/outline") @react.component
55 | external make: (~className: string=?) => React.element = "ChatBubbleLeftIcon"
56 | }
57 |
58 | module ChatBubbleLeftRightIcon = {
59 | @module("@heroicons/react/24/outline") @react.component
60 | external make: (~className: string=?) => React.element = "ChatBubbleLeftRightIcon"
61 | }
62 |
63 | module ChartBarSquareIcon = {
64 | @module("@heroicons/react/24/outline") @react.component
65 | external make: (~className: string=?) => React.element = "ChartBarSquareIcon"
66 | }
67 |
68 | module FunnelIcon = {
69 | @module("@heroicons/react/24/outline") @react.component
70 | external make: (~className: string=?) => React.element = "FunnelIcon"
71 | }
72 |
73 | module HomeIcon = {
74 | @module("@heroicons/react/24/outline") @react.component
75 | external make: (~className: string=?) => React.element = "HomeIcon"
76 | }
77 |
78 | module LightBulbIcon = {
79 | @module("@heroicons/react/24/outline") @react.component
80 | external make: (~className: string=?) => React.element = "LightBulbIcon"
81 | }
82 |
83 | module PencilSquareIcon = {
84 | @module("@heroicons/react/24/outline") @react.component
85 | external make: (~className: string=?) => React.element = "PencilSquareIcon"
86 | }
87 |
88 | module WrenchIcon = {
89 | @module("@heroicons/react/24/outline") @react.component
90 | external make: (~className: string=?) => React.element = "WrenchIcon"
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/HideUs.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function HideUs(props) {
6 | return JsxRuntime.jsx("div", {
7 | children: props.children,
8 | className: "absolute -top-full -left-full"
9 | });
10 | }
11 |
12 | var make = HideUs;
13 |
14 | export {
15 | make ,
16 | }
17 | /* react/jsx-runtime Not a pure module */
18 |
--------------------------------------------------------------------------------
/src/HideUs.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~children: React.element) => {
3 | children
4 | }
5 |
--------------------------------------------------------------------------------
/src/HomeJargonListSection.res:
--------------------------------------------------------------------------------
1 | module HomeJargonListSectionQuery = %relay(`
2 | query HomeJargonListSectionQuery(
3 | $searchTerm: String!
4 | $categoryIDs: [Int!]!
5 | $onlyWithoutTranslationFilter: [jargon_bool_exp!]!
6 | $directions: [jargon_order_by!]!
7 | ) {
8 | ...JargonListOrderQuery
9 | }
10 | `)
11 |
12 | @react.component
13 | let make = (~searchTerm, ~categoryIDs, ~onlyWithoutTranslation, ~axis, ~direction) => {
14 | let searchTerm = searchTerm->String.replaceRegExp(%re(`/\s+/g`), "")
15 | let {fragmentRefs: query} = HomeJargonListSectionQuery.use(
16 | ~variables={
17 | searchTerm,
18 | categoryIDs,
19 | onlyWithoutTranslationFilter: if onlyWithoutTranslation {
20 | [
21 | {
22 | _not: {translations: {}},
23 | },
24 | ]
25 | } else {
26 | []
27 | },
28 | directions: {
29 | switch axis {
30 | | Jargon.English => [
31 | {
32 | name_lower: switch direction {
33 | | #asc => Asc
34 | | #desc => Desc
35 | },
36 | },
37 | {updated_at: Desc},
38 | ]
39 | | Chrono => [{updated_at: Desc}, {name_lower: Asc}]
40 | | Random(_) => []
41 | }
42 | },
43 | },
44 | )
45 |
46 |
48 |
49 | }>
50 | {switch axis {
51 | | Random(seed) =>
52 | | _ =>
53 | }}
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/Hooks.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 |
5 | function useDebounce(value, delay) {
6 | var match = React.useState(function () {
7 | return value;
8 | });
9 | var setDebouncedValue = match[1];
10 | React.useEffect((function () {
11 | var handler = setTimeout((function () {
12 | setDebouncedValue(function (param) {
13 | return value;
14 | });
15 | }), delay);
16 | return (function () {
17 | clearTimeout(handler);
18 | });
19 | }), [
20 | value,
21 | delay
22 | ]);
23 | return match[0];
24 | }
25 |
26 | function useClosingDropdown(id) {
27 | var close = function (dropdown) {
28 | if (dropdown.hasAttribute("open")) {
29 | dropdown.removeAttribute("open");
30 | return ;
31 | }
32 |
33 | };
34 | var closeDropdown = function () {
35 | var dropdown = document.getElementById(id);
36 | if (!(dropdown == null)) {
37 | return close(dropdown);
38 | }
39 |
40 | };
41 | React.useEffect((function () {
42 | var dropdown = document.getElementById(id);
43 | if (!(dropdown == null)) {
44 | document.addEventListener("click", (function ($$event) {
45 | if (!dropdown.contains($$event.target)) {
46 | return close(dropdown);
47 | }
48 |
49 | }));
50 | window.addEventListener("scroll", (function (param) {
51 | close(dropdown);
52 | }), {
53 | capture: false,
54 | once: false,
55 | passive: true
56 | });
57 | }
58 |
59 | }), []);
60 | return closeDropdown;
61 | }
62 |
63 | export {
64 | useDebounce ,
65 | useClosingDropdown ,
66 | }
67 | /* react Not a pure module */
68 |
--------------------------------------------------------------------------------
/src/Hooks.res:
--------------------------------------------------------------------------------
1 | let useDebounce = (value, delay) => {
2 | let (debouncedValue, setDebouncedValue) = React.useState(_ => value)
3 |
4 | React.useEffect(() => {
5 | let handler = setTimeout(() => setDebouncedValue(_ => value), delay)
6 |
7 | Some(() => clearTimeout(handler))
8 | }, (value, delay))
9 |
10 | debouncedValue
11 | }
12 |
13 | let useClosingDropdown = id => {
14 | open! Webapi.Dom
15 |
16 | let close = dropdown => {
17 | if dropdown->Element.hasAttribute("open") {
18 | dropdown->Element.removeAttribute("open")
19 | }
20 | }
21 |
22 | let closeDropdown = () =>
23 | switch document->Document.getElementById(id) {
24 | | Some(dropdown) => dropdown->close
25 | | None => ()
26 | }
27 |
28 | React.useEffect0(() => {
29 | switch document->Document.getElementById(id) {
30 | | Some(dropdown) => {
31 | document->Document.addEventListener("click", event => {
32 | if !(dropdown->Element.contains(~child=event->Event.target->Obj.magic)) {
33 | dropdown->close
34 | }
35 | })
36 | window->Window.addEventListenerWithOptions(
37 | "scroll",
38 | _ => dropdown->close,
39 | {"capture": false, "once": false, "passive": true},
40 | )
41 | }
42 | | None => ()
43 | }
44 |
45 | None
46 | })
47 |
48 | closeDropdown
49 | }
50 |
--------------------------------------------------------------------------------
/src/Index.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as App from "./App.js";
4 | import * as Firebase from "./Firebase.js";
5 | import * as Reactfire from "reactfire";
6 | import * as PervasivesU from "rescript/lib/es6/pervasivesU.js";
7 | import * as Client from "react-dom/client";
8 | import * as JsxRuntime from "react/jsx-runtime";
9 |
10 | import './main.css'
11 | ;
12 |
13 | var rootElement = document.querySelector("#root");
14 |
15 | if (rootElement == null) {
16 | PervasivesU.failwith("DOM root is missing");
17 | } else {
18 | var root = Client.createRoot(rootElement);
19 | root.render(JsxRuntime.jsx(Reactfire.FirebaseAppProvider, {
20 | firebaseConfig: Firebase.firebaseConfig,
21 | children: JsxRuntime.jsx(App.make, {})
22 | }));
23 | }
24 |
25 | export {
26 |
27 | }
28 | /* Not a pure module */
29 |
--------------------------------------------------------------------------------
/src/Index.res:
--------------------------------------------------------------------------------
1 | %%raw("import './main.css'")
2 |
3 | open Firebase
4 |
5 | switch ReactDOM.querySelector("#root") {
6 | | Some(rootElement) =>
7 | let root = ReactDOM.Client.createRoot(rootElement)
8 | ReactDOM.Client.Root.render(
9 | root,
10 |
11 |
12 | ,
13 | )
14 | | None => failwith("DOM root is missing")
15 | }
16 |
--------------------------------------------------------------------------------
/src/InfiniteScroll.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/InfiniteScroll.res:
--------------------------------------------------------------------------------
1 | @module("react-infinite-scroll-component") @react.component
2 | external make: (
3 | ~className: string,
4 | ~dataLength: int,
5 | ~next: unit => unit,
6 | ~hasMore: bool,
7 | ~loader: React.element,
8 | ~children: React.element,
9 | ) => React.element = "default"
10 |
--------------------------------------------------------------------------------
/src/Jargon.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 |
4 | function joinTranslations(translations) {
5 | return Object.entries(translations).toSorted(function (param, param$1) {
6 | var v2 = param$1[1];
7 | var v1 = param[1];
8 | if ((v2 - v1 | 0) !== 0) {
9 | return v2 - v1 | 0;
10 | }
11 | var k2 = param$1[0];
12 | var k1 = param[0];
13 | if (k1 > k2) {
14 | return 1.0;
15 | } else if (k1 < k2) {
16 | return -1.0;
17 | } else {
18 | return 0.0;
19 | }
20 | }).map(function (param) {
21 | return param[0];
22 | }).join(",");
23 | }
24 |
25 | export {
26 | joinTranslations ,
27 | }
28 | /* No side effect */
29 |
--------------------------------------------------------------------------------
/src/Jargon.res:
--------------------------------------------------------------------------------
1 | type card = {
2 | id: string,
3 | name: string,
4 | updated_at: Date.t,
5 | translations: array<(string, string)>,
6 | commentsCount: int,
7 | }
8 |
9 | let joinTranslations = translations =>
10 | translations
11 | ->Dict.toArray
12 | ->Array.toSorted(((k1, v1), (k2, v2)) => {
13 | if v2 - v1 != 0 {
14 | float(v2 - v1)
15 | } else if k1 > k2 {
16 | 1.0
17 | } else if k1 < k2 {
18 | -1.0
19 | } else {
20 | 0.0
21 | }
22 | })
23 | ->Array.map(((k, _)) => k)
24 | ->Array.join(",")
25 |
26 | type translation = {
27 | id: string,
28 | korean: string,
29 | @as("associated_comment") associatedComment: string,
30 | }
31 | type add = {english: string, korean: string, comment: string, withoutKorean: bool}
32 | type addTranslation = {id: string, korean: string, comment: string}
33 |
34 | type vote = {jargonID: string, translations: array}
35 |
36 | type axis = English | Chrono | Random(float)
37 |
--------------------------------------------------------------------------------
/src/JargonCard.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as DateFormat from "./DateFormat.js";
4 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
5 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
6 | import * as JsxRuntime from "react/jsx-runtime";
7 | import * as RescriptReactRouter from "@rescript/react/src/RescriptReactRouter.js";
8 | import * as RescriptRelay_Fragment from "rescript-relay/src/RescriptRelay_Fragment.js";
9 | import * as JargonCard_jargon_graphql from "./__generated__/JargonCard_jargon_graphql.js";
10 |
11 | var convertFragment = JargonCard_jargon_graphql.Internal.convertFragment;
12 |
13 | function waitForFragmentData(environment, fRef) {
14 | return RescriptRelay_Fragment.waitForFragmentData(environment, JargonCard_jargon_graphql.node, convertFragment, fRef);
15 | }
16 |
17 | function use(fRef) {
18 | return RescriptRelay_Fragment.useFragment(JargonCard_jargon_graphql.node, convertFragment, fRef);
19 | }
20 |
21 | function useOpt(fRef) {
22 | return RescriptRelay_Fragment.useFragmentOpt(fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(fRef)) : undefined, JargonCard_jargon_graphql.node, convertFragment);
23 | }
24 |
25 | function readResolverFragment(fRef) {
26 | return RescriptRelay_Fragment.read(JargonCard_jargon_graphql.node, convertFragment, fRef);
27 | }
28 |
29 | var JargonCardFragment = {
30 | Types: undefined,
31 | Operation: undefined,
32 | convertFragment: convertFragment,
33 | waitForFragmentData: waitForFragmentData,
34 | use: use,
35 | useOpt: useOpt,
36 | readResolverFragment: readResolverFragment
37 | };
38 |
39 | function badgify(text) {
40 | return JsxRuntime.jsx("div", {
41 | children: text,
42 | className: "badge badge-sm"
43 | }, text);
44 | }
45 |
46 | function JargonCard(props) {
47 | var match = use(props.jargonCardRef);
48 | var id = match.id;
49 | return JsxRuntime.jsxs("div", {
50 | children: [
51 | JsxRuntime.jsxs("div", {
52 | children: [
53 | JsxRuntime.jsx("div", {
54 | children: "최근 활동 " + DateFormat.timeAgo(new Date(match.updated_at)),
55 | className: "text-xs dark:text-zinc-500"
56 | }),
57 | JsxRuntime.jsx("div", {
58 | children: match.jargon_categories.map(function (r) {
59 | return badgify(r.category.acronym);
60 | }),
61 | className: "flex gap-1"
62 | })
63 | ],
64 | className: "flex justify-between"
65 | }),
66 | JsxRuntime.jsxs("div", {
67 | children: [
68 | JsxRuntime.jsx("div", {
69 | children: match.name,
70 | className: "font-semibold group-hover:text-teal-700 dark:group-hover:text-teal-200"
71 | }),
72 | JsxRuntime.jsx("div", {
73 | children: JsxRuntime.jsx("ol", {
74 | children: match.translations.map(function (param) {
75 | return JsxRuntime.jsx("li", {
76 | children: param.name
77 | }, param.id);
78 | })
79 | }),
80 | className: "overflow-hidden group-hover:overflow-visible whitespace-nowrap group-hover:whitespace-normal text-ellipsis font-regular text-zinc-500 group-hover:text-teal-600 dark:text-zinc-400 dark:group-hover:text-teal-300"
81 | })
82 | ],
83 | className: "flex-none inline-grid grid-cols-1"
84 | }),
85 | JsxRuntime.jsx("div", {
86 | children: "댓글 " + Core__Option.getOr(Core__Option.map(match.comments_aggregate.aggregate, (function (x) {
87 | return x.count;
88 | })), 0).toString() + "개",
89 | className: "flex-none text-xs dark:text-zinc-400"
90 | })
91 | ],
92 | className: "h-[100%] p-4",
93 | onClick: (function (param) {
94 | RescriptReactRouter.push("/jargon/" + id);
95 | })
96 | });
97 | }
98 |
99 | var make = JargonCard;
100 |
101 | export {
102 | JargonCardFragment ,
103 | badgify ,
104 | make ,
105 | }
106 | /* react/jsx-runtime Not a pure module */
107 |
--------------------------------------------------------------------------------
/src/JargonCard.res:
--------------------------------------------------------------------------------
1 | module JargonCardFragment = %relay(`
2 | fragment JargonCard_jargon on jargon {
3 | id
4 | name
5 | updated_at
6 | jargon_categories(order_by: { category: { name: asc } }) {
7 | category {
8 | acronym
9 | }
10 | }
11 | translations(order_by: { name: asc }, limit: 20) {
12 | id
13 | name
14 | }
15 | comments_aggregate {
16 | aggregate {
17 | count
18 | }
19 | }
20 | }
21 | `)
22 |
23 | let badgify = text => {text->React.string}
24 |
25 | @react.component
26 | let make = (~jargonCardRef) => {
27 | let {
28 | id,
29 | name,
30 | updated_at,
31 | jargon_categories,
32 | translations,
33 | comments_aggregate,
34 | } = JargonCardFragment.use(jargonCardRef)
35 |
36 | RescriptReactRouter.push(`/jargon/${id}`)}>
37 | // first row
38 |
39 |
40 | {`최근 활동 ${updated_at->Date.fromString->DateFormat.timeAgo}`->React.string}
41 |
42 |
43 | {jargon_categories
44 | ->Array.map(r => r.category.acronym->badgify)
45 | ->React.array}
46 |
47 |
48 | // second row
49 |
50 |
51 | {name->React.string}
52 |
53 |
55 |
56 | {translations
57 | ->Array.map(({id, name}) => - {name->React.string}
)
58 | ->React.array}
59 |
60 |
61 |
62 | // third row
63 |
64 | {`댓글 ${comments_aggregate.aggregate
65 | ->Option.map(x => x.count)
66 | ->Option.getOr(0)
67 | ->Int.toString}개`->React.string}
68 |
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/JargonList.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Loader from "./Loader.js";
4 | import * as JargonCard from "./JargonCard.js";
5 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
6 | import * as JsxRuntime from "react/jsx-runtime";
7 | import * as RescriptRelay_Fragment from "rescript-relay/src/RescriptRelay_Fragment.js";
8 | import * as JargonListOrderQuery_graphql from "./__generated__/JargonListOrderQuery_graphql.js";
9 | import ReactInfiniteScrollComponent from "react-infinite-scroll-component";
10 | import * as JargonListOrderRefetchQuery_graphql from "./__generated__/JargonListOrderRefetchQuery_graphql.js";
11 |
12 | var getConnectionNodes = JargonListOrderQuery_graphql.Utils.getConnectionNodes;
13 |
14 | var convertFragment = JargonListOrderQuery_graphql.Internal.convertFragment;
15 |
16 | function waitForFragmentData(environment, fRef) {
17 | return RescriptRelay_Fragment.waitForFragmentData(environment, JargonListOrderQuery_graphql.node, convertFragment, fRef);
18 | }
19 |
20 | function use(fRef) {
21 | return RescriptRelay_Fragment.useFragment(JargonListOrderQuery_graphql.node, convertFragment, fRef);
22 | }
23 |
24 | function useOpt(fRef) {
25 | return RescriptRelay_Fragment.useFragmentOpt(fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(fRef)) : undefined, JargonListOrderQuery_graphql.node, convertFragment);
26 | }
27 |
28 | function readResolverFragment(fRef) {
29 | return RescriptRelay_Fragment.read(JargonListOrderQuery_graphql.node, convertFragment, fRef);
30 | }
31 |
32 | var makeRefetchVariables = JargonListOrderRefetchQuery_graphql.Types.makeRefetchVariables;
33 |
34 | var convertRefetchVariables = JargonListOrderRefetchQuery_graphql.Internal.convertVariables;
35 |
36 | function useRefetchable(fRef) {
37 | return RescriptRelay_Fragment.useRefetchableFragment(JargonListOrderQuery_graphql.node, convertFragment, convertRefetchVariables, fRef);
38 | }
39 |
40 | function usePagination(fRef) {
41 | return RescriptRelay_Fragment.usePaginationFragment(JargonListOrderQuery_graphql.node, fRef, convertFragment, convertRefetchVariables);
42 | }
43 |
44 | function useBlockingPagination(fRef) {
45 | return RescriptRelay_Fragment.useBlockingPaginationFragment(JargonListOrderQuery_graphql.node, fRef, convertFragment, convertRefetchVariables);
46 | }
47 |
48 | var JargonListOrderQuery = {
49 | getConnectionNodes: getConnectionNodes,
50 | Types: undefined,
51 | Operation: undefined,
52 | convertFragment: convertFragment,
53 | waitForFragmentData: waitForFragmentData,
54 | use: use,
55 | useOpt: useOpt,
56 | readResolverFragment: readResolverFragment,
57 | makeRefetchVariables: makeRefetchVariables,
58 | convertRefetchVariables: convertRefetchVariables,
59 | useRefetchable: useRefetchable,
60 | usePagination: usePagination,
61 | useBlockingPagination: useBlockingPagination
62 | };
63 |
64 | function JargonList(props) {
65 | var match = usePagination(props.query);
66 | var loadNext = match.loadNext;
67 | var rows = getConnectionNodes(match.data.jargon_connection).map(function (node) {
68 | return [
69 | node.id,
70 | node.fragmentRefs
71 | ];
72 | });
73 | return JsxRuntime.jsx(ReactInfiniteScrollComponent, {
74 | className: "grid sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 gap-x-6 gap-y-2 pb-10",
75 | dataLength: rows.length,
76 | next: (function () {
77 | loadNext(40, undefined);
78 | }),
79 | hasMore: match.hasNext,
80 | loader: JsxRuntime.jsx("div", {
81 | children: JsxRuntime.jsx(Loader.make, {}),
82 | className: "grid justify-center content-center"
83 | }),
84 | children: rows.map(function (param) {
85 | return JsxRuntime.jsx("li", {
86 | children: JsxRuntime.jsx(JargonCard.make, {
87 | jargonCardRef: param[1]
88 | }),
89 | className: "flex flex-col gap-y-2 group cursor-pointer bg-white hover:bg-teal-50 rounded-xl shadow-md dark:bg-zinc-900 dark:hover:bg-teal-900"
90 | }, param[0]);
91 | })
92 | });
93 | }
94 |
95 | var make = JargonList;
96 |
97 | export {
98 | JargonListOrderQuery ,
99 | make ,
100 | }
101 | /* Loader Not a pure module */
102 |
--------------------------------------------------------------------------------
/src/JargonList.res:
--------------------------------------------------------------------------------
1 | module JargonListOrderQuery = %relay(`
2 | fragment JargonListOrderQuery on query_root
3 | @refetchable(queryName: "JargonListOrderRefetchQuery")
4 | @argumentDefinitions(
5 | count: { type: "Int", defaultValue: 40 }
6 | cursor: { type: "String" }
7 | ) {
8 | jargon_connection(
9 | order_by: $directions
10 | first: $count
11 | after: $cursor
12 | where: {
13 | _and: [
14 | {
15 | _or: [
16 | { name_lower_no_spaces: { _iregex: $searchTerm } }
17 | { translations: { name_lower_no_spaces: { _iregex: $searchTerm } } }
18 | ]
19 | }
20 | {
21 | _or: [
22 | { jargon_categories: { category_id: { _in: $categoryIDs } } }
23 | { _not: { jargon_categories: { _and: [] } } }
24 | ]
25 | }
26 | { _and: $onlyWithoutTranslationFilter }
27 | ]
28 | }
29 | ) @connection(key: "JargonListOrderQuery_jargon_connection") {
30 | edges {
31 | node {
32 | id
33 | ...JargonCard_jargon
34 | }
35 | }
36 | }
37 | }
38 | `)
39 |
40 | @react.component
41 | let make = (~query) => {
42 | let (rows, hasMore, loadNext) = {
43 | let {
44 | data: {jargon_connection: jargonConnection},
45 | hasNext,
46 | loadNext,
47 | } = JargonListOrderQuery.usePagination(query)
48 | (
49 | jargonConnection
50 | ->JargonListOrderQuery.getConnectionNodes
51 | ->Array.map(node => (node.id, node.fragmentRefs)),
52 | hasNext,
53 | loadNext,
54 | )
55 | }
56 |
57 | Array.length}
60 | next={() => loadNext(~count=40)->RescriptRelay.Disposable.ignore}
61 | hasMore
62 | loader={
63 |
64 |
}>
65 | {rows
66 | ->Array.map(((key, jargonCardRef)) =>
67 |
70 |
71 |
72 | )
73 | ->React.array}
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/JargonPost.res:
--------------------------------------------------------------------------------
1 | module JargonPostQuery = %relay(`
2 | query JargonPostQuery($id: ID!) {
3 | node(id: $id) {
4 | ... on jargon {
5 | name
6 | comments_aggregate {
7 | aggregate {
8 | count
9 | }
10 | }
11 | jargon_categories(order_by: { category: { name: asc } }) {
12 | category {
13 | acronym
14 | }
15 | }
16 | ...RelatedJargons_jargon
17 | ...Translation_jargon
18 | ...CommentSection_jargon
19 | }
20 | }
21 | }
22 | `)
23 |
24 | @react.component
25 | let make = (~jargonID) => {
26 | let {node} = JargonPostQuery.use(~variables={id: jargonID})
27 |
28 | switch node {
29 | | None => React.null
30 | | Some(node) =>
31 | switch node {
32 | | Jargon(jargon) =>
33 |
34 |
35 | // Jargon
36 |
37 |
38 | {jargon.jargon_categories
39 | ->Array.map(r => r.category.acronym->Util.badgify)
40 | ->React.array}
41 | {"+"->Util.badgify(~onClick=_ =>
42 | RescriptReactRouter.replace(`/edit-categories/${jargonID}`)
43 | )}
44 |
45 |
{jargon.name->React.string}
46 |
47 | // Translation
48 |
49 | // New translation
50 |
55 | // Related Jargons
56 |
57 |
58 |
59 |
60 | {jargon.comments_aggregate.aggregate
61 | ->Option.map(x => x.count)
62 | ->Option.getOr(0)
63 | ->Int.toString
64 | ->React.string}
65 |
66 | // New comment
67 |
68 | // Comments
69 |
70 |
71 |
72 |
73 | | UnselectedUnionMember(resp) => raise(Exc.HTTPError(404, resp))
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/JargonRandomList.res:
--------------------------------------------------------------------------------
1 | module JargonRandomListOrderQuery = %relay(`
2 | query JargonRandomListOrderQuery(
3 | $seed: seed_float!
4 | $categoryIDs: [Int!]!
5 | $onlyWithoutTranslationFilter: [jargon_bool_exp!]!
6 | ) {
7 | list_jargon_random_connection(
8 | args: { seed: $seed }
9 | where: {
10 | _and: [
11 | {
12 | _or: [
13 | { jargon_categories: { category_id: { _in: $categoryIDs } } }
14 | { _not: { jargon_categories: { _and: [] } } }
15 | ]
16 | }
17 | { _and: $onlyWithoutTranslationFilter }
18 | ]
19 | }
20 | first: 40
21 | ) {
22 | edges {
23 | node {
24 | id
25 | ...JargonCard_jargon
26 | }
27 | }
28 | }
29 | }
30 | `)
31 |
32 | @react.component
33 | let make = (~seed, ~categoryIDs, ~onlyWithoutTranslation) => {
34 | let {list_jargon_random_connection: {edges}} = JargonRandomListOrderQuery.use(
35 | ~variables={
36 | seed: seed->Float.toString,
37 | categoryIDs,
38 | onlyWithoutTranslationFilter: if onlyWithoutTranslation {
39 | [
40 | {
41 | _not: {translations: {}},
42 | },
43 | ]
44 | } else {
45 | []
46 | },
47 | },
48 | )
49 | let rows = edges->Array.map(({node}) => (node.id, node.fragmentRefs))
50 |
51 |
52 | {rows
53 | ->Array.map(((key, jargonCardRef)) =>
54 |
57 |
58 |
59 | )
60 | ->React.array}
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/LazyComponents.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "@rescript/react/src/React.js";
4 |
5 | var make = React.lazy_(function () {
6 | return import("./SignIn.js").then(function (m) {
7 | return m.make;
8 | });
9 | });
10 |
11 | var SignIn = {
12 | make: make
13 | };
14 |
15 | var make$1 = React.lazy_(function () {
16 | return import("./SignOut.js").then(function (m) {
17 | return m.make;
18 | });
19 | });
20 |
21 | var SignOut = {
22 | make: make$1
23 | };
24 |
25 | var make$2 = React.lazy_(function () {
26 | return import("./Profile.js").then(function (m) {
27 | return m.make;
28 | });
29 | });
30 |
31 | var Profile = {
32 | make: make$2
33 | };
34 |
35 | var make$3 = React.lazy_(function () {
36 | return import("./NewJargon.js").then(function (m) {
37 | return m.make;
38 | });
39 | });
40 |
41 | var NewJargon = {
42 | make: make$3
43 | };
44 |
45 | var make$4 = React.lazy_(function () {
46 | return import("./NewTranslation.js").then(function (m) {
47 | return m.make;
48 | });
49 | });
50 |
51 | var NewTranslation = {
52 | make: make$4
53 | };
54 |
55 | var make$5 = React.lazy_(function () {
56 | return import("./JargonPost.js").then(function (m) {
57 | return m.make;
58 | });
59 | });
60 |
61 | var JargonPost = {
62 | make: make$5
63 | };
64 |
65 | var make$6 = React.lazy_(function () {
66 | return import("./Why.js").then(function (m) {
67 | return m.make;
68 | });
69 | });
70 |
71 | var Why = {
72 | make: make$6
73 | };
74 |
75 | var make$7 = React.lazy_(function () {
76 | return import("./Colophon.js").then(function (m) {
77 | return m.make;
78 | });
79 | });
80 |
81 | var Colophon = {
82 | make: make$7
83 | };
84 |
85 | export {
86 | SignIn ,
87 | SignOut ,
88 | Profile ,
89 | NewJargon ,
90 | NewTranslation ,
91 | JargonPost ,
92 | Why ,
93 | Colophon ,
94 | }
95 | /* make Not a pure module */
96 |
--------------------------------------------------------------------------------
/src/LazyComponents.res:
--------------------------------------------------------------------------------
1 | module SignIn = {
2 | let make = React.lazy_(() => Js.import(SignIn.make))
3 | }
4 |
5 | module SignOut = {
6 | let make = React.lazy_(() => Js.import(SignOut.make))
7 | }
8 |
9 | module Profile = {
10 | let make = React.lazy_(() => Js.import(Profile.make))
11 | }
12 |
13 | module NewJargon = {
14 | let make = React.lazy_(() => Js.import(NewJargon.make))
15 | }
16 |
17 | module NewTranslation = {
18 | let make = React.lazy_(() => Js.import(NewTranslation.make))
19 | }
20 |
21 | module JargonPost = {
22 | let make = React.lazy_(() => Js.import(JargonPost.make))
23 | }
24 |
25 | module Why = {
26 | let make = React.lazy_(() => Js.import(Why.make))
27 | }
28 |
29 | module Colophon = {
30 | let make = React.lazy_(() => Js.import(Colophon.make))
31 | }
32 |
--------------------------------------------------------------------------------
/src/Loader.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function Loader(props) {
6 | return JsxRuntime.jsx("span", {
7 | className: "loading loading-dots loading-lg"
8 | });
9 | }
10 |
11 | var make = Loader;
12 |
13 | export {
14 | make ,
15 | }
16 | /* react/jsx-runtime Not a pure module */
17 |
--------------------------------------------------------------------------------
/src/Loader.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = () =>
3 |
--------------------------------------------------------------------------------
/src/MathJax.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/MathJax.res:
--------------------------------------------------------------------------------
1 | @module("better-react-mathjax") @react.component
2 | external make: (~children: React.element) => React.element = "MathJax"
3 |
--------------------------------------------------------------------------------
/src/MathJaxContext.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/MathJaxContext.res:
--------------------------------------------------------------------------------
1 | @module("better-react-mathjax") @react.component
2 | external make: (~config: 'a, ~children: React.element) => React.element = "MathJaxContext"
3 |
--------------------------------------------------------------------------------
/src/MultiValueLabel.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function MultiValueLabel(props) {
6 | var acronym = props.children.split(" ")[0];
7 | return JsxRuntime.jsx("div", {
8 | children: acronym,
9 | className: "badge badge-md ml-1"
10 | });
11 | }
12 |
13 | var make = MultiValueLabel;
14 |
15 | export {
16 | make ,
17 | }
18 | /* react/jsx-runtime Not a pure module */
19 |
--------------------------------------------------------------------------------
/src/MultiValueLabel.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~children: string) => {
3 | let acronym = children->String.split(" ")->Array.getUnsafe(0)
4 | {acronym->React.string}
5 | }
6 |
--------------------------------------------------------------------------------
/src/NavbarContainer.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Navbar from "./Navbar.js";
4 | import * as JsxRuntime from "react/jsx-runtime";
5 |
6 | function NavbarContainer(props) {
7 | return JsxRuntime.jsxs("div", {
8 | children: [
9 | JsxRuntime.jsx(Navbar.make, {}),
10 | props.children
11 | ]
12 | });
13 | }
14 |
15 | var make = NavbarContainer;
16 |
17 | export {
18 | make ,
19 | }
20 | /* Navbar Not a pure module */
21 |
--------------------------------------------------------------------------------
/src/NavbarContainer.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~children: React.element) => {
3 |
4 |
5 | children
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/NewTranslation.res:
--------------------------------------------------------------------------------
1 | module JargonQuery = %relay(`
2 | query NewTranslationJargonQuery($id: ID!) {
3 | node(id: $id) {
4 | ... on jargon {
5 | name
6 | }
7 | }
8 | }
9 | `)
10 |
11 | module NewTranslationMutation = %relay(`
12 | mutation NewTranslationMutation(
13 | $id: uuid!
14 | $jargonID: uuid!
15 | $authorID: String!
16 | $name: String!
17 | $commentID: uuid!
18 | $comment: String!
19 | $now: timestamptz!
20 | ) {
21 | insert_translation_one(
22 | object: {
23 | id: $id
24 | jargon_id: $jargonID
25 | author_id: $authorID
26 | name: $name
27 | comment_id: $commentID
28 | comment: {
29 | data: {
30 | id: $commentID
31 | jargon_id: $jargonID
32 | author_id: $authorID
33 | content: $comment
34 | }
35 | }
36 | }
37 | ) {
38 | id
39 | }
40 | update_jargon_by_pk(
41 | pk_columns: { id: $jargonID }
42 | _set: { updated_at: $now }
43 | ) {
44 | id
45 | }
46 | }
47 | `)
48 |
49 | @react.component
50 | let make = (~jargonID: string) => {
51 | let {signedIn, user} = React.useContext(SignInContext.context)
52 |
53 | React.useEffect0(() => {
54 | if signedIn {
55 | switch user->Nullable.toOption {
56 | | Some(_) => ()
57 | | None => RescriptReactRouter.replace("/logout") // Something went wrong
58 | }
59 | } else {
60 | RescriptReactRouter.replace("/login")
61 | }
62 |
63 | None
64 | })
65 |
66 | let (korean, setKorean) = React.useState(() => "")
67 | let handleTranslationChange = event => {
68 | let value = ReactEvent.Form.currentTarget(event)["value"]
69 | setKorean(_ => value)
70 | }
71 |
72 | let sanitizedKorean = korean->Util.sanitize
73 |
74 | let (comment, setComment) = React.useState(() => "")
75 | let handleCommentChange = event => {
76 | let value = ReactEvent.Form.currentTarget(event)["value"]
77 | setComment(_ => value)
78 | }
79 |
80 | let (newTranslationMutate, isNewTranslationMutating) = NewTranslationMutation.use()
81 |
82 | let handleSubmit = event => {
83 | // Prevent a page refresh, we are already listening for updates
84 | ReactEvent.Form.preventDefault(event)
85 |
86 | if sanitizedKorean->String.length < 1 {
87 | Window.alert("번역을 입력해주세요")
88 | } else if signedIn {
89 | switch user->Nullable.toOption {
90 | | Some(user) =>
91 | let comment = switch comment {
92 | | "" => `${sanitizedKorean->Util.eulLeul} 제안합니다.`
93 | | _ => comment
94 | }
95 |
96 | let (id, jargonID) = (jargonID, jargonID->Base64.retrieveOriginalIDString)
97 | switch jargonID {
98 | | Some(jargonID) => {
99 | let (translationID, commentID) = (Uuid.v4(), Uuid.v4())
100 | newTranslationMutate(
101 | ~variables={
102 | id: translationID,
103 | jargonID,
104 | authorID: user.uid,
105 | name: sanitizedKorean,
106 | commentID,
107 | comment,
108 | now: Date.make()->Date.toISOString,
109 | },
110 | ~onError=error => Js.Console.error(error),
111 | ~onCompleted=({insert_translation_one}, _errors) => {
112 | switch insert_translation_one {
113 | | Some(_) => RescriptReactRouter.replace(`/jargon/${id}`)
114 | | None => {
115 | Js.Console.error("Translation mutation failed")
116 | RescriptReactRouter.replace(`/jargon/${id}`)
117 | }
118 | }
119 | },
120 | )->ignore
121 | }
122 | | None => ()
123 | }
124 |
125 | | None => RescriptReactRouter.replace("/logout") // Something went wrong
126 | }
127 | } else {
128 | RescriptReactRouter.replace("/login")
129 | }
130 | }
131 |
132 | let {node} = JargonQuery.use(~variables={id: jargonID})
133 | switch node {
134 | | Some(Jargon({name: english})) =>
135 | if signedIn {
136 |
137 |
{`${english}의 쉬운 전문용어 제안하기`->React.string}
138 |
180 |
181 | } else {
182 | React.null
183 | }
184 | | _ => React.null
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/src/NewlineText.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function NewlineText(props) {
6 | return props.text.split("\n").map(function (s) {
7 | return JsxRuntime.jsx("p", {
8 | children: s
9 | });
10 | });
11 | }
12 |
13 | var make = NewlineText;
14 |
15 | export {
16 | make ,
17 | }
18 | /* react/jsx-runtime Not a pure module */
19 |
--------------------------------------------------------------------------------
/src/NewlineText.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~text) => {
3 | text->String.split("\n")->Array.map(s => {s->React.string}
)->React.array
4 | }
5 |
--------------------------------------------------------------------------------
/src/Profile.res:
--------------------------------------------------------------------------------
1 | module DisplayNameMutation = %relay(`
2 | mutation ProfileDisplayNameMutation($uid: String!, $displayName: String!) {
3 | update_user_by_pk(
4 | pk_columns: { id: $uid }
5 | _set: { display_name: $displayName }
6 | ) {
7 | id
8 | }
9 | }
10 | `)
11 |
12 | module SignedInProfile = {
13 | @react.component
14 | let make = (~user: Firebase.User.t) => {
15 | open Firebase
16 | let firestore = useFirestore()
17 |
18 | let (mutate, _isMutating) = DisplayNameMutation.use()
19 |
20 | let (displayName, setDisplayName) = React.useState(() => user.displayName->Option.getOr(""))
21 | let handleDisplayNameChange = event => {
22 | let value = ReactEvent.Form.currentTarget(event)["value"]
23 | setDisplayName(_ => value)
24 | }
25 |
26 | let (disabled, setDisabled) = React.useState(() => false)
27 |
28 | let handleSubmit = event => {
29 | // Prevent a page refresh, we are already listening for updates
30 | ReactEvent.Form.preventDefault(event)
31 |
32 | if displayName->String.length <= 0 {
33 | Window.alert("필명을 입력해주세요")
34 | } else {
35 | setDisabled(_ => true)
36 |
37 | (
38 | async () => {
39 | try {
40 | let authUpdate = user->Auth.updateProfile({displayName: displayName})
41 |
42 | let docUpdate = {
43 | async () => {
44 | let userDocRef = firestore->doc(~path=`users/${user.uid}`)
45 | let userDoc = await userDocRef->getDoc
46 | if !userDoc.exists() {
47 | Js.Console.warn("User document does not exist!")
48 | await userDocRef->setDoc({"displayName": displayName, "email": user.email})
49 | } else {
50 | await userDocRef->updateDoc({"displayName": displayName})
51 | }
52 | }
53 | }()
54 |
55 | mutate(~variables={uid: user.uid, displayName})->ignore
56 |
57 | (await Promise.all([authUpdate, docUpdate]))->ignore
58 | } catch {
59 | | e => Js.Console.warn(e)
60 | }
61 | setDisabled(_ => false)
62 | }
63 | )()->ignore
64 | }
65 | }
66 |
67 |
97 | }
98 | }
99 |
100 | @react.component
101 | let make = () => {
102 | let {signedIn, user} = React.useContext(SignInContext.context)
103 | switch (signedIn, user->Nullable.toOption) {
104 | | (false, _) | (_, None) => {
105 | RescriptReactRouter.replace("/login")
106 | React.null
107 | }
108 | | (true, Some(user)) =>
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/ReactIcons.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 |
4 | var FaGithub = {};
5 |
6 | export {
7 | FaGithub ,
8 | }
9 | /* No side effect */
10 |
--------------------------------------------------------------------------------
/src/ReactIcons.res:
--------------------------------------------------------------------------------
1 | module FaGithub = {
2 | @module("react-icons/fa") @react.component
3 | external make: (~className: string=?) => React.element = "FaGithub"
4 | }
5 |
--------------------------------------------------------------------------------
/src/ReactSocialLoginButtons.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 |
4 | var GoogleLoginButton = {};
5 |
6 | export {
7 | GoogleLoginButton ,
8 | }
9 | /* No side effect */
10 |
--------------------------------------------------------------------------------
/src/ReactSocialLoginButtons.res:
--------------------------------------------------------------------------------
1 | module GoogleLoginButton = {
2 | @react.component @module("react-social-login-buttons")
3 | external make: (~onClick: (. unit) => unit, ~children: React.element) => React.element =
4 | "GoogleLoginButton"
5 | }
6 |
--------------------------------------------------------------------------------
/src/RelatedJargons.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Util from "./Util.js";
4 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
5 | import * as JsxRuntime from "react/jsx-runtime";
6 | import * as RescriptReactRouter from "@rescript/react/src/RescriptReactRouter.js";
7 | import * as RescriptRelay_Fragment from "rescript-relay/src/RescriptRelay_Fragment.js";
8 | import * as RelatedJargons_jargon_graphql from "./__generated__/RelatedJargons_jargon_graphql.js";
9 |
10 | var convertFragment = RelatedJargons_jargon_graphql.Internal.convertFragment;
11 |
12 | function waitForFragmentData(environment, fRef) {
13 | return RescriptRelay_Fragment.waitForFragmentData(environment, RelatedJargons_jargon_graphql.node, convertFragment, fRef);
14 | }
15 |
16 | function use(fRef) {
17 | return RescriptRelay_Fragment.useFragment(RelatedJargons_jargon_graphql.node, convertFragment, fRef);
18 | }
19 |
20 | function useOpt(fRef) {
21 | return RescriptRelay_Fragment.useFragmentOpt(fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(fRef)) : undefined, RelatedJargons_jargon_graphql.node, convertFragment);
22 | }
23 |
24 | function readResolverFragment(fRef) {
25 | return RescriptRelay_Fragment.read(RelatedJargons_jargon_graphql.node, convertFragment, fRef);
26 | }
27 |
28 | var RelatedJargonsFragment = {
29 | Types: undefined,
30 | Operation: undefined,
31 | convertFragment: convertFragment,
32 | waitForFragmentData: waitForFragmentData,
33 | use: use,
34 | useOpt: useOpt,
35 | readResolverFragment: readResolverFragment
36 | };
37 |
38 | function RelatedJargons(props) {
39 | var match = use(props.relatedJargonsRef);
40 | return JsxRuntime.jsxs("div", {
41 | children: [
42 | JsxRuntime.jsx("div", {
43 | children: "연관 용어",
44 | className: "font-medium"
45 | }),
46 | JsxRuntime.jsx("div", {
47 | children: match.related_jargons.map(function (r) {
48 | return Util.badgify((function (param) {
49 | RescriptReactRouter.push("/jargon/" + r.jargon.id);
50 | }), r.jargon.name);
51 | }),
52 | className: "flex gap-1"
53 | })
54 | ],
55 | className: "flex gap-2"
56 | });
57 | }
58 |
59 | var make = RelatedJargons;
60 |
61 | export {
62 | RelatedJargonsFragment ,
63 | make ,
64 | }
65 | /* Util Not a pure module */
66 |
--------------------------------------------------------------------------------
/src/RelatedJargons.res:
--------------------------------------------------------------------------------
1 | module RelatedJargonsFragment = %relay(`
2 | fragment RelatedJargons_jargon on jargon {
3 | related_jargons {
4 | jargon {
5 | id
6 | name
7 | }
8 | }
9 | }
10 | `)
11 |
12 | @react.component
13 | let make = (~relatedJargonsRef) => {
14 | let {related_jargons} = RelatedJargonsFragment.use(relatedJargonsRef)
15 |
16 |
17 |
{"연관 용어"->React.string}
18 |
19 | {related_jargons
20 | ->Array.map(r =>
21 | r.jargon.name->Util.badgify(~onClick=_ =>
22 | RescriptReactRouter.push(`/jargon/${r.jargon.id}`)
23 | )
24 | )
25 | ->React.array}
26 | // {"+"->Util.badgify}
27 |
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/RelayWrapper.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Exc from "./Exc.js";
4 | import * as React from "react";
5 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
6 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
7 | import * as TokenContext from "./TokenContext.js";
8 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
9 | import * as RelayRuntime from "relay-runtime";
10 | import * as JsxRuntime from "react/jsx-runtime";
11 |
12 | function RelayWrapper(props) {
13 | var token = React.useContext(TokenContext.context);
14 | var fetchQuery = async function (operation, variables, _cacheConfig, _uploadables) {
15 | var resp = await fetch("https://easyword.hasura.app/v1beta1/relay", {
16 | method: "POST",
17 | body: Caml_option.some(Core__Option.getExn(JSON.stringify({
18 | query: operation.text,
19 | variables: variables
20 | }), undefined)),
21 | headers: Caml_option.some(token !== undefined ? new Headers({
22 | "content-type": "application/json",
23 | authorization: "Bearer " + token
24 | }) : new Headers({
25 | "content-type": "application/json"
26 | }))
27 | });
28 | if (resp.ok) {
29 | return await resp.json();
30 | }
31 | throw {
32 | RE_EXN_ID: Exc.GraphQLError,
33 | _1: "Request failed: " + resp.statusText,
34 | Error: new Error()
35 | };
36 | };
37 | var network = RelayRuntime.Network.create(fetchQuery);
38 | var environment = RescriptRelay.Environment.make(network, RescriptRelay.Store.make(new RelayRuntime.RecordSource(), 10, undefined), undefined, undefined, undefined, undefined, undefined);
39 | return JsxRuntime.jsx(RescriptRelay.Context.Provider.make, {
40 | environment: environment,
41 | children: props.children
42 | });
43 | }
44 |
45 | var make = RelayWrapper;
46 |
47 | export {
48 | make ,
49 | }
50 | /* react Not a pure module */
51 |
--------------------------------------------------------------------------------
/src/RelayWrapper.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~children: React.element) => {
3 | let token = React.useContext(TokenContext.context)
4 |
5 | let fetchQuery: RescriptRelay.Network.fetchFunctionPromise = async (
6 | operation,
7 | variables,
8 | _cacheConfig,
9 | _uploadables,
10 | ) => {
11 | open Fetch
12 | let resp = await fetch(
13 | "https://easyword.hasura.app/v1beta1/relay",
14 | {
15 | method: #POST,
16 | body: {"query": operation.text, "variables": variables}
17 | ->JSON.stringifyAny
18 | ->Option.getExn
19 | ->Body.string,
20 | headers: switch token {
21 | | Some(token) =>
22 | Headers.fromObject({
23 | "content-type": "application/json",
24 | "authorization": `Bearer ${token}`,
25 | })
26 | | None =>
27 | Headers.fromObject({
28 | "content-type": "application/json",
29 | })
30 | },
31 | },
32 | )
33 |
34 | if resp->Response.ok {
35 | await resp->Response.json
36 | } else {
37 | raise(Exc.GraphQLError("Request failed: " ++ Response.statusText(resp)))
38 | }
39 | }
40 |
41 | let network = RescriptRelay.Network.makePromiseBased(~fetchFunction=fetchQuery)
42 |
43 | let environment = RescriptRelay.Environment.make(
44 | ~network,
45 | ~store=RescriptRelay.Store.make(
46 | ~source=RescriptRelay.RecordSource.make(),
47 | ~gcReleaseBufferSize=10 /* This sets the query cache size to 10 */,
48 | ),
49 | )
50 |
51 | children
52 | }
53 |
--------------------------------------------------------------------------------
/src/SearchBar.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function SearchBar(props) {
6 | return JsxRuntime.jsx("div", {
7 | children: JsxRuntime.jsx("input", {
8 | className: "input input-bordered w-full rounded-lg text-sm shadow-lg",
9 | id: "search-bar",
10 | placeholder: "정규식으로 검색해보세요",
11 | type: "search",
12 | value: props.searchTerm,
13 | onChange: props.onChange
14 | }),
15 | className: "relative flex place-items-center gap-1"
16 | });
17 | }
18 |
19 | var make = SearchBar;
20 |
21 | export {
22 | make ,
23 | }
24 | /* react/jsx-runtime Not a pure module */
25 |
--------------------------------------------------------------------------------
/src/SearchBar.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~searchTerm, ~onChange) => {
3 |
4 |
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/Select.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/Select.res:
--------------------------------------------------------------------------------
1 | type selectOption<'a> = {label: string, value: 'a}
2 |
3 | type classNamesConfig<'props> = {
4 | clearIndicator?: 'props => string,
5 | container?: 'props => string,
6 | control?: 'props => string,
7 | dropdownIndicator?: 'props => string,
8 | group?: 'props => string,
9 | groupHeading?: 'props => string,
10 | indicatorsContainer?: 'props => string,
11 | indicatorSeparator?: 'props => string,
12 | input?: 'props => string,
13 | loadingIndicator?: 'props => string,
14 | loadingMessage?: 'props => string,
15 | menu?: 'props => string,
16 | menuList?: 'props => string,
17 | menuPortal?: 'props => string,
18 | multiValue?: 'props => string,
19 | multiValueLabel?: 'props => string,
20 | multiValueRemove?: 'props => string,
21 | noOptionsMessage?: 'props => string,
22 | option?: 'props => string,
23 | placeholder?: 'props => string,
24 | singleValue?: 'props => string,
25 | valueContainer?: 'props => string,
26 | }
27 |
28 | type selectComponentsConfig<'props> = {
29 | @as("ClearIndicator") clearIndicator?: 'props => React.element,
30 | @as("Container") container?: 'props => React.element,
31 | @as("Control") control?: 'props => React.element,
32 | @as("DropdownIndicator") dropdownIndicator?: 'props => React.element,
33 | @as("Group") group?: 'props => React.element,
34 | @as("GroupHeading") groupHeading?: 'props => React.element,
35 | @as("IndicatorsContainer") indicatorsContainer?: 'props => React.element,
36 | @as("IndicatorSeparator") indicatorSeparator?: 'props => React.element,
37 | @as("Input") input?: 'props => React.element,
38 | @as("LoadingIndicator") loadingIndicator?: 'props => React.element,
39 | @as("LoadingMessage") loadingMessage?: 'props => React.element,
40 | @as("Menu") menu?: 'props => React.element,
41 | @as("MenuList") menuList?: 'props => React.element,
42 | @as("MenuPortal") menuPortal?: 'props => React.element,
43 | @as("MultiValue") multiValue?: 'props => React.element,
44 | @as("MultiValueLabel") multiValueLabel?: 'props => React.element,
45 | @as("MultiValueRemove") multiValueRemove?: 'props => React.element,
46 | @as("NoOptionsMessage") noOptionsMessage?: 'props => React.element,
47 | @as("Option") option?: 'props => React.element,
48 | @as("Placeholder") placeholder?: 'props => React.element,
49 | @as("SingleValue") singleValue?: 'props => React.element,
50 | @as("ValueContainer") valueContainer?: 'props => React.element,
51 | }
52 |
53 | @module("react-select") @react.component
54 | external make: (
55 | ~className: string=?,
56 | ~classNames: classNamesConfig<_>=?,
57 | ~components: selectComponentsConfig<_>=?,
58 | ~defaultValue: _=?,
59 | ~value: _=?,
60 | ~onChange: array> => unit,
61 | ~options: array>,
62 | ~isSearchable: bool=?,
63 | ~isClearable: bool=?,
64 | ~isMulti: bool=?,
65 | ~unstyled: bool=?,
66 | ~placeholder: string=?,
67 | ~noOptionsMessage: _ => string=?,
68 | ) => React.element = "default"
69 |
--------------------------------------------------------------------------------
/src/SignIn.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 | import * as Loader from "./Loader.js";
5 | import * as Firebase from "./Firebase.js";
6 | import * as Reactfire from "reactfire";
7 | import * as Auth from "firebase/auth";
8 | import * as JsxRuntime from "react/jsx-runtime";
9 | import * as Firestore from "firebase/firestore";
10 | import * as RescriptReactRouter from "@rescript/react/src/RescriptReactRouter.js";
11 | import * as ReactSocialLoginButtons from "react-social-login-buttons";
12 |
13 | var uiConfig = {
14 | signInFlow: "popup",
15 | signInOptions: [Firebase.Auth.GoogleAuthProvider.providerID],
16 | callbacks: {
17 | signInSuccessWithAuthResult: (function () {
18 | return false;
19 | })
20 | }
21 | };
22 |
23 | function SignIn(props) {
24 | var match = Reactfire.useSigninCheck();
25 | var data = match.data;
26 | var firestore = Reactfire.useFirestore();
27 | React.useEffect((function () {
28 | if (data !== undefined && data.signedIn) {
29 | var user = data.user;
30 | if (!(user == null)) {
31 | var photoURL = user.photoURL;
32 | var email = user.email;
33 | var displayName = user.displayName;
34 | var uid = user.uid;
35 | ((async function () {
36 | var userDocRef = Firestore.doc(firestore, "users/" + uid);
37 | await Firestore.setDoc(userDocRef, {
38 | displayName: displayName,
39 | email: email,
40 | photoURL: photoURL
41 | }, {
42 | merge: true
43 | });
44 | if (displayName !== undefined) {
45 | return RescriptReactRouter.replace("/");
46 | } else {
47 | return RescriptReactRouter.replace("/profile");
48 | }
49 | })());
50 | }
51 |
52 | }
53 |
54 | }), [data]);
55 | var auth = Reactfire.useAuth();
56 | if (match.status === "success") {
57 | if (data !== undefined && !data.signedIn) {
58 | return JsxRuntime.jsx("div", {
59 | children: JsxRuntime.jsxs("div", {
60 | children: [
61 | JsxRuntime.jsx("div", {
62 | children: "로그인",
63 | className: "text-3xl font-normal text-center"
64 | }),
65 | JsxRuntime.jsx(ReactSocialLoginButtons.GoogleLoginButton, {
66 | onClick: (function () {
67 | Auth.signInWithPopup(auth, new Auth.GoogleAuthProvider());
68 | }),
69 | children: JsxRuntime.jsx("div", {
70 | children: "Sign in with Google",
71 | className: "text-sm"
72 | })
73 | })
74 | ],
75 | className: "h-96 w-96 place-content-center bg-zinc-50 bg-opacity-30 backdrop-blur-lg drop-shadow-lg rounded-xl grid content-center gap-3 text-zinc-800 dark:text-zinc-50"
76 | }),
77 | className: "h-screen bg-cover bg-center bg-[url('/layered-waves.svg')] justify-self-stretch grid justify-center content-center"
78 | });
79 | } else {
80 | return null;
81 | }
82 | } else {
83 | return JsxRuntime.jsx("div", {
84 | children: JsxRuntime.jsx(Loader.make, {}),
85 | className: "h-screen grid justify-center content-center"
86 | });
87 | }
88 | }
89 |
90 | var make = SignIn;
91 |
92 | export {
93 | uiConfig ,
94 | make ,
95 | }
96 | /* react Not a pure module */
97 |
--------------------------------------------------------------------------------
/src/SignIn.res:
--------------------------------------------------------------------------------
1 | open Firebase
2 | open ReactSocialLoginButtons
3 |
4 | let uiConfig = {
5 | "signInFlow": "popup",
6 | "signInOptions": [Auth.GoogleAuthProvider.providerID],
7 | "callbacks": {
8 | "signInSuccessWithAuthResult": () => false,
9 | },
10 | }
11 |
12 | @react.component
13 | let make = () => {
14 | let {status, data} = useSigninCheck()
15 |
16 | let firestore = useFirestore()
17 |
18 | React.useEffect1(() => {
19 | // Js.Console.log(data)
20 | switch data {
21 | | None => ()
22 | | Some({signedIn, user}) =>
23 | if signedIn {
24 | switch user->Nullable.toOption {
25 | | Some({uid, displayName, email, photoURL}) =>
26 | // Set uid. This is safe due to the security rule:
27 | // allow write: if request.auth.uid == uid;
28 |
29 | (
30 | async () => {
31 | let userDocRef = firestore->doc(~path=`users/${uid}`)
32 | await userDocRef->setDoc2(
33 | {
34 | "displayName": displayName,
35 | "email": email,
36 | "photoURL": photoURL,
37 | },
38 | {"merge": true},
39 | )
40 |
41 | switch displayName {
42 | | Some(_) => RescriptReactRouter.replace("/")
43 | | None => RescriptReactRouter.replace("/profile")
44 | }
45 | }
46 | )()->ignore
47 |
48 | | None => () // Something went wrong
49 | }
50 | }
51 | }
52 | None
53 | }, [data])
54 |
55 | let auth = useAuth()
56 |
57 | switch status {
58 | | #loading =>
59 |
60 |
61 |
62 |
63 | | #success =>
64 | switch data {
65 | | None | Some({signedIn: true}) => React.null
66 | | Some({signedIn: false}) =>
67 |
69 |
71 |
{React.string(`로그인`)}
72 |
{
74 | open Auth
75 | signInWithPopup(auth, FederatedAuthProvider.googleAuthProvider())->ignore
76 | }}>
77 | {"Sign in with Google"->React.string}
78 |
79 |
80 |
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/SignInContext.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 |
5 | var context = React.createContext({
6 | signedIn: false,
7 | user: null
8 | });
9 |
10 | var make = context.Provider;
11 |
12 | var Provider = {
13 | make: make
14 | };
15 |
16 | export {
17 | context ,
18 | Provider ,
19 | }
20 | /* context Not a pure module */
21 |
--------------------------------------------------------------------------------
/src/SignInContext.res:
--------------------------------------------------------------------------------
1 | open React
2 |
3 | let context = createContext({Firebase.signedIn: false, user: Nullable.null})
4 |
5 | module Provider = {
6 | let make = Context.provider(context)
7 | }
8 |
--------------------------------------------------------------------------------
/src/SignInWrapper.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 | import * as Loader from "./Loader.js";
5 | import * as Reactfire from "reactfire";
6 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
7 | import * as TokenContext from "./TokenContext.js";
8 | import * as SignInContext from "./SignInContext.js";
9 | import * as Auth from "firebase/auth";
10 | import * as JsxRuntime from "react/jsx-runtime";
11 | import * as Firestore from "firebase/firestore";
12 |
13 | function SignInWrapper(props) {
14 | var match = Reactfire.useSigninCheck();
15 | var firestore = Reactfire.useFirestore();
16 | var auth = Reactfire.useAuth();
17 | var match$1 = React.useState(function () {
18 |
19 | });
20 | var setToken = match$1[1];
21 | React.useEffect(function () {
22 | var userDocUnsub = {
23 | contents: undefined
24 | };
25 | var authStateChangeUnsub = Auth.onAuthStateChanged(auth, (async function (user) {
26 | if (user == null) {
27 | return setToken(function (param) {
28 |
29 | });
30 | }
31 | var token = await user.getIdToken(false);
32 | var match = await user.getIdTokenResult(false);
33 | var hasuraClaim = match.claims["https://hasura.io/jwt/claims"];
34 | if (hasuraClaim !== undefined) {
35 | return setToken(function (param) {
36 | return token;
37 | });
38 | }
39 | var userDocRef = Firestore.doc(firestore, "users/" + user.uid);
40 | userDocUnsub.contents = Firestore.onSnapshot(userDocRef, (async function (userDoc) {
41 | var match = userDoc.data()["refreshTime"];
42 | if (match === undefined) {
43 | return ;
44 | }
45 | var token = await user.getIdToken(true);
46 | return setToken(function (param) {
47 | return token;
48 | });
49 | }));
50 | }));
51 | return (function () {
52 | authStateChangeUnsub();
53 | var unsub = userDocUnsub.contents;
54 | if (unsub !== undefined) {
55 | return unsub();
56 | }
57 |
58 | });
59 | });
60 | if (match.status === "success") {
61 | return JsxRuntime.jsx(SignInContext.Provider.make, {
62 | value: Core__Option.getExn(match.data, undefined),
63 | children: JsxRuntime.jsx(TokenContext.Provider.make, {
64 | value: match$1[0],
65 | children: props.children
66 | })
67 | });
68 | } else {
69 | return JsxRuntime.jsx("div", {
70 | children: JsxRuntime.jsx(Loader.make, {}),
71 | className: "h-screen grid justify-center content-center"
72 | });
73 | }
74 | }
75 |
76 | var make = SignInWrapper;
77 |
78 | export {
79 | make ,
80 | }
81 | /* react Not a pure module */
82 |
--------------------------------------------------------------------------------
/src/SignInWrapper.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = (~children: React.element) => {
3 | open Firebase
4 |
5 | let {status, data: signInData} = Firebase.useSigninCheck()
6 | let firestore = useFirestore()
7 | let auth = useAuth()
8 | let (token, setToken) = React.useState(() => None)
9 | // Console.log(`token: ${token->Option.getOr("None")}`)
10 |
11 | React.useEffectOnEveryRender(() => {
12 | let userDocUnsub = ref(None)
13 |
14 | let authStateChangeUnsub = auth->Auth.onAuthStateChanged(async user => {
15 | switch user->Nullable.toOption {
16 | | Some(user) => {
17 | let token = await user->Auth.AuthUser.getIdToken(~forceRefresh=false)
18 | // Console.log(`Initial token: ${token}`)
19 |
20 | let {claims} = await user->Auth.AuthUser.getIdTokenResult(~forceRefresh=false)
21 | let hasuraClaim = claims->Dict.get("https://hasura.io/jwt/claims")
22 | // Console.log(`hasuraClaim: ${hasuraClaim->Option.getOr("None")}`)
23 | switch hasuraClaim {
24 | | Some(_hasuraClaim) =>
25 | // Console.log(
26 | // `Claim found! ${_hasuraClaim->JSON.Encode.stringifyAny->Option.getOr("None")}`,
27 | // )
28 | setToken(_ => Some(token))
29 |
30 | | None => {
31 | let userDocRef = firestore->doc(~path=`users/${user.uid}`)
32 | // Console.log(`uid: ${user.uid}`)
33 | userDocUnsub :=
34 | userDocRef->onSnapshot(
35 | async userDoc => {
36 | switch userDoc.data()->Dict.get("refreshTime") {
37 | | Some(_) => {
38 | let token = await user->Auth.AuthUser.getIdToken(~forceRefresh=true)
39 | // Console.log(`New token: ${token}`)
40 | setToken(_ => Some(token))
41 | }
42 | | None => () // Console.log("refreshTime not yet found")
43 | }
44 | },
45 | )
46 | }
47 | }
48 | }
49 | | None => setToken(_ => None)
50 | }
51 | })
52 |
53 | Some(
54 | () => {
55 | let () = authStateChangeUnsub()
56 |
57 | switch userDocUnsub.contents {
58 | | None => ()
59 | | Some(unsub) => unsub()
60 | }
61 | },
62 | )
63 | })
64 |
65 | switch status {
66 | | #loading =>
67 |
68 |
69 |
70 | | #success =>
71 | Option.getExn}>
72 | children
73 |
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/SignOut.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 | import * as Reactfire from "reactfire";
5 | import * as Auth from "firebase/auth";
6 | import * as RescriptReactRouter from "@rescript/react/src/RescriptReactRouter.js";
7 |
8 | function SignOut(props) {
9 | var auth = Reactfire.useAuth();
10 | React.useEffect(function () {
11 | var signOut = async function () {
12 | await Auth.signOut(auth);
13 | return RescriptReactRouter.replace("/");
14 | };
15 | signOut();
16 | });
17 | return null;
18 | }
19 |
20 | var make = SignOut;
21 |
22 | export {
23 | make ,
24 | }
25 | /* react Not a pure module */
26 |
--------------------------------------------------------------------------------
/src/SignOut.res:
--------------------------------------------------------------------------------
1 | open Firebase
2 |
3 | @react.component
4 | let make = () => {
5 | let auth = useAuth()
6 |
7 | React.useEffectOnEveryRender(() => {
8 | let signOut = async () => {
9 | await auth->Auth.signOut
10 | RescriptReactRouter.replace("/")
11 | }
12 | let _ = signOut()
13 | None
14 | })
15 |
16 | React.null
17 | }
18 |
--------------------------------------------------------------------------------
/src/Tips.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
4 | import * as TipsQuery_graphql from "./__generated__/TipsQuery_graphql.js";
5 | import * as JsxRuntime from "react/jsx-runtime";
6 | import * as RescriptRelay_Query from "rescript-relay/src/RescriptRelay_Query.js";
7 |
8 | var convertVariables = TipsQuery_graphql.Internal.convertVariables;
9 |
10 | var convertResponse = TipsQuery_graphql.Internal.convertResponse;
11 |
12 | var convertWrapRawResponse = TipsQuery_graphql.Internal.convertWrapRawResponse;
13 |
14 | var use = RescriptRelay_Query.useQuery(convertVariables, TipsQuery_graphql.node, convertResponse);
15 |
16 | var useLoader = RescriptRelay_Query.useLoader(convertVariables, TipsQuery_graphql.node, (function (prim) {
17 | return prim;
18 | }));
19 |
20 | var usePreloaded = RescriptRelay_Query.usePreloaded(TipsQuery_graphql.node, convertResponse, (function (prim) {
21 | return prim;
22 | }));
23 |
24 | var $$fetch = RescriptRelay_Query.$$fetch(TipsQuery_graphql.node, convertResponse, convertVariables);
25 |
26 | var fetchPromised = RescriptRelay_Query.fetchPromised(TipsQuery_graphql.node, convertResponse, convertVariables);
27 |
28 | var retain = RescriptRelay_Query.retain(TipsQuery_graphql.node, convertVariables);
29 |
30 | var TipsQuery = {
31 | Operation: undefined,
32 | Types: undefined,
33 | convertVariables: convertVariables,
34 | convertResponse: convertResponse,
35 | convertWrapRawResponse: convertWrapRawResponse,
36 | use: use,
37 | useLoader: useLoader,
38 | usePreloaded: usePreloaded,
39 | $$fetch: $$fetch,
40 | fetchPromised: fetchPromised,
41 | retain: retain
42 | };
43 |
44 | function Tips(props) {
45 | var match = use(undefined, undefined, undefined, undefined);
46 | var data = Core__Option.map(match.html_connection.edges[0], (function (edge) {
47 | return edge.node.data;
48 | }));
49 | if (data !== undefined) {
50 | return JsxRuntime.jsx("article", {
51 | className: "px-6 py-12 max-w-xl mx-auto md:max-w-4xl prose",
52 | dangerouslySetInnerHTML: {
53 | __html: data
54 | }
55 | });
56 | } else {
57 | return null;
58 | }
59 | }
60 |
61 | var make = Tips;
62 |
63 | export {
64 | TipsQuery ,
65 | make ,
66 | }
67 | /* use Not a pure module */
68 |
--------------------------------------------------------------------------------
/src/Tips.res:
--------------------------------------------------------------------------------
1 | module TipsQuery = %relay(`
2 | query TipsQuery {
3 | html_connection(where: { id: { _eq: 1 } }) {
4 | edges {
5 | node {
6 | data
7 | }
8 | }
9 | }
10 | }
11 | `)
12 |
13 | @react.component
14 | let make = () => {
15 | let {html_connection: {edges: htmlEdges}} = TipsQuery.use(~variables=())
16 | let data = htmlEdges[0]->Option.map(edge => edge.node.data)
17 | switch data {
18 | | Some(data) =>
19 |
23 | | None => React.null
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/TokenContext.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as React from "react";
4 |
5 | var context = React.createContext(undefined);
6 |
7 | var make = context.Provider;
8 |
9 | var Provider = {
10 | make: make
11 | };
12 |
13 | export {
14 | context ,
15 | Provider ,
16 | }
17 | /* context Not a pure module */
18 |
--------------------------------------------------------------------------------
/src/TokenContext.res:
--------------------------------------------------------------------------------
1 | open React
2 |
3 | let context = createContext((None: option))
4 |
5 | module Provider = {
6 | let make = Context.provider(context)
7 | }
8 |
--------------------------------------------------------------------------------
/src/Translation.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
4 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
5 | import * as JsxRuntime from "react/jsx-runtime";
6 | import * as RescriptRelay_Fragment from "rescript-relay/src/RescriptRelay_Fragment.js";
7 | import * as Translation_jargon_graphql from "./__generated__/Translation_jargon_graphql.js";
8 |
9 | var convertFragment = Translation_jargon_graphql.Internal.convertFragment;
10 |
11 | function waitForFragmentData(environment, fRef) {
12 | return RescriptRelay_Fragment.waitForFragmentData(environment, Translation_jargon_graphql.node, convertFragment, fRef);
13 | }
14 |
15 | function use(fRef) {
16 | return RescriptRelay_Fragment.useFragment(Translation_jargon_graphql.node, convertFragment, fRef);
17 | }
18 |
19 | function useOpt(fRef) {
20 | return RescriptRelay_Fragment.useFragmentOpt(fRef !== undefined ? Caml_option.some(Caml_option.valFromOption(fRef)) : undefined, Translation_jargon_graphql.node, convertFragment);
21 | }
22 |
23 | function readResolverFragment(fRef) {
24 | return RescriptRelay_Fragment.read(Translation_jargon_graphql.node, convertFragment, fRef);
25 | }
26 |
27 | var TranslationFragment = {
28 | Types: undefined,
29 | Operation: undefined,
30 | convertFragment: convertFragment,
31 | waitForFragmentData: waitForFragmentData,
32 | use: use,
33 | useOpt: useOpt,
34 | readResolverFragment: readResolverFragment
35 | };
36 |
37 | function Translation$TranslationRow(props) {
38 | var commentID = props.commentID;
39 | var goToComment = function (_event) {
40 | var element = document.getElementById(commentID);
41 | if (!(element == null)) {
42 | element.scrollIntoView({
43 | block: "center",
44 | behavior: "smooth"
45 | });
46 | return ;
47 | }
48 |
49 | };
50 | return JsxRuntime.jsx("tr", {
51 | children: JsxRuntime.jsx("td", {
52 | children: props.name,
53 | className: "font-normal text-[15px] hover:underline hover:cursor-pointer",
54 | onClick: goToComment
55 | })
56 | });
57 | }
58 |
59 | var TranslationRow = {
60 | make: Translation$TranslationRow
61 | };
62 |
63 | function Translation(props) {
64 | var match = use(props.translationRefs);
65 | var translations = match.translations;
66 | if (translations.length > 0) {
67 | return JsxRuntime.jsx("div", {
68 | children: JsxRuntime.jsx("table", {
69 | children: JsxRuntime.jsx("tbody", {
70 | children: translations.map(function (param) {
71 | return JsxRuntime.jsx(Translation$TranslationRow, {
72 | name: param.name,
73 | commentID: Core__Option.getOr(Core__Option.map(param.comment, (function (x) {
74 | return x.id;
75 | })), "")
76 | }, param.id);
77 | })
78 | }),
79 | className: "table w-full"
80 | }),
81 | className: "overflow-x-auto"
82 | });
83 | } else {
84 | return null;
85 | }
86 | }
87 |
88 | var make = Translation;
89 |
90 | export {
91 | TranslationFragment ,
92 | TranslationRow ,
93 | make ,
94 | }
95 | /* react/jsx-runtime Not a pure module */
96 |
--------------------------------------------------------------------------------
/src/Translation.res:
--------------------------------------------------------------------------------
1 | module TranslationFragment = %relay(`
2 | fragment Translation_jargon on jargon {
3 | translations(order_by: { name: asc }) {
4 | id
5 | name
6 | comment {
7 | id
8 | }
9 | }
10 | }
11 | `)
12 |
13 | module TranslationRow = {
14 | @react.component
15 | let make = (~name, ~commentID) => {
16 | let goToComment = _event => {
17 | open! Webapi.Dom // suppress warning for document
18 | switch document->Document.getElementById(commentID) {
19 | | Some(element) =>
20 | element->Element.scrollIntoViewWithOptions({
21 | "block": "center",
22 | "behavior": "smooth",
23 | })
24 | | None => ()
25 | }
26 | }
27 |
28 |
29 |
32 | {name->React.string}
33 | |
34 |
35 | }
36 | }
37 |
38 | @react.component
39 | let make = (~translationRefs) => {
40 | let {translations} = TranslationFragment.use(translationRefs)
41 |
42 | if translations->Array.length > 0 {
43 |
44 |
45 |
46 | {translations
47 | ->Array.map(({id, name, comment}) =>
48 | Option.map(x => x.id)->Option.getOr("")}
50 | />
51 | )
52 | ->React.array}
53 |
54 |
55 |
56 | } else {
57 | React.null
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Translator.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function Translator(props) {
6 | return JsxRuntime.jsx("iframe", {
7 | className: "h-screen w-full",
8 | allowFullScreen: true,
9 | src: "https://ghoh-eng2koreasyword.hf.space"
10 | });
11 | }
12 |
13 | var make = Translator;
14 |
15 | export {
16 | make ,
17 | }
18 | /* react/jsx-runtime Not a pure module */
19 |
--------------------------------------------------------------------------------
/src/Translator.res:
--------------------------------------------------------------------------------
1 | @react.component
2 | let make = () =>
3 |
6 |
--------------------------------------------------------------------------------
/src/Util.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as JsxRuntime from "react/jsx-runtime";
4 |
5 | function getCode(c) {
6 | return c.charCodeAt(0) | 0;
7 | }
8 |
9 | function endsWithJong(korean) {
10 | var c = korean.charAt(korean.length - 1 | 0);
11 | if ("가" <= c && c <= "힣") {
12 | return ((c.charCodeAt(0) | 0) - ("가".charCodeAt(0) | 0) | 0) % 28 > 0;
13 | } else {
14 | return false;
15 | }
16 | }
17 |
18 | function eulLeul(korean) {
19 | return korean + (
20 | endsWithJong(korean) ? "을" : "를"
21 | );
22 | }
23 |
24 | function sanitize(word) {
25 | return word.replace(/\s+/g, " ").trim();
26 | }
27 |
28 | function badgify(onClickOpt, text) {
29 | var onClick = onClickOpt !== undefined ? onClickOpt : (function (param) {
30 |
31 | });
32 | return JsxRuntime.jsx("button", {
33 | children: text,
34 | className: "badge badge-md font-semibold",
35 | onClick: onClick
36 | }, text);
37 | }
38 |
39 | var asHtmlDialogElement = (function(element) {
40 | if ((window.constructor.name !== undefined && /^HTMLDialogElement$/.test(element.constructor.name))
41 | || (/^\[object HTMLDialogElement\]$/.test(element.constructor.toString()))) {
42 | return element;
43 | }
44 | });
45 |
46 | export {
47 | getCode ,
48 | endsWithJong ,
49 | eulLeul ,
50 | sanitize ,
51 | badgify ,
52 | asHtmlDialogElement ,
53 | }
54 | /* react/jsx-runtime Not a pure module */
55 |
--------------------------------------------------------------------------------
/src/Util.res:
--------------------------------------------------------------------------------
1 | let getCode = c => c->String.charCodeAt(0)->Float.toInt
2 |
3 | let endsWithJong = korean => {
4 | let c = korean->String.charAt(korean->String.length - 1)
5 | if "가" <= c && c <= "힣" {
6 | mod(c->getCode - "가"->getCode, 28) > 0
7 | } else {
8 | false
9 | }
10 | }
11 |
12 | let eulLeul = korean => {
13 | korean ++ if korean->endsWithJong {
14 | "을"
15 | } else {
16 | "를"
17 | }
18 | }
19 |
20 | let sanitize = word => word->String.replaceRegExp(%re(`/\s+/g`), " ")->String.trim
21 |
22 | let badgify = (~onClick=_ => (), text) =>
23 |
26 |
27 | @val external htmlDialogElement: 'a = "HTMLDialogElement"
28 | let asHtmlDialogElement: Webapi.Dom.Element.t => option<'htmlDialogElement> = %raw(`
29 | function(element) {
30 | if ((window.constructor.name !== undefined && /^HTMLDialogElement$/.test(element.constructor.name))
31 | || (/^\[object HTMLDialogElement\]$/.test(element.constructor.toString()))) {
32 | return element;
33 | }
34 | }
35 | `)
36 |
--------------------------------------------------------------------------------
/src/Why.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 |
3 | import * as Core__Option from "@rescript/core/src/Core__Option.js";
4 | import * as WhyQuery_graphql from "./__generated__/WhyQuery_graphql.js";
5 | import * as JsxRuntime from "react/jsx-runtime";
6 | import * as RescriptRelay_Query from "rescript-relay/src/RescriptRelay_Query.js";
7 |
8 | var convertVariables = WhyQuery_graphql.Internal.convertVariables;
9 |
10 | var convertResponse = WhyQuery_graphql.Internal.convertResponse;
11 |
12 | var convertWrapRawResponse = WhyQuery_graphql.Internal.convertWrapRawResponse;
13 |
14 | var use = RescriptRelay_Query.useQuery(convertVariables, WhyQuery_graphql.node, convertResponse);
15 |
16 | var useLoader = RescriptRelay_Query.useLoader(convertVariables, WhyQuery_graphql.node, (function (prim) {
17 | return prim;
18 | }));
19 |
20 | var usePreloaded = RescriptRelay_Query.usePreloaded(WhyQuery_graphql.node, convertResponse, (function (prim) {
21 | return prim;
22 | }));
23 |
24 | var $$fetch = RescriptRelay_Query.$$fetch(WhyQuery_graphql.node, convertResponse, convertVariables);
25 |
26 | var fetchPromised = RescriptRelay_Query.fetchPromised(WhyQuery_graphql.node, convertResponse, convertVariables);
27 |
28 | var retain = RescriptRelay_Query.retain(WhyQuery_graphql.node, convertVariables);
29 |
30 | var WhyQuery = {
31 | Operation: undefined,
32 | Types: undefined,
33 | convertVariables: convertVariables,
34 | convertResponse: convertResponse,
35 | convertWrapRawResponse: convertWrapRawResponse,
36 | use: use,
37 | useLoader: useLoader,
38 | usePreloaded: usePreloaded,
39 | $$fetch: $$fetch,
40 | fetchPromised: fetchPromised,
41 | retain: retain
42 | };
43 |
44 | function Why(props) {
45 | var match = use(undefined, undefined, undefined, undefined);
46 | var data = Core__Option.map(match.html_connection.edges[0], (function (edge) {
47 | return edge.node.data;
48 | }));
49 | if (data !== undefined) {
50 | return JsxRuntime.jsxs("article", {
51 | children: [
52 | JsxRuntime.jsx("h1", {
53 | children: "쉬운 전문용어"
54 | }),
55 | JsxRuntime.jsx("div", {
56 | children: JsxRuntime.jsxs("a", {
57 | children: [
58 | JsxRuntime.jsx("span", {
59 | children: "한국정보과학회 쉬운전문용어 제정위원회"
60 | }),
61 | JsxRuntime.jsx("br", {}),
62 | JsxRuntime.jsx("span", {
63 | children: "서울대학교 컴퓨터공학부 이광근"
64 | })
65 | ],
66 | href: "http://kwangkeunyi.snu.ac.kr"
67 | }),
68 | className: "flex flex-col text-right text-sm"
69 | }),
70 | JsxRuntime.jsx("div", {
71 | className: "divider"
72 | }),
73 | JsxRuntime.jsx("div", {
74 | dangerouslySetInnerHTML: {
75 | __html: data
76 | }
77 | })
78 | ],
79 | className: "px-6 py-12 max-w-xl mx-auto md:max-w-4xl prose"
80 | });
81 | } else {
82 | return null;
83 | }
84 | }
85 |
86 | var make = Why;
87 |
88 | export {
89 | WhyQuery ,
90 | make ,
91 | }
92 | /* use Not a pure module */
93 |
--------------------------------------------------------------------------------
/src/Why.res:
--------------------------------------------------------------------------------
1 | module WhyQuery = %relay(`
2 | query WhyQuery {
3 | html_connection(where: { id: { _eq: 2 } }) {
4 | edges {
5 | node {
6 | data
7 | }
8 | }
9 | }
10 | }
11 | `)
12 |
13 | @react.component
14 | let make = () => {
15 | let {html_connection: {edges: htmlEdges}} = WhyQuery.use(~variables=())
16 | let data = htmlEdges[0]->Option.map(edge => edge.node.data)
17 | switch data {
18 | | Some(data) =>
19 |
20 | {"쉬운 전문용어"->React.string}
21 |
28 |
29 |
30 |
31 | | None => React.null
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Window.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/Window.res:
--------------------------------------------------------------------------------
1 | @scope("window") @val
2 | external alert: string => unit = "alert"
3 |
--------------------------------------------------------------------------------
/src/__generated__/CommentInputMutation_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var variablesConverter = {"__root":{"now":{"b":""},"jargonID":{"b":""}}};
9 |
10 | function convertVariables(v) {
11 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
12 | }
13 |
14 | var wrapResponseConverter = {};
15 |
16 | function convertWrapResponse(v) {
17 | return RescriptRelay.convertObj(v, wrapResponseConverter, undefined, null);
18 | }
19 |
20 | var responseConverter = {};
21 |
22 | function convertResponse(v) {
23 | return RescriptRelay.convertObj(v, responseConverter, undefined, undefined);
24 | }
25 |
26 | var Internal = {
27 | variablesConverter: variablesConverter,
28 | variablesConverterMap: undefined,
29 | convertVariables: convertVariables,
30 | wrapResponseConverter: wrapResponseConverter,
31 | wrapResponseConverterMap: undefined,
32 | convertWrapResponse: convertWrapResponse,
33 | responseConverter: responseConverter,
34 | responseConverterMap: undefined,
35 | convertResponse: convertResponse,
36 | convertWrapRawResponse: convertWrapResponse,
37 | convertRawResponse: convertResponse
38 | };
39 |
40 | var Utils = {};
41 |
42 | var node = ((function(){
43 | var v0 = [
44 | {
45 | "defaultValue": null,
46 | "kind": "LocalArgument",
47 | "name": "authorID"
48 | },
49 | {
50 | "defaultValue": null,
51 | "kind": "LocalArgument",
52 | "name": "content"
53 | },
54 | {
55 | "defaultValue": null,
56 | "kind": "LocalArgument",
57 | "name": "jargonID"
58 | },
59 | {
60 | "defaultValue": null,
61 | "kind": "LocalArgument",
62 | "name": "now"
63 | }
64 | ],
65 | v1 = [
66 | {
67 | "alias": null,
68 | "args": null,
69 | "kind": "ScalarField",
70 | "name": "id",
71 | "storageKey": null
72 | }
73 | ],
74 | v2 = [
75 | {
76 | "alias": null,
77 | "args": [
78 | {
79 | "fields": [
80 | {
81 | "kind": "Variable",
82 | "name": "author_id",
83 | "variableName": "authorID"
84 | },
85 | {
86 | "kind": "Variable",
87 | "name": "content",
88 | "variableName": "content"
89 | },
90 | {
91 | "kind": "Variable",
92 | "name": "jargon_id",
93 | "variableName": "jargonID"
94 | }
95 | ],
96 | "kind": "ObjectValue",
97 | "name": "object"
98 | }
99 | ],
100 | "concreteType": "comment",
101 | "kind": "LinkedField",
102 | "name": "insert_comment_one",
103 | "plural": false,
104 | "selections": (v1/*: any*/),
105 | "storageKey": null
106 | },
107 | {
108 | "alias": null,
109 | "args": [
110 | {
111 | "fields": [
112 | {
113 | "kind": "Variable",
114 | "name": "updated_at",
115 | "variableName": "now"
116 | }
117 | ],
118 | "kind": "ObjectValue",
119 | "name": "_set"
120 | },
121 | {
122 | "fields": [
123 | {
124 | "kind": "Variable",
125 | "name": "id",
126 | "variableName": "jargonID"
127 | }
128 | ],
129 | "kind": "ObjectValue",
130 | "name": "pk_columns"
131 | }
132 | ],
133 | "concreteType": "jargon",
134 | "kind": "LinkedField",
135 | "name": "update_jargon_by_pk",
136 | "plural": false,
137 | "selections": (v1/*: any*/),
138 | "storageKey": null
139 | }
140 | ];
141 | return {
142 | "fragment": {
143 | "argumentDefinitions": (v0/*: any*/),
144 | "kind": "Fragment",
145 | "metadata": null,
146 | "name": "CommentInputMutation",
147 | "selections": (v2/*: any*/),
148 | "type": "mutation_root",
149 | "abstractKey": null
150 | },
151 | "kind": "Request",
152 | "operation": {
153 | "argumentDefinitions": (v0/*: any*/),
154 | "kind": "Operation",
155 | "name": "CommentInputMutation",
156 | "selections": (v2/*: any*/)
157 | },
158 | "params": {
159 | "cacheID": "080acbaf1c5ee27be818a444615fdbca",
160 | "id": null,
161 | "metadata": {},
162 | "name": "CommentInputMutation",
163 | "operationKind": "mutation",
164 | "text": "mutation CommentInputMutation(\n $authorID: String!\n $content: String!\n $jargonID: uuid!\n $now: timestamptz!\n) {\n insert_comment_one(object: {author_id: $authorID, content: $content, jargon_id: $jargonID}) {\n id\n }\n update_jargon_by_pk(pk_columns: {id: $jargonID}, _set: {updated_at: $now}) {\n id\n }\n}\n"
165 | }
166 | };
167 | })());
168 |
169 | export {
170 | Types ,
171 | Internal ,
172 | Utils ,
173 | node ,
174 | }
175 | /* node Not a pure module */
176 |
--------------------------------------------------------------------------------
/src/__generated__/CommentInputMutation_graphql.res:
--------------------------------------------------------------------------------
1 | /* @sourceLoc CommentInput.res */
2 | /* @generated */
3 | %%raw("/* @generated */")
4 | module Types = {
5 | @@warning("-30")
6 |
7 | @live
8 | type rec response_insert_comment_one = {
9 | @live id: string,
10 | }
11 | @live
12 | and response_update_jargon_by_pk = {
13 | @live id: string,
14 | }
15 | @live
16 | type response = {
17 | insert_comment_one: option,
18 | update_jargon_by_pk: option,
19 | }
20 | @live
21 | type rawResponse = response
22 | @live
23 | type variables = {
24 | authorID: string,
25 | content: string,
26 | jargonID: string,
27 | now: string,
28 | }
29 | }
30 |
31 | module Internal = {
32 | @live
33 | let variablesConverter: Js.Dict.t>> = %raw(
34 | json`{"__root":{"now":{"b":""},"jargonID":{"b":""}}}`
35 | )
36 | @live
37 | let variablesConverterMap = ()
38 | @live
39 | let convertVariables = v => v->RescriptRelay.convertObj(
40 | variablesConverter,
41 | variablesConverterMap,
42 | Js.undefined
43 | )
44 | @live
45 | type wrapResponseRaw
46 | @live
47 | let wrapResponseConverter: Js.Dict.t>> = %raw(
48 | json`{}`
49 | )
50 | @live
51 | let wrapResponseConverterMap = ()
52 | @live
53 | let convertWrapResponse = v => v->RescriptRelay.convertObj(
54 | wrapResponseConverter,
55 | wrapResponseConverterMap,
56 | Js.null
57 | )
58 | @live
59 | type responseRaw
60 | @live
61 | let responseConverter: Js.Dict.t>> = %raw(
62 | json`{}`
63 | )
64 | @live
65 | let responseConverterMap = ()
66 | @live
67 | let convertResponse = v => v->RescriptRelay.convertObj(
68 | responseConverter,
69 | responseConverterMap,
70 | Js.undefined
71 | )
72 | type wrapRawResponseRaw = wrapResponseRaw
73 | @live
74 | let convertWrapRawResponse = convertWrapResponse
75 | type rawResponseRaw = responseRaw
76 | @live
77 | let convertRawResponse = convertResponse
78 | }
79 | module Utils = {
80 | @@warning("-33")
81 | open Types
82 | }
83 |
84 | type relayOperationNode
85 | type operationType = RescriptRelay.mutationNode
86 |
87 |
88 | let node: operationType = %raw(json` (function(){
89 | var v0 = [
90 | {
91 | "defaultValue": null,
92 | "kind": "LocalArgument",
93 | "name": "authorID"
94 | },
95 | {
96 | "defaultValue": null,
97 | "kind": "LocalArgument",
98 | "name": "content"
99 | },
100 | {
101 | "defaultValue": null,
102 | "kind": "LocalArgument",
103 | "name": "jargonID"
104 | },
105 | {
106 | "defaultValue": null,
107 | "kind": "LocalArgument",
108 | "name": "now"
109 | }
110 | ],
111 | v1 = [
112 | {
113 | "alias": null,
114 | "args": null,
115 | "kind": "ScalarField",
116 | "name": "id",
117 | "storageKey": null
118 | }
119 | ],
120 | v2 = [
121 | {
122 | "alias": null,
123 | "args": [
124 | {
125 | "fields": [
126 | {
127 | "kind": "Variable",
128 | "name": "author_id",
129 | "variableName": "authorID"
130 | },
131 | {
132 | "kind": "Variable",
133 | "name": "content",
134 | "variableName": "content"
135 | },
136 | {
137 | "kind": "Variable",
138 | "name": "jargon_id",
139 | "variableName": "jargonID"
140 | }
141 | ],
142 | "kind": "ObjectValue",
143 | "name": "object"
144 | }
145 | ],
146 | "concreteType": "comment",
147 | "kind": "LinkedField",
148 | "name": "insert_comment_one",
149 | "plural": false,
150 | "selections": (v1/*: any*/),
151 | "storageKey": null
152 | },
153 | {
154 | "alias": null,
155 | "args": [
156 | {
157 | "fields": [
158 | {
159 | "kind": "Variable",
160 | "name": "updated_at",
161 | "variableName": "now"
162 | }
163 | ],
164 | "kind": "ObjectValue",
165 | "name": "_set"
166 | },
167 | {
168 | "fields": [
169 | {
170 | "kind": "Variable",
171 | "name": "id",
172 | "variableName": "jargonID"
173 | }
174 | ],
175 | "kind": "ObjectValue",
176 | "name": "pk_columns"
177 | }
178 | ],
179 | "concreteType": "jargon",
180 | "kind": "LinkedField",
181 | "name": "update_jargon_by_pk",
182 | "plural": false,
183 | "selections": (v1/*: any*/),
184 | "storageKey": null
185 | }
186 | ];
187 | return {
188 | "fragment": {
189 | "argumentDefinitions": (v0/*: any*/),
190 | "kind": "Fragment",
191 | "metadata": null,
192 | "name": "CommentInputMutation",
193 | "selections": (v2/*: any*/),
194 | "type": "mutation_root",
195 | "abstractKey": null
196 | },
197 | "kind": "Request",
198 | "operation": {
199 | "argumentDefinitions": (v0/*: any*/),
200 | "kind": "Operation",
201 | "name": "CommentInputMutation",
202 | "selections": (v2/*: any*/)
203 | },
204 | "params": {
205 | "cacheID": "080acbaf1c5ee27be818a444615fdbca",
206 | "id": null,
207 | "metadata": {},
208 | "name": "CommentInputMutation",
209 | "operationKind": "mutation",
210 | "text": "mutation CommentInputMutation(\n $authorID: String!\n $content: String!\n $jargonID: uuid!\n $now: timestamptz!\n) {\n insert_comment_one(object: {author_id: $authorID, content: $content, jargon_id: $jargonID}) {\n id\n }\n update_jargon_by_pk(pk_columns: {id: $jargonID}, _set: {updated_at: $now}) {\n id\n }\n}\n"
211 | }
212 | };
213 | })() `)
214 |
215 |
216 |
--------------------------------------------------------------------------------
/src/__generated__/CommentRowMutation_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var variablesConverter = {"__root":{"parentID":{"b":""},"now":{"b":""},"jargonID":{"b":""}}};
9 |
10 | function convertVariables(v) {
11 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
12 | }
13 |
14 | var wrapResponseConverter = {};
15 |
16 | function convertWrapResponse(v) {
17 | return RescriptRelay.convertObj(v, wrapResponseConverter, undefined, null);
18 | }
19 |
20 | var responseConverter = {};
21 |
22 | function convertResponse(v) {
23 | return RescriptRelay.convertObj(v, responseConverter, undefined, undefined);
24 | }
25 |
26 | var Internal = {
27 | variablesConverter: variablesConverter,
28 | variablesConverterMap: undefined,
29 | convertVariables: convertVariables,
30 | wrapResponseConverter: wrapResponseConverter,
31 | wrapResponseConverterMap: undefined,
32 | convertWrapResponse: convertWrapResponse,
33 | responseConverter: responseConverter,
34 | responseConverterMap: undefined,
35 | convertResponse: convertResponse,
36 | convertWrapRawResponse: convertWrapResponse,
37 | convertRawResponse: convertResponse
38 | };
39 |
40 | var Utils = {};
41 |
42 | var node = ((function(){
43 | var v0 = {
44 | "defaultValue": null,
45 | "kind": "LocalArgument",
46 | "name": "authorID"
47 | },
48 | v1 = {
49 | "defaultValue": null,
50 | "kind": "LocalArgument",
51 | "name": "content"
52 | },
53 | v2 = {
54 | "defaultValue": null,
55 | "kind": "LocalArgument",
56 | "name": "jargonID"
57 | },
58 | v3 = {
59 | "defaultValue": null,
60 | "kind": "LocalArgument",
61 | "name": "now"
62 | },
63 | v4 = {
64 | "defaultValue": null,
65 | "kind": "LocalArgument",
66 | "name": "parentID"
67 | },
68 | v5 = [
69 | {
70 | "alias": null,
71 | "args": null,
72 | "kind": "ScalarField",
73 | "name": "id",
74 | "storageKey": null
75 | }
76 | ],
77 | v6 = [
78 | {
79 | "alias": null,
80 | "args": [
81 | {
82 | "fields": [
83 | {
84 | "kind": "Variable",
85 | "name": "author_id",
86 | "variableName": "authorID"
87 | },
88 | {
89 | "kind": "Variable",
90 | "name": "content",
91 | "variableName": "content"
92 | },
93 | {
94 | "kind": "Variable",
95 | "name": "jargon_id",
96 | "variableName": "jargonID"
97 | },
98 | {
99 | "kind": "Variable",
100 | "name": "parent_id",
101 | "variableName": "parentID"
102 | }
103 | ],
104 | "kind": "ObjectValue",
105 | "name": "object"
106 | }
107 | ],
108 | "concreteType": "comment",
109 | "kind": "LinkedField",
110 | "name": "insert_comment_one",
111 | "plural": false,
112 | "selections": (v5/*: any*/),
113 | "storageKey": null
114 | },
115 | {
116 | "alias": null,
117 | "args": [
118 | {
119 | "fields": [
120 | {
121 | "kind": "Variable",
122 | "name": "updated_at",
123 | "variableName": "now"
124 | }
125 | ],
126 | "kind": "ObjectValue",
127 | "name": "_set"
128 | },
129 | {
130 | "fields": [
131 | {
132 | "kind": "Variable",
133 | "name": "id",
134 | "variableName": "jargonID"
135 | }
136 | ],
137 | "kind": "ObjectValue",
138 | "name": "pk_columns"
139 | }
140 | ],
141 | "concreteType": "jargon",
142 | "kind": "LinkedField",
143 | "name": "update_jargon_by_pk",
144 | "plural": false,
145 | "selections": (v5/*: any*/),
146 | "storageKey": null
147 | }
148 | ];
149 | return {
150 | "fragment": {
151 | "argumentDefinitions": [
152 | (v0/*: any*/),
153 | (v1/*: any*/),
154 | (v2/*: any*/),
155 | (v3/*: any*/),
156 | (v4/*: any*/)
157 | ],
158 | "kind": "Fragment",
159 | "metadata": null,
160 | "name": "CommentRowMutation",
161 | "selections": (v6/*: any*/),
162 | "type": "mutation_root",
163 | "abstractKey": null
164 | },
165 | "kind": "Request",
166 | "operation": {
167 | "argumentDefinitions": [
168 | (v0/*: any*/),
169 | (v1/*: any*/),
170 | (v2/*: any*/),
171 | (v4/*: any*/),
172 | (v3/*: any*/)
173 | ],
174 | "kind": "Operation",
175 | "name": "CommentRowMutation",
176 | "selections": (v6/*: any*/)
177 | },
178 | "params": {
179 | "cacheID": "80aa57994b6dbbafbc93308d75b9f2ee",
180 | "id": null,
181 | "metadata": {},
182 | "name": "CommentRowMutation",
183 | "operationKind": "mutation",
184 | "text": "mutation CommentRowMutation(\n $authorID: String!\n $content: String!\n $jargonID: uuid!\n $parentID: uuid!\n $now: timestamptz!\n) {\n insert_comment_one(object: {author_id: $authorID, content: $content, jargon_id: $jargonID, parent_id: $parentID}) {\n id\n }\n update_jargon_by_pk(pk_columns: {id: $jargonID}, _set: {updated_at: $now}) {\n id\n }\n}\n"
185 | }
186 | };
187 | })());
188 |
189 | export {
190 | Types ,
191 | Internal ,
192 | Utils ,
193 | node ,
194 | }
195 | /* node Not a pure module */
196 |
--------------------------------------------------------------------------------
/src/__generated__/CommentRowMutation_graphql.res:
--------------------------------------------------------------------------------
1 | /* @sourceLoc CommentRow.res */
2 | /* @generated */
3 | %%raw("/* @generated */")
4 | module Types = {
5 | @@warning("-30")
6 |
7 | @live
8 | type rec response_insert_comment_one = {
9 | @live id: string,
10 | }
11 | @live
12 | and response_update_jargon_by_pk = {
13 | @live id: string,
14 | }
15 | @live
16 | type response = {
17 | insert_comment_one: option,
18 | update_jargon_by_pk: option,
19 | }
20 | @live
21 | type rawResponse = response
22 | @live
23 | type variables = {
24 | authorID: string,
25 | content: string,
26 | jargonID: string,
27 | now: string,
28 | parentID: string,
29 | }
30 | }
31 |
32 | module Internal = {
33 | @live
34 | let variablesConverter: Js.Dict.t>> = %raw(
35 | json`{"__root":{"parentID":{"b":""},"now":{"b":""},"jargonID":{"b":""}}}`
36 | )
37 | @live
38 | let variablesConverterMap = ()
39 | @live
40 | let convertVariables = v => v->RescriptRelay.convertObj(
41 | variablesConverter,
42 | variablesConverterMap,
43 | Js.undefined
44 | )
45 | @live
46 | type wrapResponseRaw
47 | @live
48 | let wrapResponseConverter: Js.Dict.t>> = %raw(
49 | json`{}`
50 | )
51 | @live
52 | let wrapResponseConverterMap = ()
53 | @live
54 | let convertWrapResponse = v => v->RescriptRelay.convertObj(
55 | wrapResponseConverter,
56 | wrapResponseConverterMap,
57 | Js.null
58 | )
59 | @live
60 | type responseRaw
61 | @live
62 | let responseConverter: Js.Dict.t>> = %raw(
63 | json`{}`
64 | )
65 | @live
66 | let responseConverterMap = ()
67 | @live
68 | let convertResponse = v => v->RescriptRelay.convertObj(
69 | responseConverter,
70 | responseConverterMap,
71 | Js.undefined
72 | )
73 | type wrapRawResponseRaw = wrapResponseRaw
74 | @live
75 | let convertWrapRawResponse = convertWrapResponse
76 | type rawResponseRaw = responseRaw
77 | @live
78 | let convertRawResponse = convertResponse
79 | }
80 | module Utils = {
81 | @@warning("-33")
82 | open Types
83 | }
84 |
85 | type relayOperationNode
86 | type operationType = RescriptRelay.mutationNode
87 |
88 |
89 | let node: operationType = %raw(json` (function(){
90 | var v0 = {
91 | "defaultValue": null,
92 | "kind": "LocalArgument",
93 | "name": "authorID"
94 | },
95 | v1 = {
96 | "defaultValue": null,
97 | "kind": "LocalArgument",
98 | "name": "content"
99 | },
100 | v2 = {
101 | "defaultValue": null,
102 | "kind": "LocalArgument",
103 | "name": "jargonID"
104 | },
105 | v3 = {
106 | "defaultValue": null,
107 | "kind": "LocalArgument",
108 | "name": "now"
109 | },
110 | v4 = {
111 | "defaultValue": null,
112 | "kind": "LocalArgument",
113 | "name": "parentID"
114 | },
115 | v5 = [
116 | {
117 | "alias": null,
118 | "args": null,
119 | "kind": "ScalarField",
120 | "name": "id",
121 | "storageKey": null
122 | }
123 | ],
124 | v6 = [
125 | {
126 | "alias": null,
127 | "args": [
128 | {
129 | "fields": [
130 | {
131 | "kind": "Variable",
132 | "name": "author_id",
133 | "variableName": "authorID"
134 | },
135 | {
136 | "kind": "Variable",
137 | "name": "content",
138 | "variableName": "content"
139 | },
140 | {
141 | "kind": "Variable",
142 | "name": "jargon_id",
143 | "variableName": "jargonID"
144 | },
145 | {
146 | "kind": "Variable",
147 | "name": "parent_id",
148 | "variableName": "parentID"
149 | }
150 | ],
151 | "kind": "ObjectValue",
152 | "name": "object"
153 | }
154 | ],
155 | "concreteType": "comment",
156 | "kind": "LinkedField",
157 | "name": "insert_comment_one",
158 | "plural": false,
159 | "selections": (v5/*: any*/),
160 | "storageKey": null
161 | },
162 | {
163 | "alias": null,
164 | "args": [
165 | {
166 | "fields": [
167 | {
168 | "kind": "Variable",
169 | "name": "updated_at",
170 | "variableName": "now"
171 | }
172 | ],
173 | "kind": "ObjectValue",
174 | "name": "_set"
175 | },
176 | {
177 | "fields": [
178 | {
179 | "kind": "Variable",
180 | "name": "id",
181 | "variableName": "jargonID"
182 | }
183 | ],
184 | "kind": "ObjectValue",
185 | "name": "pk_columns"
186 | }
187 | ],
188 | "concreteType": "jargon",
189 | "kind": "LinkedField",
190 | "name": "update_jargon_by_pk",
191 | "plural": false,
192 | "selections": (v5/*: any*/),
193 | "storageKey": null
194 | }
195 | ];
196 | return {
197 | "fragment": {
198 | "argumentDefinitions": [
199 | (v0/*: any*/),
200 | (v1/*: any*/),
201 | (v2/*: any*/),
202 | (v3/*: any*/),
203 | (v4/*: any*/)
204 | ],
205 | "kind": "Fragment",
206 | "metadata": null,
207 | "name": "CommentRowMutation",
208 | "selections": (v6/*: any*/),
209 | "type": "mutation_root",
210 | "abstractKey": null
211 | },
212 | "kind": "Request",
213 | "operation": {
214 | "argumentDefinitions": [
215 | (v0/*: any*/),
216 | (v1/*: any*/),
217 | (v2/*: any*/),
218 | (v4/*: any*/),
219 | (v3/*: any*/)
220 | ],
221 | "kind": "Operation",
222 | "name": "CommentRowMutation",
223 | "selections": (v6/*: any*/)
224 | },
225 | "params": {
226 | "cacheID": "80aa57994b6dbbafbc93308d75b9f2ee",
227 | "id": null,
228 | "metadata": {},
229 | "name": "CommentRowMutation",
230 | "operationKind": "mutation",
231 | "text": "mutation CommentRowMutation(\n $authorID: String!\n $content: String!\n $jargonID: uuid!\n $parentID: uuid!\n $now: timestamptz!\n) {\n insert_comment_one(object: {author_id: $authorID, content: $content, jargon_id: $jargonID, parent_id: $parentID}) {\n id\n }\n update_jargon_by_pk(pk_columns: {id: $jargonID}, _set: {updated_at: $now}) {\n id\n }\n}\n"
232 | }
233 | };
234 | })() `)
235 |
236 |
237 |
--------------------------------------------------------------------------------
/src/__generated__/CommentSection_jargon_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var fragmentConverter = {"__root":{"comments_connection_edges_node_created_at":{"b":""}}};
9 |
10 | function convertFragment(v) {
11 | return RescriptRelay.convertObj(v, fragmentConverter, undefined, undefined);
12 | }
13 |
14 | var Internal = {
15 | fragmentConverter: fragmentConverter,
16 | fragmentConverterMap: undefined,
17 | convertFragment: convertFragment
18 | };
19 |
20 | var Utils = {};
21 |
22 | var node = ((function(){
23 | var v0 = {
24 | "alias": null,
25 | "args": null,
26 | "kind": "ScalarField",
27 | "name": "id",
28 | "storageKey": null
29 | };
30 | return {
31 | "argumentDefinitions": [],
32 | "kind": "Fragment",
33 | "metadata": null,
34 | "name": "CommentSection_jargon",
35 | "selections": [
36 | {
37 | "alias": null,
38 | "args": null,
39 | "concreteType": "commentConnection",
40 | "kind": "LinkedField",
41 | "name": "comments_connection",
42 | "plural": false,
43 | "selections": [
44 | {
45 | "alias": null,
46 | "args": null,
47 | "concreteType": "commentEdge",
48 | "kind": "LinkedField",
49 | "name": "edges",
50 | "plural": true,
51 | "selections": [
52 | {
53 | "alias": null,
54 | "args": null,
55 | "concreteType": "comment",
56 | "kind": "LinkedField",
57 | "name": "node",
58 | "plural": false,
59 | "selections": [
60 | (v0/*: any*/),
61 | {
62 | "alias": null,
63 | "args": null,
64 | "kind": "ScalarField",
65 | "name": "content",
66 | "storageKey": null
67 | },
68 | {
69 | "alias": null,
70 | "args": null,
71 | "kind": "ScalarField",
72 | "name": "created_at",
73 | "storageKey": null
74 | },
75 | {
76 | "alias": null,
77 | "args": null,
78 | "concreteType": "comment",
79 | "kind": "LinkedField",
80 | "name": "parent",
81 | "plural": false,
82 | "selections": [
83 | (v0/*: any*/)
84 | ],
85 | "storageKey": null
86 | },
87 | {
88 | "alias": null,
89 | "args": null,
90 | "concreteType": "user",
91 | "kind": "LinkedField",
92 | "name": "author",
93 | "plural": false,
94 | "selections": [
95 | {
96 | "alias": null,
97 | "args": null,
98 | "kind": "ScalarField",
99 | "name": "photo_url",
100 | "storageKey": null
101 | },
102 | {
103 | "alias": null,
104 | "args": null,
105 | "kind": "ScalarField",
106 | "name": "display_name",
107 | "storageKey": null
108 | }
109 | ],
110 | "storageKey": null
111 | },
112 | {
113 | "alias": null,
114 | "args": null,
115 | "concreteType": "translation",
116 | "kind": "LinkedField",
117 | "name": "translation",
118 | "plural": false,
119 | "selections": [
120 | (v0/*: any*/),
121 | {
122 | "alias": null,
123 | "args": null,
124 | "kind": "ScalarField",
125 | "name": "name",
126 | "storageKey": null
127 | }
128 | ],
129 | "storageKey": null
130 | }
131 | ],
132 | "storageKey": null
133 | }
134 | ],
135 | "storageKey": null
136 | }
137 | ],
138 | "storageKey": null
139 | },
140 | {
141 | "kind": "ClientExtension",
142 | "selections": [
143 | {
144 | "alias": null,
145 | "args": null,
146 | "kind": "ScalarField",
147 | "name": "__id",
148 | "storageKey": null
149 | }
150 | ]
151 | }
152 | ],
153 | "type": "jargon",
154 | "abstractKey": null
155 | };
156 | })());
157 |
158 | export {
159 | Types ,
160 | Internal ,
161 | Utils ,
162 | node ,
163 | }
164 | /* node Not a pure module */
165 |
--------------------------------------------------------------------------------
/src/__generated__/EditCategoriesCategoryQuery_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
5 | import * as ReactRelay from "react-relay";
6 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
7 |
8 | function makeRefetchVariables() {
9 |
10 | }
11 |
12 | var Types = {
13 | makeRefetchVariables: makeRefetchVariables
14 | };
15 |
16 | var variablesConverter = {};
17 |
18 | function convertVariables(v) {
19 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
20 | }
21 |
22 | var wrapResponseConverter = {};
23 |
24 | function convertWrapResponse(v) {
25 | return RescriptRelay.convertObj(v, wrapResponseConverter, undefined, null);
26 | }
27 |
28 | var responseConverter = {};
29 |
30 | function convertResponse(v) {
31 | return RescriptRelay.convertObj(v, responseConverter, undefined, undefined);
32 | }
33 |
34 | var Internal = {
35 | variablesConverter: variablesConverter,
36 | variablesConverterMap: undefined,
37 | convertVariables: convertVariables,
38 | wrapResponseConverter: wrapResponseConverter,
39 | wrapResponseConverterMap: undefined,
40 | convertWrapResponse: convertWrapResponse,
41 | responseConverter: responseConverter,
42 | responseConverterMap: undefined,
43 | convertResponse: convertResponse,
44 | convertWrapRawResponse: convertWrapResponse,
45 | convertRawResponse: convertResponse
46 | };
47 |
48 | var Utils = {};
49 |
50 | var node = ((function(){
51 | var v0 = [
52 | {
53 | "alias": null,
54 | "args": [
55 | {
56 | "kind": "Literal",
57 | "name": "order_by",
58 | "value": {
59 | "name": "asc"
60 | }
61 | }
62 | ],
63 | "concreteType": "categoryConnection",
64 | "kind": "LinkedField",
65 | "name": "category_connection",
66 | "plural": false,
67 | "selections": [
68 | {
69 | "alias": null,
70 | "args": null,
71 | "concreteType": "categoryEdge",
72 | "kind": "LinkedField",
73 | "name": "edges",
74 | "plural": true,
75 | "selections": [
76 | {
77 | "alias": null,
78 | "args": null,
79 | "concreteType": "category",
80 | "kind": "LinkedField",
81 | "name": "node",
82 | "plural": false,
83 | "selections": [
84 | {
85 | "alias": null,
86 | "args": null,
87 | "kind": "ScalarField",
88 | "name": "id",
89 | "storageKey": null
90 | },
91 | {
92 | "alias": null,
93 | "args": null,
94 | "kind": "ScalarField",
95 | "name": "name",
96 | "storageKey": null
97 | },
98 | {
99 | "alias": null,
100 | "args": null,
101 | "kind": "ScalarField",
102 | "name": "acronym",
103 | "storageKey": null
104 | }
105 | ],
106 | "storageKey": null
107 | }
108 | ],
109 | "storageKey": null
110 | }
111 | ],
112 | "storageKey": "category_connection(order_by:{\"name\":\"asc\"})"
113 | }
114 | ];
115 | return {
116 | "fragment": {
117 | "argumentDefinitions": [],
118 | "kind": "Fragment",
119 | "metadata": null,
120 | "name": "EditCategoriesCategoryQuery",
121 | "selections": (v0/*: any*/),
122 | "type": "query_root",
123 | "abstractKey": null
124 | },
125 | "kind": "Request",
126 | "operation": {
127 | "argumentDefinitions": [],
128 | "kind": "Operation",
129 | "name": "EditCategoriesCategoryQuery",
130 | "selections": (v0/*: any*/)
131 | },
132 | "params": {
133 | "cacheID": "4b825ab8a1e9b5122adeb6921f3fe882",
134 | "id": null,
135 | "metadata": {},
136 | "name": "EditCategoriesCategoryQuery",
137 | "operationKind": "query",
138 | "text": "query EditCategoriesCategoryQuery {\n category_connection(order_by: {name: asc}) {\n edges {\n node {\n id\n name\n acronym\n }\n }\n }\n}\n"
139 | }
140 | };
141 | })());
142 |
143 | function load(environment, variables, fetchPolicy, fetchKey, networkCacheConfig) {
144 | return ReactRelay.loadQuery(environment, node, convertVariables(variables), {
145 | fetchKey: fetchKey,
146 | fetchPolicy: fetchPolicy,
147 | networkCacheConfig: networkCacheConfig
148 | });
149 | }
150 |
151 | function queryRefToObservable(token) {
152 | return Caml_option.nullable_to_opt(token.source);
153 | }
154 |
155 | function queryRefToPromise(token) {
156 | return new Promise((function (resolve, param) {
157 | var o = queryRefToObservable(token);
158 | if (o !== undefined) {
159 | Caml_option.valFromOption(o).subscribe({
160 | complete: (function () {
161 | resolve({
162 | TAG: "Ok",
163 | _0: undefined
164 | });
165 | })
166 | });
167 | return ;
168 | } else {
169 | return resolve({
170 | TAG: "Error",
171 | _0: undefined
172 | });
173 | }
174 | }));
175 | }
176 |
177 | export {
178 | Types ,
179 | Internal ,
180 | Utils ,
181 | node ,
182 | load ,
183 | queryRefToObservable ,
184 | queryRefToPromise ,
185 | }
186 | /* node Not a pure module */
187 |
--------------------------------------------------------------------------------
/src/__generated__/HomeCategoryQuery_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
5 | import * as ReactRelay from "react-relay";
6 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
7 |
8 | function makeRefetchVariables() {
9 |
10 | }
11 |
12 | var Types = {
13 | makeRefetchVariables: makeRefetchVariables
14 | };
15 |
16 | var variablesConverter = {};
17 |
18 | function convertVariables(v) {
19 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
20 | }
21 |
22 | var wrapResponseConverter = {};
23 |
24 | function convertWrapResponse(v) {
25 | return RescriptRelay.convertObj(v, wrapResponseConverter, undefined, null);
26 | }
27 |
28 | var responseConverter = {};
29 |
30 | function convertResponse(v) {
31 | return RescriptRelay.convertObj(v, responseConverter, undefined, undefined);
32 | }
33 |
34 | var Internal = {
35 | variablesConverter: variablesConverter,
36 | variablesConverterMap: undefined,
37 | convertVariables: convertVariables,
38 | wrapResponseConverter: wrapResponseConverter,
39 | wrapResponseConverterMap: undefined,
40 | convertWrapResponse: convertWrapResponse,
41 | responseConverter: responseConverter,
42 | responseConverterMap: undefined,
43 | convertResponse: convertResponse,
44 | convertWrapRawResponse: convertWrapResponse,
45 | convertRawResponse: convertResponse
46 | };
47 |
48 | var Utils = {};
49 |
50 | var node = ((function(){
51 | var v0 = [
52 | {
53 | "alias": null,
54 | "args": [
55 | {
56 | "kind": "Literal",
57 | "name": "order_by",
58 | "value": {
59 | "name": "asc"
60 | }
61 | }
62 | ],
63 | "concreteType": "categoryConnection",
64 | "kind": "LinkedField",
65 | "name": "category_connection",
66 | "plural": false,
67 | "selections": [
68 | {
69 | "alias": null,
70 | "args": null,
71 | "concreteType": "categoryEdge",
72 | "kind": "LinkedField",
73 | "name": "edges",
74 | "plural": true,
75 | "selections": [
76 | {
77 | "alias": null,
78 | "args": null,
79 | "concreteType": "category",
80 | "kind": "LinkedField",
81 | "name": "node",
82 | "plural": false,
83 | "selections": [
84 | {
85 | "alias": null,
86 | "args": null,
87 | "kind": "ScalarField",
88 | "name": "id",
89 | "storageKey": null
90 | },
91 | {
92 | "alias": null,
93 | "args": null,
94 | "kind": "ScalarField",
95 | "name": "name",
96 | "storageKey": null
97 | },
98 | {
99 | "alias": null,
100 | "args": null,
101 | "kind": "ScalarField",
102 | "name": "acronym",
103 | "storageKey": null
104 | }
105 | ],
106 | "storageKey": null
107 | }
108 | ],
109 | "storageKey": null
110 | }
111 | ],
112 | "storageKey": "category_connection(order_by:{\"name\":\"asc\"})"
113 | }
114 | ];
115 | return {
116 | "fragment": {
117 | "argumentDefinitions": [],
118 | "kind": "Fragment",
119 | "metadata": null,
120 | "name": "HomeCategoryQuery",
121 | "selections": (v0/*: any*/),
122 | "type": "query_root",
123 | "abstractKey": null
124 | },
125 | "kind": "Request",
126 | "operation": {
127 | "argumentDefinitions": [],
128 | "kind": "Operation",
129 | "name": "HomeCategoryQuery",
130 | "selections": (v0/*: any*/)
131 | },
132 | "params": {
133 | "cacheID": "f95eabc635d3820fab69514a45e72e73",
134 | "id": null,
135 | "metadata": {},
136 | "name": "HomeCategoryQuery",
137 | "operationKind": "query",
138 | "text": "query HomeCategoryQuery {\n category_connection(order_by: {name: asc}) {\n edges {\n node {\n id\n name\n acronym\n }\n }\n }\n}\n"
139 | }
140 | };
141 | })());
142 |
143 | function load(environment, variables, fetchPolicy, fetchKey, networkCacheConfig) {
144 | return ReactRelay.loadQuery(environment, node, convertVariables(variables), {
145 | fetchKey: fetchKey,
146 | fetchPolicy: fetchPolicy,
147 | networkCacheConfig: networkCacheConfig
148 | });
149 | }
150 |
151 | function queryRefToObservable(token) {
152 | return Caml_option.nullable_to_opt(token.source);
153 | }
154 |
155 | function queryRefToPromise(token) {
156 | return new Promise((function (resolve, param) {
157 | var o = queryRefToObservable(token);
158 | if (o !== undefined) {
159 | Caml_option.valFromOption(o).subscribe({
160 | complete: (function () {
161 | resolve({
162 | TAG: "Ok",
163 | _0: undefined
164 | });
165 | })
166 | });
167 | return ;
168 | } else {
169 | return resolve({
170 | TAG: "Error",
171 | _0: undefined
172 | });
173 | }
174 | }));
175 | }
176 |
177 | export {
178 | Types ,
179 | Internal ,
180 | Utils ,
181 | node ,
182 | load ,
183 | queryRefToObservable ,
184 | queryRefToPromise ,
185 | }
186 | /* node Not a pure module */
187 |
--------------------------------------------------------------------------------
/src/__generated__/JargonCard_jargon_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var fragmentConverter = {"__root":{"updated_at":{"b":""}}};
9 |
10 | function convertFragment(v) {
11 | return RescriptRelay.convertObj(v, fragmentConverter, undefined, undefined);
12 | }
13 |
14 | var Internal = {
15 | fragmentConverter: fragmentConverter,
16 | fragmentConverterMap: undefined,
17 | convertFragment: convertFragment
18 | };
19 |
20 | var Utils = {};
21 |
22 | var node = ((function(){
23 | var v0 = {
24 | "alias": null,
25 | "args": null,
26 | "kind": "ScalarField",
27 | "name": "id",
28 | "storageKey": null
29 | },
30 | v1 = {
31 | "alias": null,
32 | "args": null,
33 | "kind": "ScalarField",
34 | "name": "name",
35 | "storageKey": null
36 | },
37 | v2 = {
38 | "name": "asc"
39 | };
40 | return {
41 | "argumentDefinitions": [],
42 | "kind": "Fragment",
43 | "metadata": null,
44 | "name": "JargonCard_jargon",
45 | "selections": [
46 | (v0/*: any*/),
47 | (v1/*: any*/),
48 | {
49 | "alias": null,
50 | "args": null,
51 | "kind": "ScalarField",
52 | "name": "updated_at",
53 | "storageKey": null
54 | },
55 | {
56 | "alias": null,
57 | "args": [
58 | {
59 | "kind": "Literal",
60 | "name": "order_by",
61 | "value": {
62 | "category": (v2/*: any*/)
63 | }
64 | }
65 | ],
66 | "concreteType": "jargon_category",
67 | "kind": "LinkedField",
68 | "name": "jargon_categories",
69 | "plural": true,
70 | "selections": [
71 | {
72 | "alias": null,
73 | "args": null,
74 | "concreteType": "category",
75 | "kind": "LinkedField",
76 | "name": "category",
77 | "plural": false,
78 | "selections": [
79 | {
80 | "alias": null,
81 | "args": null,
82 | "kind": "ScalarField",
83 | "name": "acronym",
84 | "storageKey": null
85 | }
86 | ],
87 | "storageKey": null
88 | }
89 | ],
90 | "storageKey": "jargon_categories(order_by:{\"category\":{\"name\":\"asc\"}})"
91 | },
92 | {
93 | "alias": null,
94 | "args": [
95 | {
96 | "kind": "Literal",
97 | "name": "limit",
98 | "value": 20
99 | },
100 | {
101 | "kind": "Literal",
102 | "name": "order_by",
103 | "value": (v2/*: any*/)
104 | }
105 | ],
106 | "concreteType": "translation",
107 | "kind": "LinkedField",
108 | "name": "translations",
109 | "plural": true,
110 | "selections": [
111 | (v0/*: any*/),
112 | (v1/*: any*/)
113 | ],
114 | "storageKey": "translations(limit:20,order_by:{\"name\":\"asc\"})"
115 | },
116 | {
117 | "alias": null,
118 | "args": null,
119 | "concreteType": "comment_aggregate",
120 | "kind": "LinkedField",
121 | "name": "comments_aggregate",
122 | "plural": false,
123 | "selections": [
124 | {
125 | "alias": null,
126 | "args": null,
127 | "concreteType": "comment_aggregate_fields",
128 | "kind": "LinkedField",
129 | "name": "aggregate",
130 | "plural": false,
131 | "selections": [
132 | {
133 | "alias": null,
134 | "args": null,
135 | "kind": "ScalarField",
136 | "name": "count",
137 | "storageKey": null
138 | }
139 | ],
140 | "storageKey": null
141 | }
142 | ],
143 | "storageKey": null
144 | }
145 | ],
146 | "type": "jargon",
147 | "abstractKey": null
148 | };
149 | })());
150 |
151 | export {
152 | Types ,
153 | Internal ,
154 | Utils ,
155 | node ,
156 | }
157 | /* node Not a pure module */
158 |
--------------------------------------------------------------------------------
/src/__generated__/JargonCard_jargon_graphql.res:
--------------------------------------------------------------------------------
1 | /* @sourceLoc JargonCard.res */
2 | /* @generated */
3 | %%raw("/* @generated */")
4 | module Types = {
5 | @@warning("-30")
6 |
7 | type rec fragment_comments_aggregate_aggregate = {
8 | count: int,
9 | }
10 | and fragment_comments_aggregate = {
11 | aggregate: option,
12 | }
13 | and fragment_jargon_categories_category = {
14 | acronym: string,
15 | }
16 | and fragment_jargon_categories = {
17 | category: fragment_jargon_categories_category,
18 | }
19 | and fragment_translations = {
20 | @live id: string,
21 | name: string,
22 | }
23 | type fragment = {
24 | comments_aggregate: fragment_comments_aggregate,
25 | @live id: string,
26 | jargon_categories: array,
27 | name: string,
28 | translations: array,
29 | updated_at: string,
30 | }
31 | }
32 |
33 | module Internal = {
34 | @live
35 | type fragmentRaw
36 | @live
37 | let fragmentConverter: Js.Dict.t>> = %raw(
38 | json`{"__root":{"updated_at":{"b":""}}}`
39 | )
40 | @live
41 | let fragmentConverterMap = ()
42 | @live
43 | let convertFragment = v => v->RescriptRelay.convertObj(
44 | fragmentConverter,
45 | fragmentConverterMap,
46 | Js.undefined
47 | )
48 | }
49 |
50 | type t
51 | type fragmentRef
52 | external getFragmentRef:
53 | RescriptRelay.fragmentRefs<[> | #JargonCard_jargon]> => fragmentRef = "%identity"
54 |
55 | module Utils = {
56 | @@warning("-33")
57 | open Types
58 | }
59 |
60 | type relayOperationNode
61 | type operationType = RescriptRelay.fragmentNode
62 |
63 |
64 | let node: operationType = %raw(json` (function(){
65 | var v0 = {
66 | "alias": null,
67 | "args": null,
68 | "kind": "ScalarField",
69 | "name": "id",
70 | "storageKey": null
71 | },
72 | v1 = {
73 | "alias": null,
74 | "args": null,
75 | "kind": "ScalarField",
76 | "name": "name",
77 | "storageKey": null
78 | },
79 | v2 = {
80 | "name": "asc"
81 | };
82 | return {
83 | "argumentDefinitions": [],
84 | "kind": "Fragment",
85 | "metadata": null,
86 | "name": "JargonCard_jargon",
87 | "selections": [
88 | (v0/*: any*/),
89 | (v1/*: any*/),
90 | {
91 | "alias": null,
92 | "args": null,
93 | "kind": "ScalarField",
94 | "name": "updated_at",
95 | "storageKey": null
96 | },
97 | {
98 | "alias": null,
99 | "args": [
100 | {
101 | "kind": "Literal",
102 | "name": "order_by",
103 | "value": {
104 | "category": (v2/*: any*/)
105 | }
106 | }
107 | ],
108 | "concreteType": "jargon_category",
109 | "kind": "LinkedField",
110 | "name": "jargon_categories",
111 | "plural": true,
112 | "selections": [
113 | {
114 | "alias": null,
115 | "args": null,
116 | "concreteType": "category",
117 | "kind": "LinkedField",
118 | "name": "category",
119 | "plural": false,
120 | "selections": [
121 | {
122 | "alias": null,
123 | "args": null,
124 | "kind": "ScalarField",
125 | "name": "acronym",
126 | "storageKey": null
127 | }
128 | ],
129 | "storageKey": null
130 | }
131 | ],
132 | "storageKey": "jargon_categories(order_by:{\"category\":{\"name\":\"asc\"}})"
133 | },
134 | {
135 | "alias": null,
136 | "args": [
137 | {
138 | "kind": "Literal",
139 | "name": "limit",
140 | "value": 20
141 | },
142 | {
143 | "kind": "Literal",
144 | "name": "order_by",
145 | "value": (v2/*: any*/)
146 | }
147 | ],
148 | "concreteType": "translation",
149 | "kind": "LinkedField",
150 | "name": "translations",
151 | "plural": true,
152 | "selections": [
153 | (v0/*: any*/),
154 | (v1/*: any*/)
155 | ],
156 | "storageKey": "translations(limit:20,order_by:{\"name\":\"asc\"})"
157 | },
158 | {
159 | "alias": null,
160 | "args": null,
161 | "concreteType": "comment_aggregate",
162 | "kind": "LinkedField",
163 | "name": "comments_aggregate",
164 | "plural": false,
165 | "selections": [
166 | {
167 | "alias": null,
168 | "args": null,
169 | "concreteType": "comment_aggregate_fields",
170 | "kind": "LinkedField",
171 | "name": "aggregate",
172 | "plural": false,
173 | "selections": [
174 | {
175 | "alias": null,
176 | "args": null,
177 | "kind": "ScalarField",
178 | "name": "count",
179 | "storageKey": null
180 | }
181 | ],
182 | "storageKey": null
183 | }
184 | ],
185 | "storageKey": null
186 | }
187 | ],
188 | "type": "jargon",
189 | "abstractKey": null
190 | };
191 | })() `)
192 |
193 |
--------------------------------------------------------------------------------
/src/__generated__/NewJargonCategoryQuery_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
5 | import * as ReactRelay from "react-relay";
6 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
7 |
8 | function makeRefetchVariables() {
9 |
10 | }
11 |
12 | var Types = {
13 | makeRefetchVariables: makeRefetchVariables
14 | };
15 |
16 | var variablesConverter = {};
17 |
18 | function convertVariables(v) {
19 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
20 | }
21 |
22 | var wrapResponseConverter = {};
23 |
24 | function convertWrapResponse(v) {
25 | return RescriptRelay.convertObj(v, wrapResponseConverter, undefined, null);
26 | }
27 |
28 | var responseConverter = {};
29 |
30 | function convertResponse(v) {
31 | return RescriptRelay.convertObj(v, responseConverter, undefined, undefined);
32 | }
33 |
34 | var Internal = {
35 | variablesConverter: variablesConverter,
36 | variablesConverterMap: undefined,
37 | convertVariables: convertVariables,
38 | wrapResponseConverter: wrapResponseConverter,
39 | wrapResponseConverterMap: undefined,
40 | convertWrapResponse: convertWrapResponse,
41 | responseConverter: responseConverter,
42 | responseConverterMap: undefined,
43 | convertResponse: convertResponse,
44 | convertWrapRawResponse: convertWrapResponse,
45 | convertRawResponse: convertResponse
46 | };
47 |
48 | var Utils = {};
49 |
50 | var node = ((function(){
51 | var v0 = [
52 | {
53 | "alias": null,
54 | "args": [
55 | {
56 | "kind": "Literal",
57 | "name": "order_by",
58 | "value": {
59 | "name": "asc"
60 | }
61 | }
62 | ],
63 | "concreteType": "categoryConnection",
64 | "kind": "LinkedField",
65 | "name": "category_connection",
66 | "plural": false,
67 | "selections": [
68 | {
69 | "alias": null,
70 | "args": null,
71 | "concreteType": "categoryEdge",
72 | "kind": "LinkedField",
73 | "name": "edges",
74 | "plural": true,
75 | "selections": [
76 | {
77 | "alias": null,
78 | "args": null,
79 | "concreteType": "category",
80 | "kind": "LinkedField",
81 | "name": "node",
82 | "plural": false,
83 | "selections": [
84 | {
85 | "alias": null,
86 | "args": null,
87 | "kind": "ScalarField",
88 | "name": "id",
89 | "storageKey": null
90 | },
91 | {
92 | "alias": null,
93 | "args": null,
94 | "kind": "ScalarField",
95 | "name": "name",
96 | "storageKey": null
97 | },
98 | {
99 | "alias": null,
100 | "args": null,
101 | "kind": "ScalarField",
102 | "name": "acronym",
103 | "storageKey": null
104 | }
105 | ],
106 | "storageKey": null
107 | }
108 | ],
109 | "storageKey": null
110 | }
111 | ],
112 | "storageKey": "category_connection(order_by:{\"name\":\"asc\"})"
113 | }
114 | ];
115 | return {
116 | "fragment": {
117 | "argumentDefinitions": [],
118 | "kind": "Fragment",
119 | "metadata": null,
120 | "name": "NewJargonCategoryQuery",
121 | "selections": (v0/*: any*/),
122 | "type": "query_root",
123 | "abstractKey": null
124 | },
125 | "kind": "Request",
126 | "operation": {
127 | "argumentDefinitions": [],
128 | "kind": "Operation",
129 | "name": "NewJargonCategoryQuery",
130 | "selections": (v0/*: any*/)
131 | },
132 | "params": {
133 | "cacheID": "3559bb0ff3d005da909e52b30368336e",
134 | "id": null,
135 | "metadata": {},
136 | "name": "NewJargonCategoryQuery",
137 | "operationKind": "query",
138 | "text": "query NewJargonCategoryQuery {\n category_connection(order_by: {name: asc}) {\n edges {\n node {\n id\n name\n acronym\n }\n }\n }\n}\n"
139 | }
140 | };
141 | })());
142 |
143 | function load(environment, variables, fetchPolicy, fetchKey, networkCacheConfig) {
144 | return ReactRelay.loadQuery(environment, node, convertVariables(variables), {
145 | fetchKey: fetchKey,
146 | fetchPolicy: fetchPolicy,
147 | networkCacheConfig: networkCacheConfig
148 | });
149 | }
150 |
151 | function queryRefToObservable(token) {
152 | return Caml_option.nullable_to_opt(token.source);
153 | }
154 |
155 | function queryRefToPromise(token) {
156 | return new Promise((function (resolve, param) {
157 | var o = queryRefToObservable(token);
158 | if (o !== undefined) {
159 | Caml_option.valFromOption(o).subscribe({
160 | complete: (function () {
161 | resolve({
162 | TAG: "Ok",
163 | _0: undefined
164 | });
165 | })
166 | });
167 | return ;
168 | } else {
169 | return resolve({
170 | TAG: "Error",
171 | _0: undefined
172 | });
173 | }
174 | }));
175 | }
176 |
177 | export {
178 | Types ,
179 | Internal ,
180 | Utils ,
181 | node ,
182 | load ,
183 | queryRefToObservable ,
184 | queryRefToPromise ,
185 | }
186 | /* node Not a pure module */
187 |
--------------------------------------------------------------------------------
/src/__generated__/NewTranslationJargonQuery_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as Caml_option from "rescript/lib/es6/caml_option.js";
5 | import * as ReactRelay from "react-relay";
6 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
7 | import * as RescriptRelay_Internal from "rescript-relay/src/RescriptRelay_Internal.js";
8 |
9 | function makeRefetchVariables(id) {
10 | return {
11 | id: id
12 | };
13 | }
14 |
15 | var Types = {
16 | makeRefetchVariables: makeRefetchVariables
17 | };
18 |
19 | function unwrap_response_node(__x) {
20 | return RescriptRelay_Internal.unwrapUnion(__x, ["jargon"]);
21 | }
22 |
23 | var variablesConverter = {};
24 |
25 | function convertVariables(v) {
26 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
27 | }
28 |
29 | var wrapResponseConverter = {"__root":{"node":{"u":"response_node"}}};
30 |
31 | var wrapResponseConverterMap = {
32 | response_node: RescriptRelay_Internal.wrapUnion
33 | };
34 |
35 | function convertWrapResponse(v) {
36 | return RescriptRelay.convertObj(v, wrapResponseConverter, wrapResponseConverterMap, null);
37 | }
38 |
39 | var responseConverter = {"__root":{"node":{"u":"response_node"}}};
40 |
41 | var responseConverterMap = {
42 | response_node: unwrap_response_node
43 | };
44 |
45 | function convertResponse(v) {
46 | return RescriptRelay.convertObj(v, responseConverter, responseConverterMap, undefined);
47 | }
48 |
49 | var Internal = {
50 | variablesConverter: variablesConverter,
51 | variablesConverterMap: undefined,
52 | convertVariables: convertVariables,
53 | wrapResponseConverter: wrapResponseConverter,
54 | wrapResponseConverterMap: wrapResponseConverterMap,
55 | convertWrapResponse: convertWrapResponse,
56 | responseConverter: responseConverter,
57 | responseConverterMap: responseConverterMap,
58 | convertResponse: convertResponse,
59 | convertWrapRawResponse: convertWrapResponse,
60 | convertRawResponse: convertResponse
61 | };
62 |
63 | var Utils = {};
64 |
65 | var node = ((function(){
66 | var v0 = [
67 | {
68 | "defaultValue": null,
69 | "kind": "LocalArgument",
70 | "name": "id"
71 | }
72 | ],
73 | v1 = [
74 | {
75 | "kind": "Variable",
76 | "name": "id",
77 | "variableName": "id"
78 | }
79 | ],
80 | v2 = {
81 | "alias": null,
82 | "args": null,
83 | "kind": "ScalarField",
84 | "name": "__typename",
85 | "storageKey": null
86 | },
87 | v3 = {
88 | "kind": "InlineFragment",
89 | "selections": [
90 | {
91 | "alias": null,
92 | "args": null,
93 | "kind": "ScalarField",
94 | "name": "name",
95 | "storageKey": null
96 | }
97 | ],
98 | "type": "jargon",
99 | "abstractKey": null
100 | };
101 | return {
102 | "fragment": {
103 | "argumentDefinitions": (v0/*: any*/),
104 | "kind": "Fragment",
105 | "metadata": null,
106 | "name": "NewTranslationJargonQuery",
107 | "selections": [
108 | {
109 | "alias": null,
110 | "args": (v1/*: any*/),
111 | "concreteType": null,
112 | "kind": "LinkedField",
113 | "name": "node",
114 | "plural": false,
115 | "selections": [
116 | (v2/*: any*/),
117 | (v3/*: any*/)
118 | ],
119 | "storageKey": null
120 | }
121 | ],
122 | "type": "query_root",
123 | "abstractKey": null
124 | },
125 | "kind": "Request",
126 | "operation": {
127 | "argumentDefinitions": (v0/*: any*/),
128 | "kind": "Operation",
129 | "name": "NewTranslationJargonQuery",
130 | "selections": [
131 | {
132 | "alias": null,
133 | "args": (v1/*: any*/),
134 | "concreteType": null,
135 | "kind": "LinkedField",
136 | "name": "node",
137 | "plural": false,
138 | "selections": [
139 | (v2/*: any*/),
140 | (v3/*: any*/),
141 | {
142 | "alias": null,
143 | "args": null,
144 | "kind": "ScalarField",
145 | "name": "id",
146 | "storageKey": null
147 | }
148 | ],
149 | "storageKey": null
150 | }
151 | ]
152 | },
153 | "params": {
154 | "cacheID": "9115e3f77d6f4e4cba47d643e0a7087c",
155 | "id": null,
156 | "metadata": {},
157 | "name": "NewTranslationJargonQuery",
158 | "operationKind": "query",
159 | "text": "query NewTranslationJargonQuery(\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ... on jargon {\n name\n }\n id\n }\n}\n"
160 | }
161 | };
162 | })());
163 |
164 | function load(environment, variables, fetchPolicy, fetchKey, networkCacheConfig) {
165 | return ReactRelay.loadQuery(environment, node, convertVariables(variables), {
166 | fetchKey: fetchKey,
167 | fetchPolicy: fetchPolicy,
168 | networkCacheConfig: networkCacheConfig
169 | });
170 | }
171 |
172 | function queryRefToObservable(token) {
173 | return Caml_option.nullable_to_opt(token.source);
174 | }
175 |
176 | function queryRefToPromise(token) {
177 | return new Promise((function (resolve, param) {
178 | var o = queryRefToObservable(token);
179 | if (o !== undefined) {
180 | Caml_option.valFromOption(o).subscribe({
181 | complete: (function () {
182 | resolve({
183 | TAG: "Ok",
184 | _0: undefined
185 | });
186 | })
187 | });
188 | return ;
189 | } else {
190 | return resolve({
191 | TAG: "Error",
192 | _0: undefined
193 | });
194 | }
195 | }));
196 | }
197 |
198 | var wrap_response_node = RescriptRelay_Internal.wrapUnion;
199 |
200 | export {
201 | Types ,
202 | unwrap_response_node ,
203 | wrap_response_node ,
204 | Internal ,
205 | Utils ,
206 | node ,
207 | load ,
208 | queryRefToObservable ,
209 | queryRefToPromise ,
210 | }
211 | /* node Not a pure module */
212 |
--------------------------------------------------------------------------------
/src/__generated__/ProfileDisplayNameMutation_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var variablesConverter = {};
9 |
10 | function convertVariables(v) {
11 | return RescriptRelay.convertObj(v, variablesConverter, undefined, undefined);
12 | }
13 |
14 | var wrapResponseConverter = {};
15 |
16 | function convertWrapResponse(v) {
17 | return RescriptRelay.convertObj(v, wrapResponseConverter, undefined, null);
18 | }
19 |
20 | var responseConverter = {};
21 |
22 | function convertResponse(v) {
23 | return RescriptRelay.convertObj(v, responseConverter, undefined, undefined);
24 | }
25 |
26 | var Internal = {
27 | variablesConverter: variablesConverter,
28 | variablesConverterMap: undefined,
29 | convertVariables: convertVariables,
30 | wrapResponseConverter: wrapResponseConverter,
31 | wrapResponseConverterMap: undefined,
32 | convertWrapResponse: convertWrapResponse,
33 | responseConverter: responseConverter,
34 | responseConverterMap: undefined,
35 | convertResponse: convertResponse,
36 | convertWrapRawResponse: convertWrapResponse,
37 | convertRawResponse: convertResponse
38 | };
39 |
40 | var Utils = {};
41 |
42 | var node = ((function(){
43 | var v0 = {
44 | "defaultValue": null,
45 | "kind": "LocalArgument",
46 | "name": "displayName"
47 | },
48 | v1 = {
49 | "defaultValue": null,
50 | "kind": "LocalArgument",
51 | "name": "uid"
52 | },
53 | v2 = [
54 | {
55 | "alias": null,
56 | "args": [
57 | {
58 | "fields": [
59 | {
60 | "kind": "Variable",
61 | "name": "display_name",
62 | "variableName": "displayName"
63 | }
64 | ],
65 | "kind": "ObjectValue",
66 | "name": "_set"
67 | },
68 | {
69 | "fields": [
70 | {
71 | "kind": "Variable",
72 | "name": "id",
73 | "variableName": "uid"
74 | }
75 | ],
76 | "kind": "ObjectValue",
77 | "name": "pk_columns"
78 | }
79 | ],
80 | "concreteType": "user",
81 | "kind": "LinkedField",
82 | "name": "update_user_by_pk",
83 | "plural": false,
84 | "selections": [
85 | {
86 | "alias": null,
87 | "args": null,
88 | "kind": "ScalarField",
89 | "name": "id",
90 | "storageKey": null
91 | }
92 | ],
93 | "storageKey": null
94 | }
95 | ];
96 | return {
97 | "fragment": {
98 | "argumentDefinitions": [
99 | (v0/*: any*/),
100 | (v1/*: any*/)
101 | ],
102 | "kind": "Fragment",
103 | "metadata": null,
104 | "name": "ProfileDisplayNameMutation",
105 | "selections": (v2/*: any*/),
106 | "type": "mutation_root",
107 | "abstractKey": null
108 | },
109 | "kind": "Request",
110 | "operation": {
111 | "argumentDefinitions": [
112 | (v1/*: any*/),
113 | (v0/*: any*/)
114 | ],
115 | "kind": "Operation",
116 | "name": "ProfileDisplayNameMutation",
117 | "selections": (v2/*: any*/)
118 | },
119 | "params": {
120 | "cacheID": "0853760246db799c0714f59a3721d163",
121 | "id": null,
122 | "metadata": {},
123 | "name": "ProfileDisplayNameMutation",
124 | "operationKind": "mutation",
125 | "text": "mutation ProfileDisplayNameMutation(\n $uid: String!\n $displayName: String!\n) {\n update_user_by_pk(pk_columns: {id: $uid}, _set: {display_name: $displayName}) {\n id\n }\n}\n"
126 | }
127 | };
128 | })());
129 |
130 | export {
131 | Types ,
132 | Internal ,
133 | Utils ,
134 | node ,
135 | }
136 | /* node Not a pure module */
137 |
--------------------------------------------------------------------------------
/src/__generated__/ProfileDisplayNameMutation_graphql.res:
--------------------------------------------------------------------------------
1 | /* @sourceLoc Profile.res */
2 | /* @generated */
3 | %%raw("/* @generated */")
4 | module Types = {
5 | @@warning("-30")
6 |
7 | @live
8 | type rec response_update_user_by_pk = {
9 | @live id: string,
10 | }
11 | @live
12 | type response = {
13 | update_user_by_pk: option,
14 | }
15 | @live
16 | type rawResponse = response
17 | @live
18 | type variables = {
19 | displayName: string,
20 | uid: string,
21 | }
22 | }
23 |
24 | module Internal = {
25 | @live
26 | let variablesConverter: Js.Dict.t>> = %raw(
27 | json`{}`
28 | )
29 | @live
30 | let variablesConverterMap = ()
31 | @live
32 | let convertVariables = v => v->RescriptRelay.convertObj(
33 | variablesConverter,
34 | variablesConverterMap,
35 | Js.undefined
36 | )
37 | @live
38 | type wrapResponseRaw
39 | @live
40 | let wrapResponseConverter: Js.Dict.t>> = %raw(
41 | json`{}`
42 | )
43 | @live
44 | let wrapResponseConverterMap = ()
45 | @live
46 | let convertWrapResponse = v => v->RescriptRelay.convertObj(
47 | wrapResponseConverter,
48 | wrapResponseConverterMap,
49 | Js.null
50 | )
51 | @live
52 | type responseRaw
53 | @live
54 | let responseConverter: Js.Dict.t>> = %raw(
55 | json`{}`
56 | )
57 | @live
58 | let responseConverterMap = ()
59 | @live
60 | let convertResponse = v => v->RescriptRelay.convertObj(
61 | responseConverter,
62 | responseConverterMap,
63 | Js.undefined
64 | )
65 | type wrapRawResponseRaw = wrapResponseRaw
66 | @live
67 | let convertWrapRawResponse = convertWrapResponse
68 | type rawResponseRaw = responseRaw
69 | @live
70 | let convertRawResponse = convertResponse
71 | }
72 | module Utils = {
73 | @@warning("-33")
74 | open Types
75 | }
76 |
77 | type relayOperationNode
78 | type operationType = RescriptRelay.mutationNode
79 |
80 |
81 | let node: operationType = %raw(json` (function(){
82 | var v0 = {
83 | "defaultValue": null,
84 | "kind": "LocalArgument",
85 | "name": "displayName"
86 | },
87 | v1 = {
88 | "defaultValue": null,
89 | "kind": "LocalArgument",
90 | "name": "uid"
91 | },
92 | v2 = [
93 | {
94 | "alias": null,
95 | "args": [
96 | {
97 | "fields": [
98 | {
99 | "kind": "Variable",
100 | "name": "display_name",
101 | "variableName": "displayName"
102 | }
103 | ],
104 | "kind": "ObjectValue",
105 | "name": "_set"
106 | },
107 | {
108 | "fields": [
109 | {
110 | "kind": "Variable",
111 | "name": "id",
112 | "variableName": "uid"
113 | }
114 | ],
115 | "kind": "ObjectValue",
116 | "name": "pk_columns"
117 | }
118 | ],
119 | "concreteType": "user",
120 | "kind": "LinkedField",
121 | "name": "update_user_by_pk",
122 | "plural": false,
123 | "selections": [
124 | {
125 | "alias": null,
126 | "args": null,
127 | "kind": "ScalarField",
128 | "name": "id",
129 | "storageKey": null
130 | }
131 | ],
132 | "storageKey": null
133 | }
134 | ];
135 | return {
136 | "fragment": {
137 | "argumentDefinitions": [
138 | (v0/*: any*/),
139 | (v1/*: any*/)
140 | ],
141 | "kind": "Fragment",
142 | "metadata": null,
143 | "name": "ProfileDisplayNameMutation",
144 | "selections": (v2/*: any*/),
145 | "type": "mutation_root",
146 | "abstractKey": null
147 | },
148 | "kind": "Request",
149 | "operation": {
150 | "argumentDefinitions": [
151 | (v1/*: any*/),
152 | (v0/*: any*/)
153 | ],
154 | "kind": "Operation",
155 | "name": "ProfileDisplayNameMutation",
156 | "selections": (v2/*: any*/)
157 | },
158 | "params": {
159 | "cacheID": "0853760246db799c0714f59a3721d163",
160 | "id": null,
161 | "metadata": {},
162 | "name": "ProfileDisplayNameMutation",
163 | "operationKind": "mutation",
164 | "text": "mutation ProfileDisplayNameMutation(\n $uid: String!\n $displayName: String!\n) {\n update_user_by_pk(pk_columns: {id: $uid}, _set: {display_name: $displayName}) {\n id\n }\n}\n"
165 | }
166 | };
167 | })() `)
168 |
169 |
170 |
--------------------------------------------------------------------------------
/src/__generated__/RelatedJargons_jargon_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var fragmentConverter = {};
9 |
10 | function convertFragment(v) {
11 | return RescriptRelay.convertObj(v, fragmentConverter, undefined, undefined);
12 | }
13 |
14 | var Internal = {
15 | fragmentConverter: fragmentConverter,
16 | fragmentConverterMap: undefined,
17 | convertFragment: convertFragment
18 | };
19 |
20 | var Utils = {};
21 |
22 | var node = {
23 | "argumentDefinitions": [],
24 | "kind": "Fragment",
25 | "metadata": null,
26 | "name": "RelatedJargons_jargon",
27 | "selections": [
28 | {
29 | "alias": null,
30 | "args": null,
31 | "concreteType": "related_jargon",
32 | "kind": "LinkedField",
33 | "name": "related_jargons",
34 | "plural": true,
35 | "selections": [
36 | {
37 | "alias": null,
38 | "args": null,
39 | "concreteType": "jargon",
40 | "kind": "LinkedField",
41 | "name": "jargon",
42 | "plural": false,
43 | "selections": [
44 | {
45 | "alias": null,
46 | "args": null,
47 | "kind": "ScalarField",
48 | "name": "id",
49 | "storageKey": null
50 | },
51 | {
52 | "alias": null,
53 | "args": null,
54 | "kind": "ScalarField",
55 | "name": "name",
56 | "storageKey": null
57 | }
58 | ],
59 | "storageKey": null
60 | }
61 | ],
62 | "storageKey": null
63 | }
64 | ],
65 | "type": "jargon",
66 | "abstractKey": null
67 | };
68 |
69 | export {
70 | Types ,
71 | Internal ,
72 | Utils ,
73 | node ,
74 | }
75 | /* RescriptRelay Not a pure module */
76 |
--------------------------------------------------------------------------------
/src/__generated__/RelatedJargons_jargon_graphql.res:
--------------------------------------------------------------------------------
1 | /* @sourceLoc RelatedJargons.res */
2 | /* @generated */
3 | %%raw("/* @generated */")
4 | module Types = {
5 | @@warning("-30")
6 |
7 | type rec fragment_related_jargons_jargon = {
8 | @live id: string,
9 | name: string,
10 | }
11 | and fragment_related_jargons = {
12 | jargon: fragment_related_jargons_jargon,
13 | }
14 | type fragment = {
15 | related_jargons: array,
16 | }
17 | }
18 |
19 | module Internal = {
20 | @live
21 | type fragmentRaw
22 | @live
23 | let fragmentConverter: Js.Dict.t>> = %raw(
24 | json`{}`
25 | )
26 | @live
27 | let fragmentConverterMap = ()
28 | @live
29 | let convertFragment = v => v->RescriptRelay.convertObj(
30 | fragmentConverter,
31 | fragmentConverterMap,
32 | Js.undefined
33 | )
34 | }
35 |
36 | type t
37 | type fragmentRef
38 | external getFragmentRef:
39 | RescriptRelay.fragmentRefs<[> | #RelatedJargons_jargon]> => fragmentRef = "%identity"
40 |
41 | module Utils = {
42 | @@warning("-33")
43 | open Types
44 | }
45 |
46 | type relayOperationNode
47 | type operationType = RescriptRelay.fragmentNode
48 |
49 |
50 | let node: operationType = %raw(json` {
51 | "argumentDefinitions": [],
52 | "kind": "Fragment",
53 | "metadata": null,
54 | "name": "RelatedJargons_jargon",
55 | "selections": [
56 | {
57 | "alias": null,
58 | "args": null,
59 | "concreteType": "related_jargon",
60 | "kind": "LinkedField",
61 | "name": "related_jargons",
62 | "plural": true,
63 | "selections": [
64 | {
65 | "alias": null,
66 | "args": null,
67 | "concreteType": "jargon",
68 | "kind": "LinkedField",
69 | "name": "jargon",
70 | "plural": false,
71 | "selections": [
72 | {
73 | "alias": null,
74 | "args": null,
75 | "kind": "ScalarField",
76 | "name": "id",
77 | "storageKey": null
78 | },
79 | {
80 | "alias": null,
81 | "args": null,
82 | "kind": "ScalarField",
83 | "name": "name",
84 | "storageKey": null
85 | }
86 | ],
87 | "storageKey": null
88 | }
89 | ],
90 | "storageKey": null
91 | }
92 | ],
93 | "type": "jargon",
94 | "abstractKey": null
95 | } `)
96 |
97 |
--------------------------------------------------------------------------------
/src/__generated__/RelaySchemaAssets_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/__generated__/Translation_jargon_graphql.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* @generated */
3 |
4 | import * as RescriptRelay from "rescript-relay/src/RescriptRelay.js";
5 |
6 | var Types = {};
7 |
8 | var fragmentConverter = {};
9 |
10 | function convertFragment(v) {
11 | return RescriptRelay.convertObj(v, fragmentConverter, undefined, undefined);
12 | }
13 |
14 | var Internal = {
15 | fragmentConverter: fragmentConverter,
16 | fragmentConverterMap: undefined,
17 | convertFragment: convertFragment
18 | };
19 |
20 | var Utils = {};
21 |
22 | var node = ((function(){
23 | var v0 = {
24 | "alias": null,
25 | "args": null,
26 | "kind": "ScalarField",
27 | "name": "id",
28 | "storageKey": null
29 | };
30 | return {
31 | "argumentDefinitions": [],
32 | "kind": "Fragment",
33 | "metadata": null,
34 | "name": "Translation_jargon",
35 | "selections": [
36 | {
37 | "alias": null,
38 | "args": [
39 | {
40 | "kind": "Literal",
41 | "name": "order_by",
42 | "value": {
43 | "name": "asc"
44 | }
45 | }
46 | ],
47 | "concreteType": "translation",
48 | "kind": "LinkedField",
49 | "name": "translations",
50 | "plural": true,
51 | "selections": [
52 | (v0/*: any*/),
53 | {
54 | "alias": null,
55 | "args": null,
56 | "kind": "ScalarField",
57 | "name": "name",
58 | "storageKey": null
59 | },
60 | {
61 | "alias": null,
62 | "args": null,
63 | "concreteType": "comment",
64 | "kind": "LinkedField",
65 | "name": "comment",
66 | "plural": false,
67 | "selections": [
68 | (v0/*: any*/)
69 | ],
70 | "storageKey": null
71 | }
72 | ],
73 | "storageKey": "translations(order_by:{\"name\":\"asc\"})"
74 | }
75 | ],
76 | "type": "jargon",
77 | "abstractKey": null
78 | };
79 | })());
80 |
81 | export {
82 | Types ,
83 | Internal ,
84 | Utils ,
85 | node ,
86 | }
87 | /* node Not a pure module */
88 |
--------------------------------------------------------------------------------
/src/__generated__/Translation_jargon_graphql.res:
--------------------------------------------------------------------------------
1 | /* @sourceLoc Translation.res */
2 | /* @generated */
3 | %%raw("/* @generated */")
4 | module Types = {
5 | @@warning("-30")
6 |
7 | type rec fragment_translations_comment = {
8 | @live id: string,
9 | }
10 | and fragment_translations = {
11 | comment: option,
12 | @live id: string,
13 | name: string,
14 | }
15 | type fragment = {
16 | translations: array,
17 | }
18 | }
19 |
20 | module Internal = {
21 | @live
22 | type fragmentRaw
23 | @live
24 | let fragmentConverter: Js.Dict.t>> = %raw(
25 | json`{}`
26 | )
27 | @live
28 | let fragmentConverterMap = ()
29 | @live
30 | let convertFragment = v => v->RescriptRelay.convertObj(
31 | fragmentConverter,
32 | fragmentConverterMap,
33 | Js.undefined
34 | )
35 | }
36 |
37 | type t
38 | type fragmentRef
39 | external getFragmentRef:
40 | RescriptRelay.fragmentRefs<[> | #Translation_jargon]> => fragmentRef = "%identity"
41 |
42 | module Utils = {
43 | @@warning("-33")
44 | open Types
45 | }
46 |
47 | type relayOperationNode
48 | type operationType = RescriptRelay.fragmentNode
49 |
50 |
51 | let node: operationType = %raw(json` (function(){
52 | var v0 = {
53 | "alias": null,
54 | "args": null,
55 | "kind": "ScalarField",
56 | "name": "id",
57 | "storageKey": null
58 | };
59 | return {
60 | "argumentDefinitions": [],
61 | "kind": "Fragment",
62 | "metadata": null,
63 | "name": "Translation_jargon",
64 | "selections": [
65 | {
66 | "alias": null,
67 | "args": [
68 | {
69 | "kind": "Literal",
70 | "name": "order_by",
71 | "value": {
72 | "name": "asc"
73 | }
74 | }
75 | ],
76 | "concreteType": "translation",
77 | "kind": "LinkedField",
78 | "name": "translations",
79 | "plural": true,
80 | "selections": [
81 | (v0/*: any*/),
82 | {
83 | "alias": null,
84 | "args": null,
85 | "kind": "ScalarField",
86 | "name": "name",
87 | "storageKey": null
88 | },
89 | {
90 | "alias": null,
91 | "args": null,
92 | "concreteType": "comment",
93 | "kind": "LinkedField",
94 | "name": "comment",
95 | "plural": false,
96 | "selections": [
97 | (v0/*: any*/)
98 | ],
99 | "storageKey": null
100 | }
101 | ],
102 | "storageKey": "translations(order_by:{\"name\":\"asc\"})"
103 | }
104 | ],
105 | "type": "jargon",
106 | "abstractKey": null
107 | };
108 | })() `)
109 |
110 |
--------------------------------------------------------------------------------
/src/firebaseConfig.js:
--------------------------------------------------------------------------------
1 | // For Firebase JS SDK v7.20.0 and later, measurementId is optional
2 | export const firebaseConfig = {
3 | apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
4 | authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
5 | projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
6 | storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
7 | messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
8 | appId: import.meta.env.VITE_FIREBASE_APP_ID,
9 | measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID
10 | };
11 |
12 | export const APP_CHECK_TOKEN = import.meta.env.VITE_FIREBASE_APP_CHECK_TOKEN
13 |
--------------------------------------------------------------------------------
/src/main.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer base {
6 | html {
7 | -webkit-appearance: none;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/uuid.js:
--------------------------------------------------------------------------------
1 | // Generated by ReScript, PLEASE EDIT WITH CARE
2 | /* This output is empty. Its source's type definitions, externals and/or unused code got optimized away. */
3 |
--------------------------------------------------------------------------------
/src/uuid.res:
--------------------------------------------------------------------------------
1 | @module("uuid") external v4: unit => string = "v4"
2 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./index.html", "./src/**/*.{res,js,ts,jsx,tsx}"],
4 | theme: {
5 | extend: {},
6 | fontFamily: {
7 | sans: [
8 | "Inter",
9 | "Noto Sans KR",
10 | "SF Pro Text",
11 | "-apple-system",
12 | "BlinkMacSystemFont",
13 | "Helvetica Neue",
14 | "Arial",
15 | "sans-serif",
16 | ],
17 | mono: ["SFMono-Regular", "Menlo", "Segoe UI", "Courier", "monospace"],
18 | },
19 | },
20 | plugins: [
21 | require("@tailwindcss/forms"),
22 | require("@tailwindcss/typography"),
23 | require("daisyui"),
24 | ],
25 | daisyui: {
26 | themes: [
27 | "emerald",
28 | {
29 | myForest: {
30 | ...require("daisyui/src/theming/themes")["forest"],
31 | "--rounded-btn": "0.5rem",
32 | },
33 | },
34 | ],
35 | darkTheme: "myForest",
36 | },
37 | };
38 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vite";
2 | import legacy from "@vitejs/plugin-legacy";
3 | import react from "@vitejs/plugin-react-swc";
4 |
5 | export default defineConfig({
6 | build: {
7 | minify: "terser",
8 | cssMinify: "lightningcss",
9 | terserOptions: {
10 | compress: {
11 | passes: 5,
12 | },
13 | },
14 | },
15 | plugins: [
16 | react(),
17 | legacy({
18 | modernPolyfills: ["es.array.to-sorted"],
19 | }),
20 | ],
21 | });
22 |
--------------------------------------------------------------------------------