From acce5fa5c95489411386f0985f26978fe79f77d9 Mon Sep 17 00:00:00 2001 From: ViktoriiaNakoryk Date: Thu, 15 Feb 2024 14:48:32 +0100 Subject: [PATCH 01/15] added rendering and markup for statistic tab --- package.json | 2 + src/components/Chart/Chart.tsx | 104 +++++++++++++++++++++++++ src/components/Sidebar/Settings.tsx | 2 +- src/components/Sidebar/Sidebar.tsx | 80 ++++++++++++------- src/components/Statistic/Statistic.tsx | 96 +++++++++++++++++++++++ src/components/Table/Table.module.css | 12 +++ src/components/Table/Table.tsx | 97 +++++++++++++++++++++++ src/lib/index.ts | 2 +- src/lib/render/RenderStatistic.tsx | 18 +++++ src/lib/render/index.tsx | 1 + src/services/refact.ts | 34 ++++++++ 11 files changed, 417 insertions(+), 31 deletions(-) create mode 100644 src/components/Chart/Chart.tsx create mode 100644 src/components/Statistic/Statistic.tsx create mode 100644 src/components/Table/Table.module.css create mode 100644 src/components/Table/Table.tsx create mode 100644 src/lib/render/RenderStatistic.tsx diff --git a/package.json b/package.json index c91ce087..674c67aa 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,8 @@ "@vitest/coverage-v8": "^1.1.0", "@vitest/ui": "^1.1.0", "classnames": "^2.3.2", + "echarts": "^5.4.3", + "echarts-for-react": "^3.0.2", "eslint": "^8.55.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-react": "^7.33.2", diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx new file mode 100644 index 00000000..e3420173 --- /dev/null +++ b/src/components/Chart/Chart.tsx @@ -0,0 +1,104 @@ +import React from "react"; +import { Box, Text } from "@radix-ui/themes"; +import { + RefactTableData, + RefactTableImpactDatesRow, +} from "../../services/refact"; +import ReactEcharts from "echarts-for-react"; +import { Spinner } from "../Spinner"; + +export const Chart: React.FC<{ + refactTable: RefactTableData | null; +}> = ({ refactTable }) => { + if (refactTable === null) { + return ; + } + const refactImpactDatesWeekly: RefactTableImpactDatesRow[] = + refactTable.refact_impact_dates.data.weekly; + const dates: string[] = Object.keys(refactImpactDatesWeekly).map((date) => { + return new Date(date).toLocaleString("en-US", { + month: "short", + day: "numeric", + }); + }); + const humanData: number[] = Object.values(refactImpactDatesWeekly).map( + (entry) => entry.human, + ); + const refactData: number[] = Object.values(refactImpactDatesWeekly).map( + (entry) => entry.refact, + ); + + const option = { + tooltip: { + trigger: "axis", + axisPointer: { + type: "shadow", + }, + }, + legend: {}, + height: "200px", + grid: { + left: "3%", + right: "4%", + bottom: "3%", + containLabel: true, + }, + xAxis: [ + { + type: "category", + data: dates, + axisLabel: { + fontSize: 8, + }, + }, + ], + yAxis: [ + { + type: "value", + }, + ], + series: [ + { + name: "Human", + type: "bar", + stack: "Ad", + data: humanData, + barWidth: "80%", + }, + { + name: "Refact", + type: "bar", + stack: "Ad", + data: refactData, + barWidth: "80%", + }, + ], + }; + + return ( + + + Refact vs Human + + + + {dates.map((date: string, index: number) => ( + + + Date: {date} + + + Human: {humanData[index]} ch. + + + Refact: {refactData[index]} ch. + + + ))} + + + ); +}; diff --git a/src/components/Sidebar/Settings.tsx b/src/components/Sidebar/Settings.tsx index 1ae4ece5..50f32e8b 100644 --- a/src/components/Sidebar/Settings.tsx +++ b/src/components/Sidebar/Settings.tsx @@ -32,7 +32,7 @@ export const Settings: React.FC = () => { }; return ( - + diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index b10264a4..c8d14097 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -1,43 +1,65 @@ -import React from "react"; -import { Box, Flex, Button } from "@radix-ui/themes"; +import React, { useState } from "react"; +import { Box, Flex, Button, IconButton } from "@radix-ui/themes"; +import { BarChartIcon } from "@radix-ui/react-icons"; import styles from "./sidebar.module.css"; import { ChatHistory, type ChatHistoryProps } from "../ChatHistory"; import { Settings } from "./Settings"; +import { Statistic } from "../Statistic/Statistic"; export const Sidebar: React.FC< { onCreateNewChat: () => void; } & ChatHistoryProps -> = ({ history, onHistoryItemClick, onCreateNewChat, onDeleteHistoryItem }) => { + > = ({ history, onHistoryItemClick, onCreateNewChat, onDeleteHistoryItem }) => { + const [isOpenedStatistic, setIsOpenedStatistic] = useState(false); + + const handleCloseStatistic = () => { + setIsOpenedStatistic(false); + }; return ( - - - + {isOpenedStatistic ? ( + + + + ) : ( + + + + + + + + setIsOpenedStatistic(true)} + > + + + - - - + )} ); }; diff --git a/src/components/Statistic/Statistic.tsx b/src/components/Statistic/Statistic.tsx new file mode 100644 index 00000000..0d9525b3 --- /dev/null +++ b/src/components/Statistic/Statistic.tsx @@ -0,0 +1,96 @@ +import React, { useEffect, useState } from "react"; +import { Box, Flex, Button, Heading, Responsive } from "@radix-ui/themes"; +import { RefactTableData } from "../../services/refact"; +import { Table } from "../Table/Table"; +import { Chart } from "../Chart/Chart"; +import { Spinner } from "../Spinner"; +import { ArrowLeftIcon } from "@radix-ui/react-icons"; +import { useEventBusForChat } from "../../hooks"; +import { useConfig } from "../../contexts/config-context"; + +const table: { data: string } = { + data: '{"refact_impact_dates":{"data":{"daily":{"2023-12-15":{"completions":14,"human":52,"langs":[".rs",".py"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-18":{"completions":16,"human":83,"langs":[".py"],"refact":245,"refact_impact":0.7469512224197388,"total":328},"2023-12-19":{"completions":6,"human":4,"langs":[".cpp"],"refact":103,"refact_impact":0.9626168012619019,"total":107},"2023-12-20":{"completions":46,"human":857,"langs":[".py"],"refact":693,"refact_impact":0.4470967650413513,"total":1550},"2023-12-21":{"completions":92,"human":1157,"langs":[".py"],"refact":3103,"refact_impact":0.7284037470817566,"total":4260},"2023-12-22":{"completions":59,"human":-38,"langs":[".py"],"refact":2005,"refact_impact":1.0193188190460205,"total":1967},"2023-12-27":{"completions":13,"human":28,"langs":[".py"],"refact":409,"refact_impact":0.9359267950057983,"total":437},"2023-12-29":{"completions":2,"human":2,"langs":[".py"],"refact":71,"refact_impact":0.9726027250289917,"total":73},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":10,"human":808,"langs":[".rs"],"refact":410,"refact_impact":0.3366174101829529,"total":1218},"2024-01-25":{"completions":76,"human":7993,"langs":[".rs"],"refact":2772,"refact_impact":0.25750115513801575,"total":10765},"2024-01-26":{"completions":21,"human":1931,"langs":[".rs"],"refact":557,"refact_impact":0.22387459874153137,"total":2488},"2024-01-29":{"completions":21,"human":2574,"langs":[".rs"],"refact":655,"refact_impact":0.20284917950630188,"total":3229},"2024-01-30":{"completions":29,"human":1849,"langs":[".rs"],"refact":1310,"refact_impact":0.41468819975852966,"total":3159},"2024-01-31":{"completions":31,"human":3452,"langs":[".rs",".txt"],"refact":1114,"refact_impact":0.24397721886634827,"total":4566},"2024-02-01":{"completions":57,"human":8806,"langs":[".rs",".txt"],"refact":2465,"refact_impact":0.21870286762714386,"total":11271},"2024-02-02":{"completions":11,"human":5869,"langs":[".rs",".txt",".py"],"refact":307,"refact_impact":0.04970854893326759,"total":6176},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}},"weekly":{"2023-12-15":{"completions":14,"human":52,"langs":[".py",".rs"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-22":{"completions":219,"human":2063,"langs":[".py",".cpp"],"refact":6149,"refact_impact":0.7487822771072388,"total":8212},"2023-12-27":{"completions":15,"human":30,"langs":[".py"],"refact":480,"refact_impact":0.9411764740943909,"total":510},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":107,"human":10732,"langs":[".rs"],"refact":3739,"refact_impact":0.2583788335323334,"total":14471},"2024-02-02":{"completions":149,"human":22550,"langs":[".rs",".py",".txt"],"refact":5851,"refact_impact":0.20601387321949005,"total":28401},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}}}},"table_refact_impact":{"columns":["Language","Refact","Human","Total (characters)","Refact Impact","Completions"],"data":[{"completions":276,"human":31996,"lang":".rs","refact":10092,"refact_impact":0.23978331685066223,"total":42088},{"completions":243,"human":7110,"lang":".py","refact":6929,"refact_impact":0.49355366826057434,"total":14039},{"completions":6,"human":4,"lang":".cpp","refact":103,"refact_impact":0.9626168012619019,"total":107},{"completions":0,"human":98,"lang":".txt","refact":0,"refact_impact":0.0,"total":98}],"title":"Refact\'s impact by language"}}', +}; + +export const Statistic: React.FC<{ + onCloseStatistic?: () => void; +}> = ({ onCloseStatistic }) => { + const [isLoaded, setIsLoaded] = useState(false); + const [refactTable, setRefactTable] = useState(null); + const { host, tabbed } = useConfig(); + const { backFromChat } = useEventBusForChat(); + + const LeftRightPadding: Responsive< + "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + > = + host === "web" + ? { initial: "2", xl: "9" } + : { + initial: "2", + xs: "2", + sm: "4", + md: "8", + lg: "8", + xl: "9", + }; + + const TopBottomPadding: Responsive< + "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" + > = { + initial: "5", + }; + + useEffect(() => { + if (table.data) { + setRefactTable(JSON.parse(table.data) as RefactTableData); + setIsLoaded(true); + } + }, []); + + return ( + + {isLoaded ? ( + + {host === "vscode" && !tabbed ? ( + + + + ) : ( + + )} + + + Statistics + + {refactTable !== null && ( + + + + + )} + + + ) : ( + + )} + + ); +}; diff --git a/src/components/Table/Table.module.css b/src/components/Table/Table.module.css new file mode 100644 index 00000000..2d428062 --- /dev/null +++ b/src/components/Table/Table.module.css @@ -0,0 +1,12 @@ +.table { + border-collapse: collapse; + font-size: 9px; + text-align: center; + width: 100%; + table-layout: fixed; +} +.table td, +.table th { + border: 1px solid white; + padding: 3px; +} diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx new file mode 100644 index 00000000..fac8db0c --- /dev/null +++ b/src/components/Table/Table.tsx @@ -0,0 +1,97 @@ +import React from "react"; +import { Box, Text } from "@radix-ui/themes"; +import { + FormatCellValue, + ColumnName, + RefactTableImpactLanguagesRow, + RefactTableData, +} from "../../services/refact"; +import styles from "./Table.module.css"; +import { Spinner } from "../Spinner"; + +export const Table: React.FC<{ + refactTable: RefactTableData | null; +}> = ({ refactTable }) => { + if (refactTable === null) { + return ; + } + const refactImpactTable: RefactTableImpactLanguagesRow[] = + refactTable.table_refact_impact.data; + const convertedColumnNames: Record = { + lang: "Lang.", + refact: "Refact", + human: "Human", + total: "Total", + refact_impact: "Refact Impact", + completions: "Compl.", + }; + const formatCellValue: FormatCellValue = ( + columnName: string, + cellValue: string | number, + ): string | number => { + if (columnName === "refact_impact") { + return cellValue === 0 + ? cellValue + : parseFloat(cellValue.toString()).toFixed(2); + } else if (columnName === "lang" || columnName === "completions") { + return cellValue; + } else { + const convertedNumber = Number( + cellValue + .toLocaleString("en-US", { + style: "decimal", + maximumFractionDigits: 0, + minimumFractionDigits: 0, + useGrouping: true, + }) + .replace(",", "."), + ); + if (convertedNumber === 0) { + return "0"; + } else if (Number.isInteger(convertedNumber)) { + return convertedNumber + "k"; + } else { + return `${convertedNumber.toFixed(2)}k`; + } + } + }; + + return ( + + + Refact`'s impact by language + +
+ + + {Object.values(convertedColumnNames).map( + (columnName: string, idx: number) => ( + + ), + )} + + + + {refactImpactTable.map( + (rowData: RefactTableImpactLanguagesRow, idx: number) => ( + + {Object.keys(convertedColumnNames).map( + (columnName: string, idx: number) => ( + + ), + )} + + ), + )} + +
{columnName}
+ {formatCellValue( + columnName, + rowData[ + columnName as keyof RefactTableImpactLanguagesRow + ], + )} +
+
+ ); +}; diff --git a/src/lib/index.ts b/src/lib/index.ts index ec59ef7f..0ec57230 100644 --- a/src/lib/index.ts +++ b/src/lib/index.ts @@ -1,2 +1,2 @@ export * from "../events"; -export { render, renderHistoryList } from "./render"; +export { render, renderHistoryList, renderStatistic } from "./render"; diff --git a/src/lib/render/RenderStatistic.tsx b/src/lib/render/RenderStatistic.tsx new file mode 100644 index 00000000..63ead16c --- /dev/null +++ b/src/lib/render/RenderStatistic.tsx @@ -0,0 +1,18 @@ +import React from "react"; +import { ConfigProvider, type Config } from "../../contexts/config-context.tsx"; +import ReactDOM from "react-dom/client"; +import { Theme } from "../../components/Theme"; +import { Statistic } from "../../components/Statistic/Statistic"; + +export function renderStatistic(element: HTMLElement, config: Config) { + const StatisticTab: React.FC = (config) => { + return ( + + + + + + ); + }; + ReactDOM.createRoot(element).render(); +} diff --git a/src/lib/render/index.tsx b/src/lib/render/index.tsx index 52551546..0f0ea421 100644 --- a/src/lib/render/index.tsx +++ b/src/lib/render/index.tsx @@ -6,6 +6,7 @@ import type { Config } from "../../contexts/config-context"; import { Chat } from "./Chat"; export { renderHistoryList } from "./RenderHistoryList"; +export { renderStatistic } from "./RenderStatistic"; export function render(element: HTMLElement, config: Config) { ReactDOM.createRoot(element).render(); diff --git a/src/services/refact.ts b/src/services/refact.ts index b7920164..a7e0a6e5 100644 --- a/src/services/refact.ts +++ b/src/services/refact.ts @@ -200,3 +200,37 @@ export type CapsResponse = { tokenizer_rewrite_path: Record; chat_rag_functions?: string[]; }; +export type RefactTableImpactDatesRow = { + [key in ColumnName]: number; +}; +export type RefactTableImpactLanguagesRow = { + [key in ColumnName]: string | number; +}; +export type RefactTableData = { + refact_impact_dates: { + data: { + daily: RefactTableImpactDatesRow[]; + weekly: RefactTableImpactDatesRow[]; + }; + }; + table_refact_impact: { + columns: string[]; + data: RefactTableImpactLanguagesRow[]; + title: string; + }; +}; + +export type ColumnName = + | "lang" + | "refact" + | "human" + | "total" + | "refact_impact" + | "completions"; + +export type CellValue = string | number; + +export type FormatCellValue = ( + columnName: string, + cellValue: string | number, +) => string | number; From da567e4f9c3cf107324611f5b4564d84d8028b1d Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Thu, 15 Feb 2024 15:29:25 +0100 Subject: [PATCH 02/15] updated package-lock --- package-lock.json | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/package-lock.json b/package-lock.json index 28468e29..1d6a0e59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,8 @@ "@vitest/coverage-v8": "^1.1.0", "@vitest/ui": "^1.1.0", "classnames": "^2.3.2", + "echarts": "^5.4.3", + "echarts-for-react": "^3.0.2", "eslint": "^8.55.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-react": "^7.33.2", @@ -10210,6 +10212,36 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/echarts": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.4.3.tgz", + "integrity": "sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==", + "dev": true, + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.4.4" + } + }, + "node_modules/echarts-for-react": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/echarts-for-react/-/echarts-for-react-3.0.2.tgz", + "integrity": "sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "size-sensor": "^1.0.1" + }, + "peerDependencies": { + "echarts": "^3.0.0 || ^4.0.0 || ^5.0.0", + "react": "^15.0.0 || >=16.0.0" + } + }, + "node_modules/echarts/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -17989,6 +18021,12 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, + "node_modules/size-sensor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/size-sensor/-/size-sensor-1.0.2.tgz", + "integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -21068,6 +21106,21 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/zrender": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.4.4.tgz", + "integrity": "sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==", + "dev": true, + "dependencies": { + "tslib": "2.3.0" + } + }, + "node_modules/zrender/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", From 77d334d6282c897a77126b5be66901915f8ca123 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Thu, 15 Feb 2024 15:34:21 +0100 Subject: [PATCH 03/15] fixed indents --- src/components/Sidebar/Sidebar.tsx | 2 +- src/services/refact.ts | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index c8d14097..9786e8b0 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -10,7 +10,7 @@ export const Sidebar: React.FC< { onCreateNewChat: () => void; } & ChatHistoryProps - > = ({ history, onHistoryItemClick, onCreateNewChat, onDeleteHistoryItem }) => { +> = ({ history, onHistoryItemClick, onCreateNewChat, onDeleteHistoryItem }) => { const [isOpenedStatistic, setIsOpenedStatistic] = useState(false); const handleCloseStatistic = () => { diff --git a/src/services/refact.ts b/src/services/refact.ts index a7e0a6e5..6502cce0 100644 --- a/src/services/refact.ts +++ b/src/services/refact.ts @@ -221,16 +221,16 @@ export type RefactTableData = { }; export type ColumnName = - | "lang" - | "refact" - | "human" - | "total" - | "refact_impact" - | "completions"; + | "lang" + | "refact" + | "human" + | "total" + | "refact_impact" + | "completions"; export type CellValue = string | number; export type FormatCellValue = ( - columnName: string, - cellValue: string | number, + columnName: string, + cellValue: string | number, ) => string | number; From 22897369ea7b9ca6a41d8dbc5c72ad55352e7a54 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Fri, 16 Feb 2024 14:40:42 +0100 Subject: [PATCH 04/15] add scroll to statistic component --- src/components/Sidebar/Sidebar.tsx | 4 +- src/components/Statistic/Statistic.tsx | 85 ++++++++++++++++---------- 2 files changed, 53 insertions(+), 36 deletions(-) diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 9786e8b0..04c4185f 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -19,9 +19,7 @@ export const Sidebar: React.FC< return ( {isOpenedStatistic ? ( - - - + ) : ( - {isLoaded ? ( - - {host === "vscode" && !tabbed ? ( - - - - ) : ( - - )} - - - Statistics - - {refactTable !== null && ( - - - - - )} - - + {host === "vscode" && !tabbed ? ( + + + ) : ( - + )} + + + {isLoaded ? ( + + + + Statistics + + {refactTable !== null && ( + +
+ + + )} + + + ) : ( + + )} + + ); }; From 8456d04d56b20cc4532cee252f04e499d2b12839 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Fri, 16 Feb 2024 15:17:34 +0100 Subject: [PATCH 05/15] created components for table, changed type in locale to be default as in browser --- src/components/Chart/Chart.tsx | 2 +- src/components/Table/Table.module.css | 6 ++++-- src/components/Table/Table.tsx | 20 ++++++++++++-------- src/components/Table/TableCell.tsx | 11 +++++++++++ src/components/Table/TableRow.tsx | 6 ++++++ 5 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 src/components/Table/TableCell.tsx create mode 100644 src/components/Table/TableRow.tsx diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx index e3420173..8e1fd463 100644 --- a/src/components/Chart/Chart.tsx +++ b/src/components/Chart/Chart.tsx @@ -16,7 +16,7 @@ export const Chart: React.FC<{ const refactImpactDatesWeekly: RefactTableImpactDatesRow[] = refactTable.refact_impact_dates.data.weekly; const dates: string[] = Object.keys(refactImpactDatesWeekly).map((date) => { - return new Date(date).toLocaleString("en-US", { + return new Date(date).toLocaleString(undefined, { month: "short", day: "numeric", }); diff --git a/src/components/Table/Table.module.css b/src/components/Table/Table.module.css index 2d428062..6db1e7ec 100644 --- a/src/components/Table/Table.module.css +++ b/src/components/Table/Table.module.css @@ -5,8 +5,10 @@ width: 100%; table-layout: fixed; } -.table td, -.table th { +.td { border: 1px solid white; padding: 3px; } +.tableCellHead { + font-weight: bold; +} diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index fac8db0c..c01eddab 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -8,6 +8,8 @@ import { } from "../../services/refact"; import styles from "./Table.module.css"; import { Spinner } from "../Spinner"; +import { TableRow } from "./TableRow"; +import { TableCell } from "./TableCell"; export const Table: React.FC<{ refactTable: RefactTableData | null; @@ -59,35 +61,37 @@ export const Table: React.FC<{ return ( - Refact`'s impact by language + Refact's impact by language
- + {Object.values(convertedColumnNames).map( (columnName: string, idx: number) => ( - + + {columnName} + ), )} - + {refactImpactTable.map( (rowData: RefactTableImpactLanguagesRow, idx: number) => ( - + {Object.keys(convertedColumnNames).map( (columnName: string, idx: number) => ( - + ), )} - + ), )} diff --git a/src/components/Table/TableCell.tsx b/src/components/Table/TableCell.tsx new file mode 100644 index 00000000..7c5f5c29 --- /dev/null +++ b/src/components/Table/TableCell.tsx @@ -0,0 +1,11 @@ +import React from "react"; +import classNames from "classnames"; +import styles from "./Table.module.css"; + +export const TableCell: React.FC<{ + children: React.ReactNode; + className?: string; + key: string; +}> = (props) => ( + ; From caf68936459d4b5abe29aca81fcb6bdf0ceb3458 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Fri, 16 Feb 2024 15:33:51 +0100 Subject: [PATCH 06/15] moved defining data from components to parent component --- src/components/Chart/Chart.tsx | 14 +++++-------- src/components/Statistic/Statistic.tsx | 10 ++++++++-- src/components/Table/Table.tsx | 27 +++++++++++++------------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx index 8e1fd463..8d886108 100644 --- a/src/components/Chart/Chart.tsx +++ b/src/components/Chart/Chart.tsx @@ -1,20 +1,16 @@ import React from "react"; import { Box, Text } from "@radix-ui/themes"; -import { - RefactTableData, - RefactTableImpactDatesRow, -} from "../../services/refact"; +import { RefactTableImpactDatesRow } from "../../services/refact"; import ReactEcharts from "echarts-for-react"; import { Spinner } from "../Spinner"; export const Chart: React.FC<{ - refactTable: RefactTableData | null; -}> = ({ refactTable }) => { - if (refactTable === null) { + refactImpactDatesWeekly: RefactTableImpactDatesRow[] | null; +}> = ({ refactImpactDatesWeekly }) => { + if (refactImpactDatesWeekly === null) { return ; } - const refactImpactDatesWeekly: RefactTableImpactDatesRow[] = - refactTable.refact_impact_dates.data.weekly; + const dates: string[] = Object.keys(refactImpactDatesWeekly).map((date) => { return new Date(date).toLocaleString(undefined, { month: "short", diff --git a/src/components/Statistic/Statistic.tsx b/src/components/Statistic/Statistic.tsx index 0d0b079c..f09dd979 100644 --- a/src/components/Statistic/Statistic.tsx +++ b/src/components/Statistic/Statistic.tsx @@ -99,8 +99,14 @@ export const Statistic: React.FC<{ {refactTable !== null && ( -
{columnName}
+ {formatCellValue( columnName, rowData[ columnName as keyof RefactTableImpactLanguagesRow ], )} -
+); diff --git a/src/components/Table/TableRow.tsx b/src/components/Table/TableRow.tsx new file mode 100644 index 00000000..360d003f --- /dev/null +++ b/src/components/Table/TableRow.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import styles from "./Table.module.css"; + +export const TableRow: React.FC<{ children: React.ReactNode; key: string }> = ( + props, +) =>
- +
+ )} diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index c01eddab..fd179eab 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -4,29 +4,28 @@ import { FormatCellValue, ColumnName, RefactTableImpactLanguagesRow, - RefactTableData, } from "../../services/refact"; import styles from "./Table.module.css"; import { Spinner } from "../Spinner"; import { TableRow } from "./TableRow"; import { TableCell } from "./TableCell"; +const convertedColumnNames: Record = { + lang: "Lang.", + refact: "Refact", + human: "Human", + total: "Total", + refact_impact: "Refact Impact", + completions: "Compl.", +}; + export const Table: React.FC<{ - refactTable: RefactTableData | null; -}> = ({ refactTable }) => { - if (refactTable === null) { + refactImpactTable: RefactTableImpactLanguagesRow[] | null; +}> = ({ refactImpactTable }) => { + if (refactImpactTable === null) { return ; } - const refactImpactTable: RefactTableImpactLanguagesRow[] = - refactTable.table_refact_impact.data; - const convertedColumnNames: Record = { - lang: "Lang.", - refact: "Refact", - human: "Human", - total: "Total", - refact_impact: "Refact Impact", - completions: "Compl.", - }; + const formatCellValue: FormatCellValue = ( columnName: string, cellValue: string | number, From 979f547c710f12f7c5dedac50f0f4f0645923146 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Fri, 16 Feb 2024 15:43:45 +0100 Subject: [PATCH 07/15] fixed types --- src/components/Table/TableCell.tsx | 2 +- src/components/Table/TableRow.tsx | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/Table/TableCell.tsx b/src/components/Table/TableCell.tsx index 7c5f5c29..b0a79a39 100644 --- a/src/components/Table/TableCell.tsx +++ b/src/components/Table/TableCell.tsx @@ -5,7 +5,7 @@ import styles from "./Table.module.css"; export const TableCell: React.FC<{ children: React.ReactNode; className?: string; - key: string; + key: number; }> = (props) => ( ; +) => ; From aab39d156fe9a848fe01676040090949849c51c7 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Mon, 19 Feb 2024 12:08:07 +0100 Subject: [PATCH 08/15] added storybooks for table and plots --- src/components/Chart/Chart.stories.tsx | 94 ++++++++++++++++++++++++++ src/components/Chart/Chart.tsx | 4 +- src/components/Table/Table.stories.tsx | 62 +++++++++++++++++ src/services/refact.ts | 13 ++-- 4 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 src/components/Chart/Chart.stories.tsx create mode 100644 src/components/Table/Table.stories.tsx diff --git a/src/components/Chart/Chart.stories.tsx b/src/components/Chart/Chart.stories.tsx new file mode 100644 index 00000000..c408381b --- /dev/null +++ b/src/components/Chart/Chart.stories.tsx @@ -0,0 +1,94 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Chart } from "./Chart"; +import { Box } from "@radix-ui/themes"; + +const meta = { + title: "Chart", + component: Chart, + decorators: [ + (Story) => ( + + + + ), + ], + args: { + refactImpactDatesWeekly: { + "2023-12-15": { + completions: 14, + human: 52, + langs: [".py", ".rs"], + refact: 203, + refact_impact: 0.7960784435272217, + total: 255, + }, + "2023-12-22": { + completions: 219, + human: 2063, + langs: [".py", ".cpp"], + refact: 6149, + refact_impact: 0.7487822771072388, + total: 8212, + }, + "2023-12-27": { + completions: 15, + human: 30, + langs: [".py"], + refact: 480, + refact_impact: 0.9411764740943909, + total: 510, + }, + "2024-01-04": { + completions: 12, + human: 1772, + langs: [".rs"], + refact: 303, + refact_impact: 0.14602409303188324, + total: 2075, + }, + "2024-01-09": { + completions: 4, + human: 33, + langs: [".py"], + refact: 166, + refact_impact: 0.8341708779335022, + total: 199, + }, + "2024-01-24": { + completions: 107, + human: 10732, + langs: [".rs"], + refact: 3739, + refact_impact: 0.2583788335323334, + total: 14471, + }, + "2024-02-02": { + completions: 149, + human: 22550, + langs: [".rs", ".py", ".txt"], + refact: 5851, + refact_impact: 0.20601387321949005, + total: 28401, + }, + "2024-02-05": { + completions: 5, + human: 1976, + langs: [".rs", ".txt"], + refact: 233, + refact_impact: 0.10547759383916855, + total: 2209, + }, + }, + }, +} satisfies Meta; + +export default meta; + +export const Primary: StoryObj = {}; diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx index 8d886108..76382042 100644 --- a/src/components/Chart/Chart.tsx +++ b/src/components/Chart/Chart.tsx @@ -1,11 +1,11 @@ import React from "react"; import { Box, Text } from "@radix-ui/themes"; -import { RefactTableImpactDatesRow } from "../../services/refact"; +import { RefactTableImpactDateObj } from "../../services/refact"; import ReactEcharts from "echarts-for-react"; import { Spinner } from "../Spinner"; export const Chart: React.FC<{ - refactImpactDatesWeekly: RefactTableImpactDatesRow[] | null; + refactImpactDatesWeekly: Record | null; }> = ({ refactImpactDatesWeekly }) => { if (refactImpactDatesWeekly === null) { return ; diff --git a/src/components/Table/Table.stories.tsx b/src/components/Table/Table.stories.tsx new file mode 100644 index 00000000..cd9a31d1 --- /dev/null +++ b/src/components/Table/Table.stories.tsx @@ -0,0 +1,62 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Table } from "./Table"; +import { Box } from "@radix-ui/themes"; + +const meta = { + title: "Table", + component: Table, + decorators: [ + (Story) => ( + + + + ), + ], + args: { + refactImpactTable: [ + { + completions: 276, + human: 31996, + lang: ".rs", + refact: 10092, + refact_impact: 0.23978331685066223, + total: 42088, + }, + { + completions: 243, + human: 7110, + lang: ".py", + refact: 6929, + refact_impact: 0.49355366826057434, + total: 14039, + }, + { + completions: 6, + human: 4, + lang: ".cpp", + refact: 103, + refact_impact: 0.9626168012619019, + total: 107, + }, + { + completions: 0, + human: 98, + lang: ".txt", + refact: 0, + refact_impact: 0.0, + total: 98, + }, + ], + }, +} satisfies Meta; + +export default meta; + +export const Primary: StoryObj = {}; diff --git a/src/services/refact.ts b/src/services/refact.ts index 6502cce0..916d23f6 100644 --- a/src/services/refact.ts +++ b/src/services/refact.ts @@ -200,8 +200,13 @@ export type CapsResponse = { tokenizer_rewrite_path: Record; chat_rag_functions?: string[]; }; -export type RefactTableImpactDatesRow = { - [key in ColumnName]: number; +export type RefactTableImpactDateObj = { + completions: number; + human: number; + langs: string[]; + refact: number; + refact_impact: number; + total: number; }; export type RefactTableImpactLanguagesRow = { [key in ColumnName]: string | number; @@ -209,8 +214,8 @@ export type RefactTableImpactLanguagesRow = { export type RefactTableData = { refact_impact_dates: { data: { - daily: RefactTableImpactDatesRow[]; - weekly: RefactTableImpactDatesRow[]; + daily: Record; + weekly: Record; }; }; table_refact_impact: { From d9866852f250bb14dcb2582314b1d566c732bdcf Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Mon, 19 Feb 2024 12:24:50 +0100 Subject: [PATCH 09/15] moved defining useEventBus hook to a parent component --- src/components/Sidebar/Sidebar.tsx | 7 ++++++- src/components/Statistic/Statistic.tsx | 5 ++--- src/lib/render/RenderStatistic.tsx | 5 ++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 04c4185f..ab8d72e4 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -5,6 +5,7 @@ import styles from "./sidebar.module.css"; import { ChatHistory, type ChatHistoryProps } from "../ChatHistory"; import { Settings } from "./Settings"; import { Statistic } from "../Statistic/Statistic"; +import { useEventBusForChat } from "../../hooks"; export const Sidebar: React.FC< { @@ -12,6 +13,7 @@ export const Sidebar: React.FC< } & ChatHistoryProps > = ({ history, onHistoryItemClick, onCreateNewChat, onDeleteHistoryItem }) => { const [isOpenedStatistic, setIsOpenedStatistic] = useState(false); + const { backFromChat } = useEventBusForChat(); const handleCloseStatistic = () => { setIsOpenedStatistic(false); @@ -19,7 +21,10 @@ export const Sidebar: React.FC< return ( {isOpenedStatistic ? ( - + ) : ( void; -}> = ({ onCloseStatistic }) => { + backFromChat: () => void; +}> = ({ onCloseStatistic, backFromChat }) => { const [isLoaded, setIsLoaded] = useState(false); const [refactTable, setRefactTable] = useState(null); const { host, tabbed } = useConfig(); - const { backFromChat } = useEventBusForChat(); const LeftRightPadding: Responsive< "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" diff --git a/src/lib/render/RenderStatistic.tsx b/src/lib/render/RenderStatistic.tsx index 63ead16c..09f59b69 100644 --- a/src/lib/render/RenderStatistic.tsx +++ b/src/lib/render/RenderStatistic.tsx @@ -3,13 +3,16 @@ import { ConfigProvider, type Config } from "../../contexts/config-context.tsx"; import ReactDOM from "react-dom/client"; import { Theme } from "../../components/Theme"; import { Statistic } from "../../components/Statistic/Statistic"; +import { useEventBusForChat } from "../../hooks"; export function renderStatistic(element: HTMLElement, config: Config) { const StatisticTab: React.FC = (config) => { + const { backFromChat } = useEventBusForChat(); + return ( - + ); From 9cd68ace9121106e33d7099bbcaefd3b078713d1 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Mon, 19 Feb 2024 13:39:52 +0100 Subject: [PATCH 10/15] mocked useEventBusForChat in test --- src/features/HistorySideBar.test.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/features/HistorySideBar.test.tsx b/src/features/HistorySideBar.test.tsx index a475b9b0..916c052a 100644 --- a/src/features/HistorySideBar.test.tsx +++ b/src/features/HistorySideBar.test.tsx @@ -5,6 +5,12 @@ import { EVENT_NAMES_TO_CHAT } from "../events"; import { ChatHistoryItem } from "../hooks/useChatHistory"; +vi.mock("../hooks/useEventBusForChat", () => ({ + useEventBusForChat: () => ({ + backFromChat: vi.fn, + }), +})); + describe("HistorySideBar", () => { stubResizeObserver(); From 7ca23f17c65170474edf2b457c8e603482c07434 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Tue, 20 Feb 2024 13:14:43 +0100 Subject: [PATCH 11/15] moved stub table data to separate files. replaced imported ReactEcharts only with that components which are used here. fixed storybooks for chart and table because of error during build --- src/__fixtures__/index.ts | 1 + src/__fixtures__/table.ts | 3 + src/components/Chart/Chart.stories.tsx | 166 ++++++++++++------------- src/components/Chart/Chart.tsx | 23 +++- src/components/Statistic/Statistic.tsx | 9 +- src/components/Table/Table.stories.tsx | 102 ++++++++------- 6 files changed, 160 insertions(+), 144 deletions(-) create mode 100644 src/__fixtures__/table.ts diff --git a/src/__fixtures__/index.ts b/src/__fixtures__/index.ts index c9b0f6ec..cdfd1ed1 100644 --- a/src/__fixtures__/index.ts +++ b/src/__fixtures__/index.ts @@ -1,2 +1,3 @@ export { STUB_CAPS_RESPONSE } from "./caps"; export { MARS_ROVER_CHAT } from "./chat"; +export { TABLE } from "./table"; diff --git a/src/__fixtures__/table.ts b/src/__fixtures__/table.ts new file mode 100644 index 00000000..c141f8eb --- /dev/null +++ b/src/__fixtures__/table.ts @@ -0,0 +1,3 @@ +export const TABLE = { + data: '{"refact_impact_dates":{"data":{"daily":{"2023-12-15":{"completions":14,"human":52,"langs":[".rs",".py"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-18":{"completions":16,"human":83,"langs":[".py"],"refact":245,"refact_impact":0.7469512224197388,"total":328},"2023-12-19":{"completions":6,"human":4,"langs":[".cpp"],"refact":103,"refact_impact":0.9626168012619019,"total":107},"2023-12-20":{"completions":46,"human":857,"langs":[".py"],"refact":693,"refact_impact":0.4470967650413513,"total":1550},"2023-12-21":{"completions":92,"human":1157,"langs":[".py"],"refact":3103,"refact_impact":0.7284037470817566,"total":4260},"2023-12-22":{"completions":59,"human":-38,"langs":[".py"],"refact":2005,"refact_impact":1.0193188190460205,"total":1967},"2023-12-27":{"completions":13,"human":28,"langs":[".py"],"refact":409,"refact_impact":0.9359267950057983,"total":437},"2023-12-29":{"completions":2,"human":2,"langs":[".py"],"refact":71,"refact_impact":0.9726027250289917,"total":73},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":10,"human":808,"langs":[".rs"],"refact":410,"refact_impact":0.3366174101829529,"total":1218},"2024-01-25":{"completions":76,"human":7993,"langs":[".rs"],"refact":2772,"refact_impact":0.25750115513801575,"total":10765},"2024-01-26":{"completions":21,"human":1931,"langs":[".rs"],"refact":557,"refact_impact":0.22387459874153137,"total":2488},"2024-01-29":{"completions":21,"human":2574,"langs":[".rs"],"refact":655,"refact_impact":0.20284917950630188,"total":3229},"2024-01-30":{"completions":29,"human":1849,"langs":[".rs"],"refact":1310,"refact_impact":0.41468819975852966,"total":3159},"2024-01-31":{"completions":31,"human":3452,"langs":[".rs",".txt"],"refact":1114,"refact_impact":0.24397721886634827,"total":4566},"2024-02-01":{"completions":57,"human":8806,"langs":[".rs",".txt"],"refact":2465,"refact_impact":0.21870286762714386,"total":11271},"2024-02-02":{"completions":11,"human":5869,"langs":[".rs",".txt",".py"],"refact":307,"refact_impact":0.04970854893326759,"total":6176},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}},"weekly":{"2023-12-15":{"completions":14,"human":52,"langs":[".py",".rs"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-22":{"completions":219,"human":2063,"langs":[".py",".cpp"],"refact":6149,"refact_impact":0.7487822771072388,"total":8212},"2023-12-27":{"completions":15,"human":30,"langs":[".py"],"refact":480,"refact_impact":0.9411764740943909,"total":510},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":107,"human":10732,"langs":[".rs"],"refact":3739,"refact_impact":0.2583788335323334,"total":14471},"2024-02-02":{"completions":149,"human":22550,"langs":[".rs",".py",".txt"],"refact":5851,"refact_impact":0.20601387321949005,"total":28401},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}}}},"table_refact_impact":{"columns":["Language","Refact","Human","Total (characters)","Refact Impact","Completions"],"data":[{"completions":276,"human":31996,"lang":".rs","refact":10092,"refact_impact":0.23978331685066223,"total":42088},{"completions":243,"human":7110,"lang":".py","refact":6929,"refact_impact":0.49355366826057434,"total":14039},{"completions":6,"human":4,"lang":".cpp","refact":103,"refact_impact":0.9626168012619019,"total":107},{"completions":0,"human":98,"lang":".txt","refact":0,"refact_impact":0.0,"total":98}],"title":"Refact\'s impact by language"}}', +}; diff --git a/src/components/Chart/Chart.stories.tsx b/src/components/Chart/Chart.stories.tsx index c408381b..0a935c43 100644 --- a/src/components/Chart/Chart.stories.tsx +++ b/src/components/Chart/Chart.stories.tsx @@ -1,94 +1,92 @@ -import type { Meta, StoryObj } from "@storybook/react"; +import type { Meta } from "@storybook/react"; import { Chart } from "./Chart"; import { Box } from "@radix-ui/themes"; const meta = { title: "Chart", component: Chart, - decorators: [ - (Story) => ( - - - - ), - ], - args: { - refactImpactDatesWeekly: { - "2023-12-15": { - completions: 14, - human: 52, - langs: [".py", ".rs"], - refact: 203, - refact_impact: 0.7960784435272217, - total: 255, - }, - "2023-12-22": { - completions: 219, - human: 2063, - langs: [".py", ".cpp"], - refact: 6149, - refact_impact: 0.7487822771072388, - total: 8212, - }, - "2023-12-27": { - completions: 15, - human: 30, - langs: [".py"], - refact: 480, - refact_impact: 0.9411764740943909, - total: 510, - }, - "2024-01-04": { - completions: 12, - human: 1772, - langs: [".rs"], - refact: 303, - refact_impact: 0.14602409303188324, - total: 2075, - }, - "2024-01-09": { - completions: 4, - human: 33, - langs: [".py"], - refact: 166, - refact_impact: 0.8341708779335022, - total: 199, - }, - "2024-01-24": { - completions: 107, - human: 10732, - langs: [".rs"], - refact: 3739, - refact_impact: 0.2583788335323334, - total: 14471, - }, - "2024-02-02": { - completions: 149, - human: 22550, - langs: [".rs", ".py", ".txt"], - refact: 5851, - refact_impact: 0.20601387321949005, - total: 28401, - }, - "2024-02-05": { - completions: 5, - human: 1976, - langs: [".rs", ".txt"], - refact: 233, - refact_impact: 0.10547759383916855, - total: 2209, - }, - }, - }, } satisfies Meta; export default meta; -export const Primary: StoryObj = {}; +export const Primary = () => { + return ( + + + + ); +}; diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx index 76382042..afaf768a 100644 --- a/src/components/Chart/Chart.tsx +++ b/src/components/Chart/Chart.tsx @@ -1,8 +1,26 @@ import React from "react"; import { Box, Text } from "@radix-ui/themes"; import { RefactTableImpactDateObj } from "../../services/refact"; -import ReactEcharts from "echarts-for-react"; +import ReactEChartsCore from "echarts-for-react/lib/core"; +import * as echarts from "echarts/core"; +import { BarChart } from "echarts/charts"; +import { + GridComponent, + TooltipComponent, + AxisPointerComponent, + TitleComponent, +} from "echarts/components"; +import { CanvasRenderer } from "echarts/renderers"; + import { Spinner } from "../Spinner"; +echarts.use([ + TitleComponent, + TooltipComponent, + GridComponent, + BarChart, + CanvasRenderer, + AxisPointerComponent, +]); export const Chart: React.FC<{ refactImpactDatesWeekly: Record | null; @@ -76,7 +94,8 @@ export const Chart: React.FC<{ Refact vs Human - diff --git a/src/components/Statistic/Statistic.tsx b/src/components/Statistic/Statistic.tsx index 8ac2b049..102f3210 100644 --- a/src/components/Statistic/Statistic.tsx +++ b/src/components/Statistic/Statistic.tsx @@ -7,10 +7,7 @@ import { Spinner } from "../Spinner"; import { ArrowLeftIcon } from "@radix-ui/react-icons"; import { useConfig } from "../../contexts/config-context"; import { ScrollArea } from "../ScrollArea"; - -const table: { data: string } = { - data: '{"refact_impact_dates":{"data":{"daily":{"2023-12-15":{"completions":14,"human":52,"langs":[".rs",".py"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-18":{"completions":16,"human":83,"langs":[".py"],"refact":245,"refact_impact":0.7469512224197388,"total":328},"2023-12-19":{"completions":6,"human":4,"langs":[".cpp"],"refact":103,"refact_impact":0.9626168012619019,"total":107},"2023-12-20":{"completions":46,"human":857,"langs":[".py"],"refact":693,"refact_impact":0.4470967650413513,"total":1550},"2023-12-21":{"completions":92,"human":1157,"langs":[".py"],"refact":3103,"refact_impact":0.7284037470817566,"total":4260},"2023-12-22":{"completions":59,"human":-38,"langs":[".py"],"refact":2005,"refact_impact":1.0193188190460205,"total":1967},"2023-12-27":{"completions":13,"human":28,"langs":[".py"],"refact":409,"refact_impact":0.9359267950057983,"total":437},"2023-12-29":{"completions":2,"human":2,"langs":[".py"],"refact":71,"refact_impact":0.9726027250289917,"total":73},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":10,"human":808,"langs":[".rs"],"refact":410,"refact_impact":0.3366174101829529,"total":1218},"2024-01-25":{"completions":76,"human":7993,"langs":[".rs"],"refact":2772,"refact_impact":0.25750115513801575,"total":10765},"2024-01-26":{"completions":21,"human":1931,"langs":[".rs"],"refact":557,"refact_impact":0.22387459874153137,"total":2488},"2024-01-29":{"completions":21,"human":2574,"langs":[".rs"],"refact":655,"refact_impact":0.20284917950630188,"total":3229},"2024-01-30":{"completions":29,"human":1849,"langs":[".rs"],"refact":1310,"refact_impact":0.41468819975852966,"total":3159},"2024-01-31":{"completions":31,"human":3452,"langs":[".rs",".txt"],"refact":1114,"refact_impact":0.24397721886634827,"total":4566},"2024-02-01":{"completions":57,"human":8806,"langs":[".rs",".txt"],"refact":2465,"refact_impact":0.21870286762714386,"total":11271},"2024-02-02":{"completions":11,"human":5869,"langs":[".rs",".txt",".py"],"refact":307,"refact_impact":0.04970854893326759,"total":6176},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}},"weekly":{"2023-12-15":{"completions":14,"human":52,"langs":[".py",".rs"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-22":{"completions":219,"human":2063,"langs":[".py",".cpp"],"refact":6149,"refact_impact":0.7487822771072388,"total":8212},"2023-12-27":{"completions":15,"human":30,"langs":[".py"],"refact":480,"refact_impact":0.9411764740943909,"total":510},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":107,"human":10732,"langs":[".rs"],"refact":3739,"refact_impact":0.2583788335323334,"total":14471},"2024-02-02":{"completions":149,"human":22550,"langs":[".rs",".py",".txt"],"refact":5851,"refact_impact":0.20601387321949005,"total":28401},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}}}},"table_refact_impact":{"columns":["Language","Refact","Human","Total (characters)","Refact Impact","Completions"],"data":[{"completions":276,"human":31996,"lang":".rs","refact":10092,"refact_impact":0.23978331685066223,"total":42088},{"completions":243,"human":7110,"lang":".py","refact":6929,"refact_impact":0.49355366826057434,"total":14039},{"completions":6,"human":4,"lang":".cpp","refact":103,"refact_impact":0.9626168012619019,"total":107},{"completions":0,"human":98,"lang":".txt","refact":0,"refact_impact":0.0,"total":98}],"title":"Refact\'s impact by language"}}', -}; +import { TABLE } from "../../__fixtures__"; export const Statistic: React.FC<{ onCloseStatistic?: () => void; @@ -41,8 +38,8 @@ export const Statistic: React.FC<{ }; useEffect(() => { - if (table.data) { - setRefactTable(JSON.parse(table.data) as RefactTableData); + if (TABLE.data) { + setRefactTable(JSON.parse(TABLE.data) as RefactTableData); setIsLoaded(true); } }, []); diff --git a/src/components/Table/Table.stories.tsx b/src/components/Table/Table.stories.tsx index cd9a31d1..6f1d8ef6 100644 --- a/src/components/Table/Table.stories.tsx +++ b/src/components/Table/Table.stories.tsx @@ -1,62 +1,60 @@ -import type { Meta, StoryObj } from "@storybook/react"; +import type { Meta } from "@storybook/react"; import { Table } from "./Table"; import { Box } from "@radix-ui/themes"; const meta = { title: "Table", component: Table, - decorators: [ - (Story) => ( - - - - ), - ], - args: { - refactImpactTable: [ - { - completions: 276, - human: 31996, - lang: ".rs", - refact: 10092, - refact_impact: 0.23978331685066223, - total: 42088, - }, - { - completions: 243, - human: 7110, - lang: ".py", - refact: 6929, - refact_impact: 0.49355366826057434, - total: 14039, - }, - { - completions: 6, - human: 4, - lang: ".cpp", - refact: 103, - refact_impact: 0.9626168012619019, - total: 107, - }, - { - completions: 0, - human: 98, - lang: ".txt", - refact: 0, - refact_impact: 0.0, - total: 98, - }, - ], - }, } satisfies Meta; export default meta; -export const Primary: StoryObj = {}; +export const Primary = () => { + return ( + +
); diff --git a/src/components/Table/TableRow.tsx b/src/components/Table/TableRow.tsx index 360d003f..4e653c6e 100644 --- a/src/components/Table/TableRow.tsx +++ b/src/components/Table/TableRow.tsx @@ -1,6 +1,5 @@ import React from "react"; -import styles from "./Table.module.css"; -export const TableRow: React.FC<{ children: React.ReactNode; key: string }> = ( +export const TableRow: React.FC<{ children: React.ReactNode; key?: number }> = ( props, -) =>
+ + ); +}; From f799b42390253a614ecf0eebf2d96ace8dd74eb9 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Wed, 21 Feb 2024 15:35:00 +0100 Subject: [PATCH 12/15] created eventBus for statistic --- src/components/Sidebar/Sidebar.tsx | 8 +------- src/components/Statistic/Statistic.tsx | 7 +++---- src/events/index.ts | 1 + src/events/statistic.ts | 3 +++ src/features/HistorySideBar.test.tsx | 7 ------- src/hooks/index.ts | 1 + src/hooks/useEventBusForStatistic.ts | 16 ++++++++++++++++ src/lib/render/RenderStatistic.tsx | 6 +++--- 8 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 src/events/statistic.ts create mode 100644 src/hooks/useEventBusForStatistic.ts diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index ab8d72e4..358ce2eb 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -5,7 +5,6 @@ import styles from "./sidebar.module.css"; import { ChatHistory, type ChatHistoryProps } from "../ChatHistory"; import { Settings } from "./Settings"; import { Statistic } from "../Statistic/Statistic"; -import { useEventBusForChat } from "../../hooks"; export const Sidebar: React.FC< { @@ -13,18 +12,13 @@ export const Sidebar: React.FC< } & ChatHistoryProps > = ({ history, onHistoryItemClick, onCreateNewChat, onDeleteHistoryItem }) => { const [isOpenedStatistic, setIsOpenedStatistic] = useState(false); - const { backFromChat } = useEventBusForChat(); - const handleCloseStatistic = () => { setIsOpenedStatistic(false); }; return ( {isOpenedStatistic ? ( - + ) : ( void; - backFromChat: () => void; -}> = ({ onCloseStatistic, backFromChat }) => { + backFromStatistic?: () => void; +}> = ({ onCloseStatistic, backFromStatistic }) => { const [isLoaded, setIsLoaded] = useState(false); const [refactTable, setRefactTable] = useState(null); const { host, tabbed } = useConfig(); - const LeftRightPadding: Responsive< "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" > = @@ -58,7 +57,7 @@ export const Statistic: React.FC<{ > {host === "vscode" && !tabbed ? ( - diff --git a/src/events/index.ts b/src/events/index.ts index 5a536b62..1f1c322e 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -1,3 +1,4 @@ export * from "./chat"; export type * from "../services/refact"; export * from "./sidebar"; +export * from "./statistic"; diff --git a/src/events/statistic.ts b/src/events/statistic.ts new file mode 100644 index 00000000..30c7f967 --- /dev/null +++ b/src/events/statistic.ts @@ -0,0 +1,3 @@ +export enum EVENT_NAMES_FROM_STATISTIC { + BACK_FROM_STATISTIC = "back_from_statistic", +} diff --git a/src/features/HistorySideBar.test.tsx b/src/features/HistorySideBar.test.tsx index 916c052a..0204fbae 100644 --- a/src/features/HistorySideBar.test.tsx +++ b/src/features/HistorySideBar.test.tsx @@ -2,15 +2,8 @@ import { expect, vi, describe, it } from "vitest"; import { render, stubResizeObserver } from "../utils/test-utils"; import { HistorySideBar } from "./HistorySideBar"; import { EVENT_NAMES_TO_CHAT } from "../events"; - import { ChatHistoryItem } from "../hooks/useChatHistory"; -vi.mock("../hooks/useEventBusForChat", () => ({ - useEventBusForChat: () => ({ - backFromChat: vi.fn, - }), -})); - describe("HistorySideBar", () => { stubResizeObserver(); diff --git a/src/hooks/index.ts b/src/hooks/index.ts index fe5c7595..a59f4dff 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -5,3 +5,4 @@ export * from "./useIsOnline"; export * from "./useOnPressedEnter"; export * from "./useEventBusForSidebar"; export * from "./useApiKey"; +export * from "./useEventBusForStatistic"; diff --git a/src/hooks/useEventBusForStatistic.ts b/src/hooks/useEventBusForStatistic.ts new file mode 100644 index 00000000..d6a8650c --- /dev/null +++ b/src/hooks/useEventBusForStatistic.ts @@ -0,0 +1,16 @@ +import { EVENT_NAMES_FROM_STATISTIC } from "../events"; +import { usePostMessage } from "./usePostMessage"; + +export const useEventBusForStatistic = () => { + const postMessage = usePostMessage(); + + function backFromStatistic() { + postMessage({ + type: EVENT_NAMES_FROM_STATISTIC.BACK_FROM_STATISTIC, + }); + } + + return { + backFromStatistic, + }; +}; diff --git a/src/lib/render/RenderStatistic.tsx b/src/lib/render/RenderStatistic.tsx index 09f59b69..0f97626f 100644 --- a/src/lib/render/RenderStatistic.tsx +++ b/src/lib/render/RenderStatistic.tsx @@ -3,16 +3,16 @@ import { ConfigProvider, type Config } from "../../contexts/config-context.tsx"; import ReactDOM from "react-dom/client"; import { Theme } from "../../components/Theme"; import { Statistic } from "../../components/Statistic/Statistic"; -import { useEventBusForChat } from "../../hooks"; +import { useEventBusForStatistic } from "../../hooks"; export function renderStatistic(element: HTMLElement, config: Config) { const StatisticTab: React.FC = (config) => { - const { backFromChat } = useEventBusForChat(); + const { backFromStatistic } = useEventBusForStatistic(); return ( - + ); From d16a2fe39caea45c45d287681d720eed814066a5 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Thu, 22 Feb 2024 00:28:21 +0100 Subject: [PATCH 13/15] saved the the parsed json for table data, moved Statistic to features, fixed func formatCellValue and moved it to separate file --- src/__fixtures__/table.ts | 273 +++++++++++++++++- src/components/Chart/Chart.tsx | 1 - src/components/Sidebar/Sidebar.tsx | 2 +- src/components/Table/Table.tsx | 35 +-- src/components/Table/formatCellValue.test.tsx | 25 ++ src/components/Table/formatTableCell.ts | 33 +++ .../Statistic => features}/Statistic.tsx | 19 +- src/lib/render/RenderStatistic.tsx | 7 +- 8 files changed, 345 insertions(+), 50 deletions(-) create mode 100644 src/components/Table/formatCellValue.test.tsx create mode 100644 src/components/Table/formatTableCell.ts rename src/{components/Statistic => features}/Statistic.tsx (85%) diff --git a/src/__fixtures__/table.ts b/src/__fixtures__/table.ts index c141f8eb..fddbb136 100644 --- a/src/__fixtures__/table.ts +++ b/src/__fixtures__/table.ts @@ -1,3 +1,274 @@ +const json = { + refact_impact_dates: { + data: { + daily: { + "2023-12-15": { + completions: 14, + human: 52, + langs: [".rs", ".py"], + refact: 203, + refact_impact: 0.7960784435272217, + total: 255, + }, + "2023-12-18": { + completions: 16, + human: 83, + langs: [".py"], + refact: 245, + refact_impact: 0.7469512224197388, + total: 328, + }, + "2023-12-19": { + completions: 6, + human: 4, + langs: [".cpp"], + refact: 103, + refact_impact: 0.9626168012619019, + total: 107, + }, + "2023-12-20": { + completions: 46, + human: 857, + langs: [".py"], + refact: 693, + refact_impact: 0.4470967650413513, + total: 1550, + }, + "2023-12-21": { + completions: 92, + human: 1157, + langs: [".py"], + refact: 3103, + refact_impact: 0.7284037470817566, + total: 4260, + }, + "2023-12-22": { + completions: 59, + human: -38, + langs: [".py"], + refact: 2005, + refact_impact: 1.0193188190460205, + total: 1967, + }, + "2023-12-27": { + completions: 13, + human: 28, + langs: [".py"], + refact: 409, + refact_impact: 0.9359267950057983, + total: 437, + }, + "2023-12-29": { + completions: 2, + human: 2, + langs: [".py"], + refact: 71, + refact_impact: 0.9726027250289917, + total: 73, + }, + "2024-01-04": { + completions: 12, + human: 1772, + langs: [".rs"], + refact: 303, + refact_impact: 0.14602409303188324, + total: 2075, + }, + "2024-01-09": { + completions: 4, + human: 33, + langs: [".py"], + refact: 166, + refact_impact: 0.8341708779335022, + total: 199, + }, + "2024-01-24": { + completions: 10, + human: 808, + langs: [".rs"], + refact: 410, + refact_impact: 0.3366174101829529, + total: 1218, + }, + "2024-01-25": { + completions: 76, + human: 7993, + langs: [".rs"], + refact: 2772, + refact_impact: 0.25750115513801575, + total: 10765, + }, + "2024-01-26": { + completions: 21, + human: 1931, + langs: [".rs"], + refact: 557, + refact_impact: 0.22387459874153137, + total: 2488, + }, + "2024-01-29": { + completions: 21, + human: 2574, + langs: [".rs"], + refact: 655, + refact_impact: 0.20284917950630188, + total: 3229, + }, + "2024-01-30": { + completions: 29, + human: 1849, + langs: [".rs"], + refact: 1310, + refact_impact: 0.41468819975852966, + total: 3159, + }, + "2024-01-31": { + completions: 31, + human: 3452, + langs: [".rs", ".txt"], + refact: 1114, + refact_impact: 0.24397721886634827, + total: 4566, + }, + "2024-02-01": { + completions: 57, + human: 8806, + langs: [".rs", ".txt"], + refact: 2465, + refact_impact: 0.21870286762714386, + total: 11271, + }, + "2024-02-02": { + completions: 11, + human: 5869, + langs: [".rs", ".txt", ".py"], + refact: 307, + refact_impact: 0.04970854893326759, + total: 6176, + }, + "2024-02-05": { + completions: 5, + human: 1976, + langs: [".rs", ".txt"], + refact: 233, + refact_impact: 0.10547759383916855, + total: 2209, + }, + }, + weekly: { + "2023-12-15": { + completions: 14, + human: 52, + langs: [".py", ".rs"], + refact: 203, + refact_impact: 0.7960784435272217, + total: 255, + }, + "2023-12-22": { + completions: 219, + human: 2063, + langs: [".py", ".cpp"], + refact: 6149, + refact_impact: 0.7487822771072388, + total: 8212, + }, + "2023-12-27": { + completions: 15, + human: 30, + langs: [".py"], + refact: 480, + refact_impact: 0.9411764740943909, + total: 510, + }, + "2024-01-04": { + completions: 12, + human: 1772, + langs: [".rs"], + refact: 303, + refact_impact: 0.14602409303188324, + total: 2075, + }, + "2024-01-09": { + completions: 4, + human: 33, + langs: [".py"], + refact: 166, + refact_impact: 0.8341708779335022, + total: 199, + }, + "2024-01-24": { + completions: 107, + human: 10732, + langs: [".rs"], + refact: 3739, + refact_impact: 0.2583788335323334, + total: 14471, + }, + "2024-02-02": { + completions: 149, + human: 22550, + langs: [".rs", ".py", ".txt"], + refact: 5851, + refact_impact: 0.20601387321949005, + total: 28401, + }, + "2024-02-05": { + completions: 5, + human: 1976, + langs: [".rs", ".txt"], + refact: 233, + refact_impact: 0.10547759383916855, + total: 2209, + }, + }, + }, + }, + table_refact_impact: { + columns: [ + "Language", + "Refact", + "Human", + "Total (characters)", + "Refact Impact", + "Completions", + ], + data: [ + { + completions: 276, + human: 31996, + lang: ".rs", + refact: 10092, + refact_impact: 0.23978331685066223, + total: 42088, + }, + { + completions: 243, + human: 7110, + lang: ".py", + refact: 6929, + refact_impact: 0.49355366826057434, + total: 14039, + }, + { + completions: 6, + human: 4, + lang: ".cpp", + refact: 103, + refact_impact: 0.9626168012619019, + total: 107, + }, + { + completions: 0, + human: 98, + lang: ".txt", + refact: 0, + refact_impact: 0.0, + total: 98, + }, + ], + title: "Refact's impact by language", + }, +}; export const TABLE = { - data: '{"refact_impact_dates":{"data":{"daily":{"2023-12-15":{"completions":14,"human":52,"langs":[".rs",".py"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-18":{"completions":16,"human":83,"langs":[".py"],"refact":245,"refact_impact":0.7469512224197388,"total":328},"2023-12-19":{"completions":6,"human":4,"langs":[".cpp"],"refact":103,"refact_impact":0.9626168012619019,"total":107},"2023-12-20":{"completions":46,"human":857,"langs":[".py"],"refact":693,"refact_impact":0.4470967650413513,"total":1550},"2023-12-21":{"completions":92,"human":1157,"langs":[".py"],"refact":3103,"refact_impact":0.7284037470817566,"total":4260},"2023-12-22":{"completions":59,"human":-38,"langs":[".py"],"refact":2005,"refact_impact":1.0193188190460205,"total":1967},"2023-12-27":{"completions":13,"human":28,"langs":[".py"],"refact":409,"refact_impact":0.9359267950057983,"total":437},"2023-12-29":{"completions":2,"human":2,"langs":[".py"],"refact":71,"refact_impact":0.9726027250289917,"total":73},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":10,"human":808,"langs":[".rs"],"refact":410,"refact_impact":0.3366174101829529,"total":1218},"2024-01-25":{"completions":76,"human":7993,"langs":[".rs"],"refact":2772,"refact_impact":0.25750115513801575,"total":10765},"2024-01-26":{"completions":21,"human":1931,"langs":[".rs"],"refact":557,"refact_impact":0.22387459874153137,"total":2488},"2024-01-29":{"completions":21,"human":2574,"langs":[".rs"],"refact":655,"refact_impact":0.20284917950630188,"total":3229},"2024-01-30":{"completions":29,"human":1849,"langs":[".rs"],"refact":1310,"refact_impact":0.41468819975852966,"total":3159},"2024-01-31":{"completions":31,"human":3452,"langs":[".rs",".txt"],"refact":1114,"refact_impact":0.24397721886634827,"total":4566},"2024-02-01":{"completions":57,"human":8806,"langs":[".rs",".txt"],"refact":2465,"refact_impact":0.21870286762714386,"total":11271},"2024-02-02":{"completions":11,"human":5869,"langs":[".rs",".txt",".py"],"refact":307,"refact_impact":0.04970854893326759,"total":6176},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}},"weekly":{"2023-12-15":{"completions":14,"human":52,"langs":[".py",".rs"],"refact":203,"refact_impact":0.7960784435272217,"total":255},"2023-12-22":{"completions":219,"human":2063,"langs":[".py",".cpp"],"refact":6149,"refact_impact":0.7487822771072388,"total":8212},"2023-12-27":{"completions":15,"human":30,"langs":[".py"],"refact":480,"refact_impact":0.9411764740943909,"total":510},"2024-01-04":{"completions":12,"human":1772,"langs":[".rs"],"refact":303,"refact_impact":0.14602409303188324,"total":2075},"2024-01-09":{"completions":4,"human":33,"langs":[".py"],"refact":166,"refact_impact":0.8341708779335022,"total":199},"2024-01-24":{"completions":107,"human":10732,"langs":[".rs"],"refact":3739,"refact_impact":0.2583788335323334,"total":14471},"2024-02-02":{"completions":149,"human":22550,"langs":[".rs",".py",".txt"],"refact":5851,"refact_impact":0.20601387321949005,"total":28401},"2024-02-05":{"completions":5,"human":1976,"langs":[".rs",".txt"],"refact":233,"refact_impact":0.10547759383916855,"total":2209}}}},"table_refact_impact":{"columns":["Language","Refact","Human","Total (characters)","Refact Impact","Completions"],"data":[{"completions":276,"human":31996,"lang":".rs","refact":10092,"refact_impact":0.23978331685066223,"total":42088},{"completions":243,"human":7110,"lang":".py","refact":6929,"refact_impact":0.49355366826057434,"total":14039},{"completions":6,"human":4,"lang":".cpp","refact":103,"refact_impact":0.9626168012619019,"total":107},{"completions":0,"human":98,"lang":".txt","refact":0,"refact_impact":0.0,"total":98}],"title":"Refact\'s impact by language"}}', + data: JSON.stringify(json), }; diff --git a/src/components/Chart/Chart.tsx b/src/components/Chart/Chart.tsx index afaf768a..5a977af9 100644 --- a/src/components/Chart/Chart.tsx +++ b/src/components/Chart/Chart.tsx @@ -49,7 +49,6 @@ export const Chart: React.FC<{ type: "shadow", }, }, - legend: {}, height: "200px", grid: { left: "3%", diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 358ce2eb..83ea9510 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -4,7 +4,7 @@ import { BarChartIcon } from "@radix-ui/react-icons"; import styles from "./sidebar.module.css"; import { ChatHistory, type ChatHistoryProps } from "../ChatHistory"; import { Settings } from "./Settings"; -import { Statistic } from "../Statistic/Statistic"; +import { Statistic } from "../../features/Statistic"; export const Sidebar: React.FC< { diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index fd179eab..079d8215 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -1,7 +1,6 @@ import React from "react"; import { Box, Text } from "@radix-ui/themes"; import { - FormatCellValue, ColumnName, RefactTableImpactLanguagesRow, } from "../../services/refact"; @@ -9,6 +8,7 @@ import styles from "./Table.module.css"; import { Spinner } from "../Spinner"; import { TableRow } from "./TableRow"; import { TableCell } from "./TableCell"; +import { formatTableCell } from "./formatTableCell"; const convertedColumnNames: Record = { lang: "Lang.", @@ -26,37 +26,6 @@ export const Table: React.FC<{ return ; } - const formatCellValue: FormatCellValue = ( - columnName: string, - cellValue: string | number, - ): string | number => { - if (columnName === "refact_impact") { - return cellValue === 0 - ? cellValue - : parseFloat(cellValue.toString()).toFixed(2); - } else if (columnName === "lang" || columnName === "completions") { - return cellValue; - } else { - const convertedNumber = Number( - cellValue - .toLocaleString("en-US", { - style: "decimal", - maximumFractionDigits: 0, - minimumFractionDigits: 0, - useGrouping: true, - }) - .replace(",", "."), - ); - if (convertedNumber === 0) { - return "0"; - } else if (Number.isInteger(convertedNumber)) { - return convertedNumber + "k"; - } else { - return `${convertedNumber.toFixed(2)}k`; - } - } - }; - return ( @@ -81,7 +50,7 @@ export const Table: React.FC<{ {Object.keys(convertedColumnNames).map( (columnName: string, idx: number) => ( - {formatCellValue( + {formatTableCell( columnName, rowData[ columnName as keyof RefactTableImpactLanguagesRow diff --git a/src/components/Table/formatCellValue.test.tsx b/src/components/Table/formatCellValue.test.tsx new file mode 100644 index 00000000..05c8c75f --- /dev/null +++ b/src/components/Table/formatCellValue.test.tsx @@ -0,0 +1,25 @@ +import { describe, test, expect } from "vitest"; +import { formatCellNumber } from "./formatTableCell"; + +describe("formatCellValue", () => { + test.each<[number | string, string]>([ + ["0", "0"], + ["10", "10"], + ["100", "100"], + ["1000", "1k"], + ["10000", "10k"], + ["564731", "564.73k"], + ["100000", "100k"], + ["1000000", "1M"], + [0, "0"], + [10, "10"], + [100, "100"], + [1000, "1k"], + [10000, "10k"], + [564731, "564.73k"], + [100000, "100k"], + [1000000, "1M"], + ])("returns %s for %s", (cellValue, expected) => { + expect(formatCellNumber(cellValue)).toEqual(expected); + }); +}); diff --git a/src/components/Table/formatTableCell.ts b/src/components/Table/formatTableCell.ts new file mode 100644 index 00000000..39b77f99 --- /dev/null +++ b/src/components/Table/formatTableCell.ts @@ -0,0 +1,33 @@ +import { FormatCellValue } from "../../services/refact"; + +function convertNumber(value: number): number { + return Number.isInteger(value) ? value : +value.toFixed(2); +} +export const formatCellNumber = (cellValue: number | string): string => { + cellValue = Number(cellValue); + + if (cellValue >= 1e6) { + const roundedNumber = cellValue / 1e6; + return `${convertNumber(roundedNumber)}M`; + } else if (cellValue < 1e3) { + return `${cellValue}`; + } else { + const roundedNumber = cellValue / 1000; // 1.06002 + return `${convertNumber(roundedNumber)}k`; + } +}; + +export const formatTableCell: FormatCellValue = ( + columnName: string, + cellValue: string | number, +): string | number => { + if (columnName === "refact_impact") { + return cellValue === 0 + ? cellValue + : parseFloat(cellValue.toString()).toFixed(2); + } else if (columnName === "lang" || columnName === "completions") { + return cellValue; + } else { + return formatCellNumber(cellValue); + } +}; diff --git a/src/components/Statistic/Statistic.tsx b/src/features/Statistic.tsx similarity index 85% rename from src/components/Statistic/Statistic.tsx rename to src/features/Statistic.tsx index 77216dd6..fbf41c9c 100644 --- a/src/components/Statistic/Statistic.tsx +++ b/src/features/Statistic.tsx @@ -1,21 +1,22 @@ import React, { useEffect, useState } from "react"; import { Box, Flex, Button, Heading, Responsive } from "@radix-ui/themes"; -import { RefactTableData } from "../../services/refact"; -import { Table } from "../Table/Table"; -import { Chart } from "../Chart/Chart"; -import { Spinner } from "../Spinner"; +import { RefactTableData } from "../services/refact"; +import { Table } from "../components/Table/Table"; +import { Chart } from "../components/Chart/Chart"; +import { Spinner } from "../components/Spinner"; import { ArrowLeftIcon } from "@radix-ui/react-icons"; -import { useConfig } from "../../contexts/config-context"; -import { ScrollArea } from "../ScrollArea"; -import { TABLE } from "../../__fixtures__"; +import { useConfig } from "../contexts/config-context"; +import { ScrollArea } from "../components/ScrollArea"; +import { TABLE } from "../__fixtures__"; +import { useEventBusForStatistic } from "../hooks"; export const Statistic: React.FC<{ onCloseStatistic?: () => void; - backFromStatistic?: () => void; -}> = ({ onCloseStatistic, backFromStatistic }) => { +}> = ({ onCloseStatistic }) => { const [isLoaded, setIsLoaded] = useState(false); const [refactTable, setRefactTable] = useState(null); const { host, tabbed } = useConfig(); + const { backFromStatistic } = useEventBusForStatistic(); const LeftRightPadding: Responsive< "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" > = diff --git a/src/lib/render/RenderStatistic.tsx b/src/lib/render/RenderStatistic.tsx index 0f97626f..e6f3ff92 100644 --- a/src/lib/render/RenderStatistic.tsx +++ b/src/lib/render/RenderStatistic.tsx @@ -2,17 +2,14 @@ import React from "react"; import { ConfigProvider, type Config } from "../../contexts/config-context.tsx"; import ReactDOM from "react-dom/client"; import { Theme } from "../../components/Theme"; -import { Statistic } from "../../components/Statistic/Statistic"; -import { useEventBusForStatistic } from "../../hooks"; +import { Statistic } from "../../features/Statistic"; export function renderStatistic(element: HTMLElement, config: Config) { const StatisticTab: React.FC = (config) => { - const { backFromStatistic } = useEventBusForStatistic(); - return ( - + ); From ca14457559943d0ec81edda2bdbf56c1df0c325c Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Thu, 22 Feb 2024 00:30:12 +0100 Subject: [PATCH 14/15] changed name of test-file --- .../Table/{formatCellValue.test.tsx => formatTableCell.test.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/components/Table/{formatCellValue.test.tsx => formatTableCell.test.tsx} (100%) diff --git a/src/components/Table/formatCellValue.test.tsx b/src/components/Table/formatTableCell.test.tsx similarity index 100% rename from src/components/Table/formatCellValue.test.tsx rename to src/components/Table/formatTableCell.test.tsx From f4809ef41eed0b68fae813d79a9a0157d4164a77 Mon Sep 17 00:00:00 2001 From: Viktoriia Date: Thu, 22 Feb 2024 12:23:49 +0100 Subject: [PATCH 15/15] created feature-flag for statistic --- src/components/Sidebar/Sidebar.tsx | 19 ++++++++++++------- src/contexts/config-context.tsx | 8 +++++++- src/main.tsx | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/components/Sidebar/Sidebar.tsx b/src/components/Sidebar/Sidebar.tsx index 83ea9510..0d22ba06 100644 --- a/src/components/Sidebar/Sidebar.tsx +++ b/src/components/Sidebar/Sidebar.tsx @@ -5,6 +5,7 @@ import styles from "./sidebar.module.css"; import { ChatHistory, type ChatHistoryProps } from "../ChatHistory"; import { Settings } from "./Settings"; import { Statistic } from "../../features/Statistic"; +import { useConfig } from "../../contexts/config-context"; export const Sidebar: React.FC< { @@ -15,6 +16,8 @@ export const Sidebar: React.FC< const handleCloseStatistic = () => { setIsOpenedStatistic(false); }; + const { features } = useConfig(); + return ( {isOpenedStatistic ? ( @@ -47,13 +50,15 @@ export const Sidebar: React.FC< /> - setIsOpenedStatistic(true)} - > - - + {features.statistics && ( + setIsOpenedStatistic(true)} + > + + + )} )} diff --git a/src/contexts/config-context.tsx b/src/contexts/config-context.tsx index fa9a6dc3..08fe9a24 100644 --- a/src/contexts/config-context.tsx +++ b/src/contexts/config-context.tsx @@ -8,9 +8,15 @@ export type Config = { lspUrl?: string; dev?: boolean; themeProps?: ThemeProps; + features: { + statistics: boolean; + }; }; -const ConfigContext = createContext({ host: "web" }); +const ConfigContext = createContext({ + host: "web", + features: { statistics: false }, +}); // TODO: add theme props, and configure vscode to grey const ConfigProvider: React.FC<{ diff --git a/src/main.tsx b/src/main.tsx index 871e945d..3d4a6209 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,5 +7,5 @@ import { render } from "./lib"; const element = document.getElementById("refact-chat"); if (element) { - render(element, { host: "web" }); + render(element, { host: "web", features: { statistics: false } }); }