From 9f6635d645fa5a51916226303b5479eea4c87779 Mon Sep 17 00:00:00 2001 From: ashik-75 Date: Mon, 18 Sep 2023 17:02:02 +0600 Subject: [PATCH 1/7] add tabs in newsfeed --- .../General/ListItems/News/News.tsx | 5 ++- .../General/ListItems/News/utils/types.ts | 1 + .../components/DisplayColor/index.tsx | 12 ++++- .../components/DisplayColors/index.tsx | 1 + .../pages/Colors/ColorPicker/utils/types.ts | 1 + ui/src/pages/Newsfeed/index.tsx | 44 ++++++++++++++----- ui/src/pages/Newsfeed/utils/constants.ts | 33 ++++++++++++++ ui/src/pages/Newsfeed/utils/helper.ts | 27 ++++++++++++ 8 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 ui/src/pages/Newsfeed/utils/constants.ts create mode 100644 ui/src/pages/Newsfeed/utils/helper.ts diff --git a/ui/src/components/General/ListItems/News/News.tsx b/ui/src/components/General/ListItems/News/News.tsx index 1e8b3dda..9c4b58c9 100644 --- a/ui/src/components/General/ListItems/News/News.tsx +++ b/ui/src/components/General/ListItems/News/News.tsx @@ -1,5 +1,5 @@ import { NewsType } from "./utils/types"; -import { Card, Skeleton, Typography } from "antd"; +import { Card, Image, Skeleton, Typography } from "antd"; import { ListItemProps } from "components/RenderProps/List/utils/types"; const { Title } = Typography; @@ -8,11 +8,12 @@ const News: React.FC> = ({ handleOnClick, isLoading, }) => { - const { title, content, url } = resource || {}; + const { title, content, url, image } = resource || {}; return ( handleOnClick(url)} hoverable> + {title} {content} diff --git a/ui/src/components/General/ListItems/News/utils/types.ts b/ui/src/components/General/ListItems/News/utils/types.ts index cfaec190..82dd494e 100644 --- a/ui/src/components/General/ListItems/News/utils/types.ts +++ b/ui/src/components/General/ListItems/News/utils/types.ts @@ -2,6 +2,7 @@ interface NewsType { title: string; content: string; url: string; + image?: string; } export type { NewsType }; diff --git a/ui/src/pages/Colors/ColorPicker/components/DisplayColor/index.tsx b/ui/src/pages/Colors/ColorPicker/components/DisplayColor/index.tsx index ac0a0ae5..934ce670 100644 --- a/ui/src/pages/Colors/ColorPicker/components/DisplayColor/index.tsx +++ b/ui/src/pages/Colors/ColorPicker/components/DisplayColor/index.tsx @@ -5,6 +5,7 @@ import ClipboardButton from "components/General/ClipboardButton"; import { classNames, getTextColor, isTransparent } from "lib/utils/helper"; import { DisplayColorProps } from "pages/Colors/ColorPicker/utils/types"; import { useSearchParams } from "react-router-dom"; +import CodeHighlightWithCopy from "components/General/CodeHighlightWithCopy"; const { Title } = Typography; @@ -14,6 +15,7 @@ const DisplayColor: React.FC = ({ customValue, value, format, + title, }) => { const { token: { colorBgContainer, colorText }, @@ -35,19 +37,27 @@ const DisplayColor: React.FC = ({ const containerStyle = { backgroundColor: color ? backgroundColor : colorBgContainer, border: color ? border : "none", + padding: "5px", }; const titleStyle = { color: color ? textColor : colorText, }; - return ( + return title === "Colors" ? (
{customLabel}: {color ? customValue : ""}
+ ) : ( +
+ +
); }; diff --git a/ui/src/pages/Colors/ColorPicker/components/DisplayColors/index.tsx b/ui/src/pages/Colors/ColorPicker/components/DisplayColors/index.tsx index 246f5b7d..bd421718 100644 --- a/ui/src/pages/Colors/ColorPicker/components/DisplayColors/index.tsx +++ b/ui/src/pages/Colors/ColorPicker/components/DisplayColors/index.tsx @@ -38,6 +38,7 @@ const DisplayColors: React.FC = ({ customValue={determineValue(value, displayType, colors)} value={colors[value]} format={format} + title={title} /> ))} diff --git a/ui/src/pages/Colors/ColorPicker/utils/types.ts b/ui/src/pages/Colors/ColorPicker/utils/types.ts index d7b00c31..01ddb970 100644 --- a/ui/src/pages/Colors/ColorPicker/utils/types.ts +++ b/ui/src/pages/Colors/ColorPicker/utils/types.ts @@ -19,6 +19,7 @@ interface DisplayColorProps { customValue: string; value: string; format: string; + title: string; } export type { FormatType, DisplayColorsProps, DisplayColorProps, colors }; diff --git a/ui/src/pages/Newsfeed/index.tsx b/ui/src/pages/Newsfeed/index.tsx index ac3c47bb..8d05e6d6 100644 --- a/ui/src/pages/Newsfeed/index.tsx +++ b/ui/src/pages/Newsfeed/index.tsx @@ -1,21 +1,41 @@ -import News from "components/General/ListItems/News/News"; +import React, { useState } from "react"; +import { SITE_OPTIONS, TAB_ITEMS } from "./utils/constants"; import useFetchList from "lib/utils/hooks/useFetchList"; +import { Tabs } from "antd"; import ListSearchResults from "components/RenderProps/ListSearchResults"; - -const URL = `https://raw.githubusercontent.com/lifeparticle/binarytree/main/api/news.json`; +import News from "components/General/ListItems/News/News"; +import { parseXML } from "./utils/helper"; export const QUERY_KEY_NEWS = "news"; -const Newsfeed = () => { - const { data, isLoading, isError } = useFetchList(QUERY_KEY_NEWS, URL); +const Newsfeed: React.FC = () => { + const corsProxyUrl = "https://cors-anywhere.herokuapp.com/"; + const [url, setUrl] = useState(SITE_OPTIONS["frontend-focus"].value); + const isFeedUrl = + url === SITE_OPTIONS["frontend-focus"].value || + url === SITE_OPTIONS["status-code"].value; + const { data, isLoading, isError } = useFetchList( + url, + isFeedUrl ? corsProxyUrl + url : url + ); return ( - + <> + { + setUrl(value); + }} + /> + + + ); }; diff --git a/ui/src/pages/Newsfeed/utils/constants.ts b/ui/src/pages/Newsfeed/utils/constants.ts new file mode 100644 index 00000000..30f6a5c8 --- /dev/null +++ b/ui/src/pages/Newsfeed/utils/constants.ts @@ -0,0 +1,33 @@ +import { TabsProps } from "antd"; + +const SITE_OPTIONS = { + "frontend-focus": { + label: "Frontend Focus", + value: "https://cprss.s3.amazonaws.com/frontendfoc.us.xml", + }, + "status-code": { + label: "Status Code", + value: "https://cprss.s3.amazonaws.com/react.statuscode.com.xml", + }, + news: { + label: "News", + value: "https://raw.githubusercontent.com/lifeparticle/binarytree/main/api/news.json", + }, +}; + +const TAB_ITEMS: TabsProps["items"] = [ + { + key: SITE_OPTIONS["frontend-focus"].value, + label: SITE_OPTIONS["frontend-focus"].label, + }, + { + key: SITE_OPTIONS["status-code"].value, + label: SITE_OPTIONS["status-code"].label, + }, + { + key: SITE_OPTIONS["news"].value, + label: SITE_OPTIONS["news"].label, + }, +]; + +export { SITE_OPTIONS, TAB_ITEMS }; diff --git a/ui/src/pages/Newsfeed/utils/helper.ts b/ui/src/pages/Newsfeed/utils/helper.ts new file mode 100644 index 00000000..8fe3b6b4 --- /dev/null +++ b/ui/src/pages/Newsfeed/utils/helper.ts @@ -0,0 +1,27 @@ +function parseXML(value: string) { + const parser = new DOMParser(); + const xmldoc = parser.parseFromString(value, "text/xml"); + + const items = xmldoc.getElementsByTagName("item"); + const list = []; + + for (let i = 0; i < items.length; i++) { + const item = items[i]; + + // Extract data from the 'item' element + const title = item.getElementsByTagName("title")[0].textContent; + const description = parser.parseFromString( + item.getElementsByTagName("description")[0].textContent!, + "text/html" + ); + const image = description?.getElementsByTagName("img")?.[0]?.src; + const pubDate = item.getElementsByTagName("pubDate")[0].textContent; + const url = item.getElementsByTagName("link")[0].textContent; + + list.push({ title, pubDate, url, image }); + } + + return list; +} + +export { parseXML }; From cf694f77c257cb9886596a4101af7062d43b83b8 Mon Sep 17 00:00:00 2001 From: ashik-75 Date: Mon, 18 Sep 2023 17:17:44 +0600 Subject: [PATCH 2/7] load proxy based on environment --- ui/src/pages/Newsfeed/index.tsx | 7 ++++--- ui/src/pages/Newsfeed/utils/constants.ts | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ui/src/pages/Newsfeed/index.tsx b/ui/src/pages/Newsfeed/index.tsx index 8d05e6d6..6ffba903 100644 --- a/ui/src/pages/Newsfeed/index.tsx +++ b/ui/src/pages/Newsfeed/index.tsx @@ -1,5 +1,5 @@ import React, { useState } from "react"; -import { SITE_OPTIONS, TAB_ITEMS } from "./utils/constants"; +import { SITE_OPTIONS, TAB_ITEMS, corsProxyUrl } from "./utils/constants"; import useFetchList from "lib/utils/hooks/useFetchList"; import { Tabs } from "antd"; import ListSearchResults from "components/RenderProps/ListSearchResults"; @@ -8,14 +8,15 @@ import { parseXML } from "./utils/helper"; export const QUERY_KEY_NEWS = "news"; const Newsfeed: React.FC = () => { - const corsProxyUrl = "https://cors-anywhere.herokuapp.com/"; const [url, setUrl] = useState(SITE_OPTIONS["frontend-focus"].value); const isFeedUrl = url === SITE_OPTIONS["frontend-focus"].value || url === SITE_OPTIONS["status-code"].value; const { data, isLoading, isError } = useFetchList( url, - isFeedUrl ? corsProxyUrl + url : url + isFeedUrl && import.meta.env.MODE === "development" + ? corsProxyUrl + url + : url ); return ( diff --git a/ui/src/pages/Newsfeed/utils/constants.ts b/ui/src/pages/Newsfeed/utils/constants.ts index 30f6a5c8..767c33d9 100644 --- a/ui/src/pages/Newsfeed/utils/constants.ts +++ b/ui/src/pages/Newsfeed/utils/constants.ts @@ -29,5 +29,6 @@ const TAB_ITEMS: TabsProps["items"] = [ label: SITE_OPTIONS["news"].label, }, ]; +const corsProxyUrl = "https://cors-anywhere.herokuapp.com/"; -export { SITE_OPTIONS, TAB_ITEMS }; +export { SITE_OPTIONS, TAB_ITEMS, corsProxyUrl }; From b1b1f494e0d3f7518003362c89d073e17bd174df Mon Sep 17 00:00:00 2001 From: ashik-75 Date: Mon, 18 Sep 2023 17:20:27 +0600 Subject: [PATCH 3/7] add proxy again --- ui/src/pages/Newsfeed/index.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/src/pages/Newsfeed/index.tsx b/ui/src/pages/Newsfeed/index.tsx index 6ffba903..ade139b0 100644 --- a/ui/src/pages/Newsfeed/index.tsx +++ b/ui/src/pages/Newsfeed/index.tsx @@ -14,9 +14,7 @@ const Newsfeed: React.FC = () => { url === SITE_OPTIONS["status-code"].value; const { data, isLoading, isError } = useFetchList( url, - isFeedUrl && import.meta.env.MODE === "development" - ? corsProxyUrl + url - : url + isFeedUrl ? corsProxyUrl + url : url ); return ( From 787bfc8ba567603153592ebbb0d9283e69c36b92 Mon Sep 17 00:00:00 2001 From: ashik-75 Date: Tue, 19 Sep 2023 09:14:51 +0600 Subject: [PATCH 4/7] add constant in separate file --- .../General/Search/CategoryTags/utils/helper.ts | 2 +- .../components/RenderProps/ListSearchResults/index.tsx | 2 +- ui/src/pages/Newsfeed/index.tsx | 10 +++++++--- ui/src/pages/Newsfeed/utils/constants.ts | 6 ++++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/ui/src/components/General/Search/CategoryTags/utils/helper.ts b/ui/src/components/General/Search/CategoryTags/utils/helper.ts index bcb3bc79..4cbd1372 100644 --- a/ui/src/components/General/Search/CategoryTags/utils/helper.ts +++ b/ui/src/components/General/Search/CategoryTags/utils/helper.ts @@ -1,5 +1,5 @@ -import { QUERY_KEY_NEWS } from "pages/Newsfeed"; import { ResourceType } from "components/General/ListItems/Resource/utils/types"; +import { QUERY_KEY_NEWS } from "pages/Newsfeed/utils/constants"; const getCategories = ( items: T[], diff --git a/ui/src/components/RenderProps/ListSearchResults/index.tsx b/ui/src/components/RenderProps/ListSearchResults/index.tsx index b420ede0..10f9bb97 100644 --- a/ui/src/components/RenderProps/ListSearchResults/index.tsx +++ b/ui/src/components/RenderProps/ListSearchResults/index.tsx @@ -1,7 +1,6 @@ import { useSearchParams } from "react-router-dom"; import style from "./ListSearchResults.module.scss"; import { ResourceType } from "components/General/ListItems/Resource/utils/types"; -import { QUERY_KEY_NEWS } from "pages/Newsfeed"; import Search from "components/General/Search"; import { getCategories } from "components/General/Search/CategoryTags/utils/helper"; import { ListSearchResultsProps } from "./utils/types"; @@ -11,6 +10,7 @@ import Text from "components/General/Text/Text"; import { Typography } from "antd"; import { filteredNews, filteredResource } from "./utils/helper"; import { ReactElement } from "react"; +import { QUERY_KEY_NEWS } from "pages/Newsfeed/utils/constants"; const { Title } = Typography; diff --git a/ui/src/pages/Newsfeed/index.tsx b/ui/src/pages/Newsfeed/index.tsx index ade139b0..64bc53ef 100644 --- a/ui/src/pages/Newsfeed/index.tsx +++ b/ui/src/pages/Newsfeed/index.tsx @@ -1,11 +1,15 @@ import React, { useState } from "react"; -import { SITE_OPTIONS, TAB_ITEMS, corsProxyUrl } from "./utils/constants"; +import { + QUERY_KEY_NEWS, + SITE_OPTIONS, + TAB_ITEMS, + CORS_PROXY_URL, +} from "./utils/constants"; import useFetchList from "lib/utils/hooks/useFetchList"; import { Tabs } from "antd"; import ListSearchResults from "components/RenderProps/ListSearchResults"; import News from "components/General/ListItems/News/News"; import { parseXML } from "./utils/helper"; -export const QUERY_KEY_NEWS = "news"; const Newsfeed: React.FC = () => { const [url, setUrl] = useState(SITE_OPTIONS["frontend-focus"].value); @@ -14,7 +18,7 @@ const Newsfeed: React.FC = () => { url === SITE_OPTIONS["status-code"].value; const { data, isLoading, isError } = useFetchList( url, - isFeedUrl ? corsProxyUrl + url : url + isFeedUrl ? CORS_PROXY_URL + url : url ); return ( diff --git a/ui/src/pages/Newsfeed/utils/constants.ts b/ui/src/pages/Newsfeed/utils/constants.ts index 767c33d9..9a78a6c3 100644 --- a/ui/src/pages/Newsfeed/utils/constants.ts +++ b/ui/src/pages/Newsfeed/utils/constants.ts @@ -29,6 +29,8 @@ const TAB_ITEMS: TabsProps["items"] = [ label: SITE_OPTIONS["news"].label, }, ]; -const corsProxyUrl = "https://cors-anywhere.herokuapp.com/"; +const CORS_PROXY_URL = "https://cors-anywhere.herokuapp.com/"; -export { SITE_OPTIONS, TAB_ITEMS, corsProxyUrl }; +const QUERY_KEY_NEWS = "news"; + +export { SITE_OPTIONS, TAB_ITEMS, CORS_PROXY_URL, QUERY_KEY_NEWS }; From 136308ae93ff6cf90c2fe9820d1c0ea1ed1a88ee Mon Sep 17 00:00:00 2001 From: ashik-75 Date: Tue, 19 Sep 2023 14:15:04 +0600 Subject: [PATCH 5/7] add text differentiator --- ui/package.json | 2 + .../Layouts/Menu/utils/constants.ts | 6 ++ .../Information/Textdiff/Textdiff.module.scss | 7 ++ ui/src/pages/Information/Textdiff/index.tsx | 82 +++++++++++++++++++ ui/src/pages/Routes/utils/constant.tsx | 8 ++ ui/src/pages/Routes/utils/types.ts | 1 + ui/src/pages/pages.ts | 2 + ui/yarn.lock | 11 ++- 8 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 ui/src/pages/Information/Textdiff/Textdiff.module.scss create mode 100644 ui/src/pages/Information/Textdiff/index.tsx diff --git a/ui/package.json b/ui/package.json index 25928818..a91756e9 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,6 +19,7 @@ "@uiw/react-md-editor": "^3.23.5", "antd": "^5.4.7", "buffer": "^6.0.3", + "diff": "^5.1.0", "easymde": "^2.18.0", "file-saver": "^2.0.5", "fs-extra": "^11.1.1", @@ -74,6 +75,7 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", + "@types/diff": "^5.0.4", "@types/markdown-it": "^13.0.0", "@types/marked": "^5.0.1", "@types/node": "^20.4.4", diff --git a/ui/src/components/Layouts/Menu/utils/constants.ts b/ui/src/components/Layouts/Menu/utils/constants.ts index f743422e..df75a16a 100644 --- a/ui/src/components/Layouts/Menu/utils/constants.ts +++ b/ui/src/components/Layouts/Menu/utils/constants.ts @@ -180,6 +180,12 @@ export const MENU_ITEMS = [ icon: "ArrowLeftRight", show: true, }, + { + name: routesById.textdiff.title, + url: routesById.textdiff.path, + icon: "Diff", + show: true, + }, ], }, { diff --git a/ui/src/pages/Information/Textdiff/Textdiff.module.scss b/ui/src/pages/Information/Textdiff/Textdiff.module.scss new file mode 100644 index 00000000..ada17c22 --- /dev/null +++ b/ui/src/pages/Information/Textdiff/Textdiff.module.scss @@ -0,0 +1,7 @@ +.textdiff { + &__button { + display: flex; + justify-content: center; + padding: var(--bt-size-20) 0; + } +} diff --git a/ui/src/pages/Information/Textdiff/index.tsx b/ui/src/pages/Information/Textdiff/index.tsx new file mode 100644 index 00000000..b476b992 --- /dev/null +++ b/ui/src/pages/Information/Textdiff/index.tsx @@ -0,0 +1,82 @@ +import { Card, Form, Input } from "antd"; +import PageGrid from "components/Layouts/PageGrid"; +import React, { useState } from "react"; + +import { diffChars, Change } from "diff"; +import { ResponsiveButton } from "components/General/FormComponents"; +import style from "./Textdiff.module.scss"; + +const { TextArea } = Input; + +const Textdiff: React.FC = () => { + const [text1, setText1] = useState(""); + const [text2, setText2] = useState(""); + const [differences, setDifferences] = useState([]); + + const calculateDiff = () => { + const diff = diffChars(text1, text2); + setDifferences(diff); + }; + + return ( + <> + + +
+ +