diff --git a/twenty-frontend/package-lock.json b/twenty-frontend/package-lock.json index 1805ed7..b444173 100644 --- a/twenty-frontend/package-lock.json +++ b/twenty-frontend/package-lock.json @@ -14,11 +14,13 @@ "@types/luxon": "^3.3.7", "@types/react": "^18.0.18", "@types/react-dom": "^18.0.6", + "@types/showdown": "^2.0.6", "eslint": "^8.26.0", "eslint-config-prettier": "^8.5.0", "luxon": "^3.4.4", "prettier": "^2.7.1", "react-hook-form": "^7.49.2", + "showdown": "^2.1.0", "ts-loader": "^9.3.1", "ts-standard": "^12.0.1", "typescript": "^4.8.2", @@ -317,6 +319,12 @@ "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, + "node_modules/@types/showdown": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/showdown/-/showdown-2.0.6.tgz", + "integrity": "sha512-pTvD/0CIeqe4x23+YJWlX2gArHa8G0J0Oh6GKaVXV7TAeickpkkZiNOgFcFcmLQ5lB/K0qBJL1FtRYltBfbGCQ==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", @@ -4018,6 +4026,31 @@ "node": ">=8" } }, + "node_modules/showdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz", + "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==", + "dev": true, + "dependencies": { + "commander": "^9.0.0" + }, + "bin": { + "showdown": "bin/showdown.js" + }, + "funding": { + "type": "individual", + "url": "https://www.paypal.me/tiviesantos" + } + }, + "node_modules/showdown/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", diff --git a/twenty-frontend/package.json b/twenty-frontend/package.json index 47f50cb..022b22f 100644 --- a/twenty-frontend/package.json +++ b/twenty-frontend/package.json @@ -9,11 +9,13 @@ "@types/luxon": "^3.3.7", "@types/react": "^18.0.18", "@types/react-dom": "^18.0.6", + "@types/showdown": "^2.0.6", "eslint": "^8.26.0", "eslint-config-prettier": "^8.5.0", "luxon": "^3.4.4", "prettier": "^2.7.1", "react-hook-form": "^7.49.2", + "showdown": "^2.1.0", "ts-loader": "^9.3.1", "ts-standard": "^12.0.1", "typescript": "^4.8.2", diff --git a/twenty-frontend/src/css/_colors.scss b/twenty-frontend/src/css/_colors.scss index 1fd97ce..12038d8 100644 --- a/twenty-frontend/src/css/_colors.scss +++ b/twenty-frontend/src/css/_colors.scss @@ -1 +1,3 @@ $black: lighten(#000, 20%); +$gray1: #f4f0ec; +$gray2: lighten($gray1, 5%); diff --git a/twenty-frontend/src/css/_tables.scss b/twenty-frontend/src/css/_tables.scss new file mode 100644 index 0000000..c6b00e5 --- /dev/null +++ b/twenty-frontend/src/css/_tables.scss @@ -0,0 +1,41 @@ +@import "colors"; + +.table { + .table.div { + display: flex; + padding: 10px; + width: 100%; + color: #FFF; + background: $gray1; + color: $black; + border-radius: 2px; + border: #cfcfc4 1px solid; + border-bottom: none; + } + + .table.div.tabbed { + padding: 5px 5px 0 5px; + ul.tabs { + list-style-type: none; + display: flex; + height: 100%; + margin: 0; + padding: 0; + li { + height: 100%; + border: 1px solid #cfcfc4; + border-bottom: none; + padding: 10px; + background: #FFF; + margin-right: 10px; + border-radius: 5px; + } + } + } + + .table.content { + background: $gray2; + padding: 10px; + border: #cfcfc4 1px solid; + } +} diff --git a/twenty-frontend/src/css/main.scss b/twenty-frontend/src/css/main.scss index bcb2b25..b176d84 100644 --- a/twenty-frontend/src/css/main.scss +++ b/twenty-frontend/src/css/main.scss @@ -1,6 +1,7 @@ @import "fonts"; @import "colors"; @import "forms"; +@import "tables"; *, *:before, *:after { box-sizing: border-box; @@ -11,60 +12,58 @@ html, html body, .root { } body { - font-family: "SF Mono","Segoe UI Mono","Roboto Mono",Menlo,Courier,monospace; font-weight: normal; + font-family: "Noto Sans Serif"; } .root { margin: 0 auto; color: $black; width: 75%; + padding: 20px 0 20px 0; max-width: 1024px; - .navbar { - display: flex; - justify-content: space-between; - width: 100%; - padding: 10px 0px 10px 0px; - } - form { - margin: 0 auto; - height: 100%; - width: 80%; +} - .textarea { - margin: 0 0 10px 0; - height: 50%; - textarea { height: 100%; } +.root { + .issue { + .content { + padding: 10px; + } + .content, textarea { + min-height: 350px; } } - ul { - margin: 0; - padding: 0; - list-style-type: none; - li { - margin: 0 0 15px 0; - .item.row { - display: flex; - background: #f4f0ec; - border: #cfcfc4 1px solid; - border-radius: 10px; - padding: 15px; - flex-wrap: wrap; - .header { - .item.id { - border: 1px #cfcfc4 solid; - border-radius: 10px; - padding: 5px; - margin-right: 5px; - background: #FFF; - } - } - .footer { + + .react-mount.issues { + ul { + margin: 0; + padding: 0; + list-style-type: none; + li { + margin: 0 0 15px 0; + .item.row { display: flex; - width: 100%; - justify-content: space-between; - margin: 20px 0 0 0; - font-size: small; + background: #f4f0ec; + border: #cfcfc4 1px solid; + border-radius: 10px; + padding: 10px; + flex-wrap: wrap; + .header { + .item.id { + border: 1px #cfcfc4 solid; + border-radius: 10px; + padding: 5px; + margin-right: 5px; + background: #FFF; + } + } + .footer { + display: flex; + width: 100%; + justify-content: space-between; + margin: 10px 0 0 0; + font-size: small; + } } } } diff --git a/twenty-frontend/src/html/issues/index.html.erb b/twenty-frontend/src/html/issues/index.html.erb index fd3d66f..e11aa29 100644 --- a/twenty-frontend/src/html/issues/index.html.erb +++ b/twenty-frontend/src/html/issues/index.html.erb @@ -1,5 +1,4 @@
-
diff --git a/twenty-frontend/src/html/issues/new/index.html.erb b/twenty-frontend/src/html/issues/new/index.html.erb index b1028df..ca7eebc 100644 --- a/twenty-frontend/src/html/issues/new/index.html.erb +++ b/twenty-frontend/src/html/issues/new/index.html.erb @@ -1,4 +1,4 @@
-
+
diff --git a/twenty-frontend/src/html/issues/read/index.html.erb b/twenty-frontend/src/html/issues/read/index.html.erb index a6e7e69..f07daff 100644 --- a/twenty-frontend/src/html/issues/read/index.html.erb +++ b/twenty-frontend/src/html/issues/read/index.html.erb @@ -1,4 +1,4 @@
-
+
diff --git a/twenty-frontend/src/js/components/Issue.tsx b/twenty-frontend/src/js/components/Issue.tsx new file mode 100644 index 0000000..14515ed --- /dev/null +++ b/twenty-frontend/src/js/components/Issue.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useState, useRef } from "react"; +import { useForm } from "react-hook-form"; +import { Select } from "/components/forms/Select"; +import { useUpsertIssue } from "/hooks/useUpsertIssue"; +import { useConnections } from "/hooks/useConnections"; +import { Issue } from "/types/schema"; +import showdown from "showdown"; + +type Inputs = { + id?: number; + title: string; + content: string; + connectionId: number; +}; + +export function Issue({ issue }: { issue?: Issue }) { + const { register, handleSubmit, watch, setValue: set } = useForm(); + const [isEditable, setIsEditable] = useState(!issue); + const selectRef = useRef(null); + const upsert = useUpsertIssue(); + const [connections] = useConnections(); + const c = new showdown.Converter(); + const content = watch("content"); + const onSave = (input: Inputs) => { + upsert({ input }).then(() => { + location.href = "/issues/"; + }); + }; + + useEffect(() => { + set("connectionId", 1); + }, []); + + return ( +
+ +
+
+
    +
  • setIsEditable(true)}>Write
  • +
  • setIsEditable(false)}>Preview
  • +
+
+
+
+ +
+
+ +
+ {isEditable ? ( + <> +
+