From 6dcf81b211340a44c818aeb0b96a13cc115855e7 Mon Sep 17 00:00:00 2001 From: vinicvaz Date: Mon, 19 Sep 2022 11:18:04 -0300 Subject: [PATCH] start creating grammarrelationship component using TS --- package.json | 3 +- src/App.css | 34 --- src/App.jsx | 206 ------------------ src/App.tsx | 12 + src/components/GrammarRelationship/index.tsx | 113 ++++++++++ .../grammar-relationship-interface.tsx | 15 ++ src/pages/Home/index.tsx | 50 +++++ src/services/api/baseApi/index.ts | 61 ++++++ vite.config.ts | 11 + yarn.lock | 66 +++++- 10 files changed, 329 insertions(+), 242 deletions(-) delete mode 100644 src/App.jsx create mode 100644 src/App.tsx create mode 100644 src/components/GrammarRelationship/index.tsx create mode 100644 src/interfaces/grammar-relationship-interface.tsx create mode 100644 src/pages/Home/index.tsx create mode 100644 src/services/api/baseApi/index.ts create mode 100644 vite.config.ts diff --git a/package.json b/package.json index 35b2e36..b1d14c4 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-leader-line": "^1.0.5", - "react-xarrows": "^2.0.2" + "react-xarrows": "^2.0.2", + "vite-tsconfig-paths": "^3.5.0" }, "devDependencies": { "@types/react": "^18.0.17", diff --git a/src/App.css b/src/App.css index 2c5e2ef..4014cd7 100644 --- a/src/App.css +++ b/src/App.css @@ -5,37 +5,3 @@ text-align: center; } -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} diff --git a/src/App.jsx b/src/App.jsx deleted file mode 100644 index 0106b4a..0000000 --- a/src/App.jsx +++ /dev/null @@ -1,206 +0,0 @@ -import { useState, useEffect } from 'react' -import './App.css' -import LeaderLine from "react-leader-line"; -import axios from 'axios'; - - -// const textData = { -// "0": { -// "text": "I", -// "pos": "pronoun", -// "relationships": [ -// { -// "id": "1", -// "type": "verb" -// } -// ] -// }, -// "1": { -// "text": "had", -// "pos": "verb", -// "relationships": [ -// { -// "id": "0", -// "type": "subject" -// }, -// { -// "id": "3", -// "type": "object" -// } -// ] -// }, -// "2": { -// "text": "an", -// "pos": "article", -// "relationships": [ -// { -// "id": "3", -// "type": "article" -// } -// ] -// }, -// "3": { -// "text": "apple", -// "pos": "noun", -// "relationships": [ -// { -// "id": "1", -// "type": "object" -// }, -// { -// "id": "2", -// "type": "article" -// } -// ] -// }, -// } - -const color_pallete = [ - "rgba(252, 186, 3, 0)", - "rgba(247, 16, 0, 0)", - "rgba(0, 247, 86, 0)", - "rgba(0, 202, 247, 0)", - "rgba(82, 0, 247, 0)", - "rgba(247, 0, 235, 0)", -] - -function App() { - const [message, setMessage] = useState(''); - const [tags, setTags] = useState([]); - const [dependencyParsed, setDependencyParsed] = useState({}); - - const handleInputTextChange = event => { - setMessage(event.target.value); - }; - - const changeBackgroundOver = event => { - const [r, g, b, a] = event.target.style.backgroundColor.split(','); - const newBackgroundColor = [r, g, b, 0.6].join(',') + ')'; - event.target.style.background = newBackgroundColor; - }; - - const changeBackgroundLeave = event => { - const [r, g, b, a] = event.target.style.backgroundColor.split(','); - const newBackgroundColor = [r, g, b, 0].join(',') + ')'; - event.target.style.background = newBackgroundColor; - }; - - const handleButtonClick = event => { - // Request dependency parser - const body = { - text: message, - language: 'en' - }; - axios.post('http://localhost:8000/text/dependency-parser', body) - .then(response => setDependencyParsed(response.data)); - - // Loop through input words and create paragraph with spans - const myArray = message.split(" "); - var indents = []; - for (let i = 0; i < myArray.length; i++) { - indents.push( - - {myArray[i]} - - ); - } - setTags(indents); - }; - - // Draw Arrows at each update of the tags - useEffect(() => { - for (let i = 0; i < tags.length; i++) { - const targetNode = document.getElementById(tags[i].props.id) - const tokenObj = dependencyParsed[i.toString()]; - const tokenHead = tokenObj.head - if (tokenHead != null) { - const sourceNode = document.getElementById('span-tag-' + tokenHead.ind); - if (i % 2 === 0) { - var position = 'top'; - var gravity = -100; - } else { - var position = 'bottom'; - var gravity = 100; - } - const lineOptions = { - path: "fluid", - startSocket: position, - endSocket: position, - size: 4, - dropShadow: true, - startSocketGravity: [0, gravity], - endSocketGravity: [0, gravity], - middleLabel: LeaderLine.captionLabel(tokenHead.relationship, { color: 'black', fontSize: "25px" }), - // color: window.getComputedStyle(document.getElementById("bibliography")).color, - // startPlug: "disc", - // endPlug: "behind", - }; - var line = new LeaderLine( - LeaderLine.mouseHoverAnchor( - sourceNode, - 'draw', - { - animOptions: { duration: 800, timing: 'ease' }, - style: { backgroundColor: 'rgba(0,0,0,0)', backgroundImage: null, color: null }, - hoverStyle: { backgroundColor: 'rgba(0,0,0,0)', backgroundImage: null, color: null } - } - ), - // targetNode, - LeaderLine.mouseHoverAnchor( - targetNode, - 'draw', - { - animOptions: { duration: 800, timing: 'ease' }, - style: { backgroundColor: 'rgba(0,0,0,0)', backgroundImage: null, color: null }, - hoverStyle: { backgroundColor: 'rgba(0,0,0,0)', backgroundImage: null, color: null } - } - ), - lineOptions - ); - line.id = "arrow-line-" + i.toString() + '-' + tokenHead.ind - } - } - }, [dependencyParsed]); - - return ( -
-

Interactive grammar

-
-
- - -
- -

-

-
-

- {tags} -

-
-
-
- ) -} - -export default App diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..faaf23b --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,12 @@ +import React from "react"; +import Home from "./pages/Home"; + +function App() { + return ( +
+ +
+ ); +} + +export default App; \ No newline at end of file diff --git a/src/components/GrammarRelationship/index.tsx b/src/components/GrammarRelationship/index.tsx new file mode 100644 index 0000000..9bbc449 --- /dev/null +++ b/src/components/GrammarRelationship/index.tsx @@ -0,0 +1,113 @@ +import React, { useState, useEffect, useCallback } from 'react' +import LeaderLine from "react-leader-line"; +import { IGrammarRelationshipData } from '../../interfaces/grammar-relationship-interface' + +interface Props { + data?: IGrammarRelationshipData; + /** + * style + * arrows + * colors + * onClick span callback (freeze) - not prop? clicked span + * + */ +} + +const color_pallete = [ + "rgba(252, 186, 3, 0)", + "rgba(247, 16, 0, 0)", + "rgba(0, 247, 86, 0)", + "rgba(0, 202, 247, 0)", + "rgba(82, 0, 247, 0)", + "rgba(247, 0, 235, 0)", + ] + +const GrammarRelationshipComponent = ({data}: Props) => { + const [tags, setTags] = useState([]) + + useEffect(() => { + if (!data) return; + var newTags: any[] = [] + Object.entries(data).forEach(([key, value], index) => { + const tag = + + {value['text']} + + newTags.push(tag) + }) + setTags(newTags); + }, [data]) + + useEffect(()=>{ + if (!data) return; + for (let i=0; i + {tags} + + ) +} + +export default GrammarRelationshipComponent; \ No newline at end of file diff --git a/src/interfaces/grammar-relationship-interface.tsx b/src/interfaces/grammar-relationship-interface.tsx new file mode 100644 index 0000000..2d24c43 --- /dev/null +++ b/src/interfaces/grammar-relationship-interface.tsx @@ -0,0 +1,15 @@ +interface IHead { + ind: string | number + relationship: string + relationshipTag: string + } + +export interface IGrammarRelationshipData { + [key: string | number]: { + text: string, + pos: string, + head: IHead[] + posTag: string + children: any[] + } +} \ No newline at end of file diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx new file mode 100644 index 0000000..7816fb4 --- /dev/null +++ b/src/pages/Home/index.tsx @@ -0,0 +1,50 @@ +import React, { useState, useCallback } from 'react' +import GrammarRelationshipComponent from '../../components/GrammarRelationship' +import '../../App.css' +import axios from 'axios'; + + +const Home = () => { + const [message, setMessage] = useState('') + const [grammarData, setGrammarData] = useState({}) + + + const handleClick = useCallback(() => { + // Request dependency parser + const body = { + text: message, + language: 'en' + }; + axios.post('http://localhost:8000/text/dependency-parser', body) + .then(response => { + setGrammarData(response.data) + }); + }, [message]) + + + return ( +
+

Interactive grammar

+
+
+ + setMessage(event.target.value)} + /> +
+ +

+

+
+ +
+
+
+ ) +} + +export default Home; diff --git a/src/services/api/baseApi/index.ts b/src/services/api/baseApi/index.ts new file mode 100644 index 0000000..311bee7 --- /dev/null +++ b/src/services/api/baseApi/index.ts @@ -0,0 +1,61 @@ +import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios"; + +export type AxiosMethods = + | "get" + | "delete" + | "head" + | "options" + | "post" + | "put" + | "patch"; + +export abstract class BaseApi { + private readonly api: AxiosInstance; + + constructor() { + this.api = axios.create({ + baseURL: "http://localhost:8000", // @todo change to env variable + }); + } + + protected async request( + method: AxiosMethods, + url: string, + data?: RequestType, + config?: AxiosRequestConfig, + ): Promise> { + const configWithHeaders = { + ...config, + headers: { + ...config?.headers, + }, + }; + + try { + switch (method) { + case "get": + return await this.api.get(url, configWithHeaders); + case "post": + return await this.api.post(url, data, configWithHeaders); + case "put": + return await this.api.put(url, data, configWithHeaders); + case "patch": + return await this.api.patch(url, data, configWithHeaders); + case "delete": + return await this.api.delete(url, { ...configWithHeaders, data }); + case "head": + return await this.api.head(url, configWithHeaders); + case "options": + return await this.api.options(url, configWithHeaders); + default: + throw new Error(`Method ${method} is not supported`); + } + } catch (error) { + if (error.response) { + throw new Error(error.response.data.message); + } else { + throw new Error(error.message); + } + } + } +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..0bbd9e5 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import viteTsconfigPaths from "vite-tsconfig-paths"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react(), viteTsconfigPaths()], + build: { + outDir: "build", + }, +}); \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index bca1586..14b36d0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -240,6 +240,11 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" +"@cush/relative@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@cush/relative/-/relative-1.0.0.tgz#8cd1769bf9bde3bb27dac356b1bc94af40f6cc16" + integrity sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA== + "@esbuild/linux-loong64@0.15.7": version "0.15.7" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.15.7.tgz#1ec4af4a16c554cbd402cc557ccdd874e3f7be53" @@ -399,7 +404,7 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== -debug@^4.1.0: +debug@^4.1.0, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -582,11 +587,21 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +glob-regex@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/glob-regex/-/glob-regex-0.3.2.tgz#27348f2f60648ec32a4a53137090b9fb934f3425" + integrity sha512-m5blUd3/OqDTWwzBBtWBPrGlAzatRywHameHeekAZyZrskYouOGdNB8T/q6JucucvJXtOuyHIn0/Yia7iDasDw== + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globrex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" + integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -652,6 +667,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -739,6 +759,16 @@ react@^18.2.0: dependencies: loose-envify "^1.1.0" +recrawl-sync@^2.0.3: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recrawl-sync/-/recrawl-sync-2.2.2.tgz#a5a8664c77267d603d601825af544d6716d69e15" + integrity sha512-E2sI4F25Fu2nrfV+KsnC7/qfk/spQIYXlonfQoS4rwxeNK5BjxnLPbWiRXHVXPwYBOTWtPX5765kTm/zJiL+LQ== + dependencies: + "@cush/relative" "^1.0.0" + glob-regex "^0.3.0" + slash "^3.0.0" + tslib "^1.9.3" + resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" @@ -772,6 +802,11 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" @@ -782,6 +817,11 @@ sourcemap-codec@^1.4.8: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -799,6 +839,20 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== +tsconfig-paths@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz#f8ef7d467f08ae3a695335bf1ece088c5538d2c1" + integrity sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow== + dependencies: + json5 "^2.2.1" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + update-browserslist-db@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" @@ -807,6 +861,16 @@ update-browserslist-db@^1.0.9: escalade "^3.1.1" picocolors "^1.0.0" +vite-tsconfig-paths@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-3.5.0.tgz#bfdf93f8072eff04125112ea9602fd50ae8cdad9" + integrity sha512-NKIubr7gXgh/3uniQaOytSg+aKWPrjquP6anAy+zCWEn6h9fB8z2/qdlfQrTgZWaXJ2pHVlllrSdRZltHn9P4g== + dependencies: + debug "^4.1.1" + globrex "^0.1.2" + recrawl-sync "^2.0.3" + tsconfig-paths "^4.0.0" + vite@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/vite/-/vite-3.1.1.tgz#fcfe12c3fe7e4c6def1fc52e4dc9cb0ccb2b1a59"