[WEB-4855] refactor: chart tick improvements (#7732)

* 🚧 WIP: Introduced customTicks prop in BarChart for flexible tick rendering.

*  feat: added customTicks to axis charts for flexible tick rendering

* 🔧 fix: update default bar fill color to black and ensure consistent color usage in BarChart

*  feat: add customTooltipContent prop to LineChart for enhanced tooltip flexibility

* 🔧 fix: update bar fill color handling to support dynamic colors based on data and removed DEFAULT_BAR_FILL_COLOR

* 🔧 fix: correct bar fill color handling in BarChart to ensure proper color assignment for tooltips

* 🔧 fix: update customTicks prop types in TAxisChartProps to use unknown type for better type safety

* 📝 chore: updated translations and cleaned up insight card

* 🚨 fix: lint

* 🔧 fix: remove unused translation key "no_of" from Russian translations
This commit is contained in:
Jayash Tripathy 2025-09-09 23:51:13 +05:30 committed by GitHub
parent 498613284e
commit 43b7a6ad0a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 115 additions and 93 deletions

View file

@ -1,28 +1,17 @@
// plane package imports // plane package imports
import React, { useMemo } from "react"; import React from "react";
import { IAnalyticsResponseFields } from "@plane/types"; import { IAnalyticsResponseFields } from "@plane/types";
import { Loader } from "@plane/ui"; import { Loader } from "@plane/ui";
// components
import TrendPiece from "./trend-piece";
export type InsightCardProps = { export type InsightCardProps = {
data?: IAnalyticsResponseFields; data?: IAnalyticsResponseFields;
label: string; label: string;
isLoading?: boolean; isLoading?: boolean;
versus?: string | null;
}; };
const InsightCard = (props: InsightCardProps) => { const InsightCard = (props: InsightCardProps) => {
const { data, label, isLoading, versus } = props; const { data, label, isLoading = false } = props;
const { count, filter_count } = data || {}; const count = data?.count ?? 0;
const percentage = useMemo(() => {
if (count != null && filter_count != null) {
const result = ((count - filter_count) / count) * 100;
const isFiniteAndNotNaNOrZero = Number.isFinite(result) && !Number.isNaN(result) && result !== 0;
return isFiniteAndNotNaNOrZero ? result : null;
}
return null;
}, [count, filter_count]);
return ( return (
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
@ -30,12 +19,6 @@ const InsightCard = (props: InsightCardProps) => {
{!isLoading ? ( {!isLoading ? (
<div className="flex flex-col gap-1"> <div className="flex flex-col gap-1">
<div className="text-2xl font-bold text-custom-text-100">{count}</div> <div className="text-2xl font-bold text-custom-text-100">{count}</div>
{/* {percentage && (
<div className="flex gap-1 text-xs text-custom-text-300">
<TrendPiece percentage={percentage} size="xs" />
{versus && <div>vs {versus}</div>}
</div>
)} */}
</div> </div>
) : ( ) : (
<Loader.Item height="50px" width="100%" /> <Loader.Item height="50px" width="100%" />

View file

@ -92,7 +92,6 @@ const TotalInsights: React.FC<{
isLoading={isLoading} isLoading={isLoading}
data={totalInsightsData?.[item.key]} data={totalInsightsData?.[item.key]}
label={getInsightLabel(analyticsType, item, isEpic, t)} label={getInsightLabel(analyticsType, item, isEpic, t)}
versus={selectedDurationLabel}
/> />
))} ))}
</div> </div>

View file

@ -882,7 +882,8 @@
"in_progress": "Probíhá", "in_progress": "Probíhá",
"planned": "Plánováno", "planned": "Plánováno",
"paused": "Pozastaveno", "paused": "Pozastaveno",
"no_of": "Počet {entity}" "no_of": "Počet {entity}",
"resolved": "Vyřešeno"
}, },
"chart": { "chart": {
"x_axis": "Osa X", "x_axis": "Osa X",
@ -2490,7 +2491,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane se nespustil. To může být způsobeno tím, že se jeden nebo více služeb Plane nepodařilo spustit.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane se nespustil. To může být způsobeno tím, že se jeden nebo více služeb Plane nepodařilo spustit.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Vyberte View Logs z setup.sh a Docker logů, abyste si byli jisti." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Vyberte View Logs z setup.sh a Docker logů, abyste si byli jisti."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -882,7 +882,8 @@
"in_progress": "In Bearbeitung", "in_progress": "In Bearbeitung",
"planned": "Geplant", "planned": "Geplant",
"paused": "Pausiert", "paused": "Pausiert",
"no_of": "Anzahl {entity}" "no_of": "Anzahl {entity}",
"resolved": "Gelöst"
}, },
"chart": { "chart": {
"x_axis": "X-Achse", "x_axis": "X-Achse",
@ -2489,7 +2490,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane ist nicht gestartet. Dies könnte daran liegen, dass einer oder mehrere Plane-Services nicht starten konnten.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane ist nicht gestartet. Dies könnte daran liegen, dass einer oder mehrere Plane-Services nicht starten konnten.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Wählen Sie View Logs aus setup.sh und Docker-Logs, um sicherzugehen." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Wählen Sie View Logs aus setup.sh und Docker-Logs, um sicherzugehen."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -725,7 +725,8 @@
"apply": "Apply", "apply": "Apply",
"applying": "Applying", "applying": "Applying",
"overview": "Overview", "overview": "Overview",
"no_of": "No. of {entity}" "no_of": "No. of {entity}",
"resolved": "Resolved"
}, },
"chart": { "chart": {
"x_axis": "X-axis", "x_axis": "X-axis",
@ -2366,7 +2367,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane didn't start up. This could be because one or more Plane services failed to start.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane didn't start up. This could be because one or more Plane services failed to start.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Choose View Logs from setup.sh and Docker logs to be sure." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Choose View Logs from setup.sh and Docker logs to be sure."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -885,7 +885,8 @@
"in_progress": "En progreso", "in_progress": "En progreso",
"planned": "Planificado", "planned": "Planificado",
"paused": "Pausado", "paused": "Pausado",
"no_of": "N.º de {entity}" "no_of": "N.º de {entity}",
"resolved": "Resuelto"
}, },
"chart": { "chart": {
"x_axis": "Eje X", "x_axis": "Eje X",
@ -2492,7 +2493,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane no se inició. Esto podría deberse a que uno o más servicios de Plane fallaron al iniciar.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane no se inició. Esto podría deberse a que uno o más servicios de Plane fallaron al iniciar.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Selecciona View Logs desde setup.sh y los logs de Docker para estar seguro." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Selecciona View Logs desde setup.sh y los logs de Docker para estar seguro."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -883,7 +883,8 @@
"in_progress": "En cours", "in_progress": "En cours",
"planned": "Planifié", "planned": "Planifié",
"paused": "En pause", "paused": "En pause",
"no_of": "Nº de {entity}" "no_of": "Nº de {entity}",
"resolved": "Résolu"
}, },
"chart": { "chart": {
"x_axis": "Axe X", "x_axis": "Axe X",
@ -2490,7 +2491,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane n&apos;a pas démarré. Cela pourrait être dû au fait qu&apos;un ou plusieurs services Plane ont échoué à démarrer.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane n&apos;a pas démarré. Cela pourrait être dû au fait qu&apos;un ou plusieurs services Plane ont échoué à démarrer.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Choisissez View Logs depuis setup.sh et les logs Docker pour en être sûr." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Choisissez View Logs depuis setup.sh et les logs Docker pour en être sûr."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -882,7 +882,8 @@
"in_progress": "Sedang berlangsung", "in_progress": "Sedang berlangsung",
"planned": "Direncanakan", "planned": "Direncanakan",
"paused": "Dijedaikan", "paused": "Dijedaikan",
"no_of": "Jumlah {entity}" "no_of": "Jumlah {entity}",
"resolved": "Terselesaikan"
}, },
"chart": { "chart": {
"x_axis": "Sumbu-X", "x_axis": "Sumbu-X",
@ -2485,7 +2486,6 @@
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Pilih View Logs dari setup.sh dan log Docker untuk memastikan." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Pilih View Logs dari setup.sh dan log Docker untuk memastikan."
}, },
"no_of": "Jumlah {entity}", "no_of": "Jumlah {entity}",
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -881,7 +881,8 @@
"in_progress": "In corso", "in_progress": "In corso",
"planned": "Pianificato", "planned": "Pianificato",
"paused": "In pausa", "paused": "In pausa",
"no_of": "N. di {entity}" "no_of": "N. di {entity}",
"resolved": "Risolto"
}, },
"chart": { "chart": {
"x_axis": "Asse X", "x_axis": "Asse X",
@ -2489,7 +2490,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane non si è avviato. Questo potrebbe essere dovuto al fatto che uno o più servizi Plane non sono riusciti ad avviarsi.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane non si è avviato. Questo potrebbe essere dovuto al fatto che uno o più servizi Plane non sono riusciti ad avviarsi.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Scegli View Logs da setup.sh e dai log Docker per essere sicuro." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Scegli View Logs da setup.sh e dai log Docker per essere sicuro."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -883,7 +883,8 @@
"in_progress": "進行中", "in_progress": "進行中",
"planned": "計画済み", "planned": "計画済み",
"paused": "一時停止", "paused": "一時停止",
"no_of": "{entity} の数" "no_of": "{entity} の数",
"resolved": "解決済み"
}, },
"chart": { "chart": {
"x_axis": "エックス アクシス", "x_axis": "エックス アクシス",
@ -2490,7 +2491,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Planeが起動しませんでした。これは1つまたは複数のPlaneサービスの起動に失敗したことが原因である可能性があります。", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Planeが起動しませんでした。これは1つまたは複数のPlaneサービスの起動に失敗したことが原因である可能性があります。",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "setup.shとDockerログからView Logsを選択して確認してください。" "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "setup.shとDockerログからView Logsを選択して確認してください。"
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"in_progress": "진행 중", "in_progress": "진행 중",
"planned": "계획된", "planned": "계획된",
"paused": "일시 중지됨", "paused": "일시 중지됨",
"no_of": "{entity} 수" "no_of": "{entity} 수",
"resolved": "해결됨"
}, },
"chart": { "chart": {
"x_axis": "X축", "x_axis": "X축",
@ -2492,7 +2493,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane이 시작되지 않았습니다. 이는 하나 이상의 Plane 서비스가 시작에 실패했기 때문일 수 있습니다.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane이 시작되지 않았습니다. 이는 하나 이상의 Plane 서비스가 시작에 실패했기 때문일 수 있습니다.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "확실히 하려면 setup.sh와 Docker 로그에서 View Logs를 선택하세요." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "확실히 하려면 setup.sh와 Docker 로그에서 View Logs를 선택하세요."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"in_progress": "W trakcie", "in_progress": "W trakcie",
"planned": "Zaplanowane", "planned": "Zaplanowane",
"paused": "Wstrzymane", "paused": "Wstrzymane",
"no_of": "Liczba {entity}" "no_of": "Liczba {entity}",
"resolved": "Rozwiązane"
}, },
"chart": { "chart": {
"x_axis": "Oś X", "x_axis": "Oś X",
@ -2491,7 +2492,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane nie uruchomił się. Może to być spowodowane tym, że jedna lub więcej usług Plane nie mogła się uruchomić.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane nie uruchomił się. Może to być spowodowane tym, że jedna lub więcej usług Plane nie mogła się uruchomić.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Wybierz View Logs z setup.sh i logów Docker, aby mieć pewność." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Wybierz View Logs z setup.sh i logów Docker, aby mieć pewność."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"in_progress": "Em andamento", "in_progress": "Em andamento",
"planned": "Planejado", "planned": "Planejado",
"paused": "Pausado", "paused": "Pausado",
"no_of": "Nº de {entity}" "no_of": "Nº de {entity}",
"resolved": "Resolvido"
}, },
"chart": { "chart": {
"x_axis": "Eixo X", "x_axis": "Eixo X",
@ -2486,7 +2487,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "O Plane não inicializou. Isso pode ser porque um ou mais serviços do Plane falharam ao iniciar.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "O Plane não inicializou. Isso pode ser porque um ou mais serviços do Plane falharam ao iniciar.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Escolha View Logs do setup.sh e logs do Docker para ter certeza." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Escolha View Logs do setup.sh e logs do Docker para ter certeza."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -882,7 +882,8 @@
"in_progress": "În desfășurare", "in_progress": "În desfășurare",
"planned": "Planificat", "planned": "Planificat",
"paused": "Pauzat", "paused": "Pauzat",
"no_of": "Nr. de {entity}" "no_of": "Nr. de {entity}",
"resolved": "Rezolvat"
}, },
"chart": { "chart": {
"x_axis": "axa-X", "x_axis": "axa-X",
@ -2484,7 +2485,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane nu a pornit. Aceasta ar putea fi din cauza că unul sau mai multe servicii Plane au eșuat să pornească.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane nu a pornit. Aceasta ar putea fi din cauza că unul sau mai multe servicii Plane au eșuat să pornească.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Alegeți View Logs din setup.sh și logurile Docker pentru a fi siguri." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Alegeți View Logs din setup.sh și logurile Docker pentru a fi siguri."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"in_progress": "В процессе", "in_progress": "В процессе",
"planned": "Запланировано", "planned": "Запланировано",
"paused": "На паузе", "paused": "На паузе",
"no_of": "Количество {entity}" "no_of": "Количество {entity}",
"resolved": "Решено"
}, },
"chart": { "chart": {
"x_axis": "Ось X", "x_axis": "Ось X",
@ -2492,8 +2493,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane не запустился. Это может быть из-за того, что один или несколько сервисов Plane не смогли запуститься.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane не запустился. Это может быть из-за того, что один или несколько сервисов Plane не смогли запуститься.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Выберите View Logs из setup.sh и логов Docker, чтобы убедиться." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Выберите View Logs из setup.sh и логов Docker, чтобы убедиться."
}, },
"no_of": "Количество {entity}",
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"in_progress": "Prebieha", "in_progress": "Prebieha",
"planned": "Plánované", "planned": "Plánované",
"paused": "Pozastavené", "paused": "Pozastavené",
"no_of": "Počet {entity}" "no_of": "Počet {entity}",
"resolved": "Vyriešené"
}, },
"chart": { "chart": {
"x_axis": "Os X", "x_axis": "Os X",
@ -2491,7 +2492,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane sa nespustil. Toto môže byť spôsobené tým, že sa jedna alebo viac služieb Plane nepodarilo spustiť.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane sa nespustil. Toto môže byť spôsobené tým, že sa jedna alebo viac služieb Plane nepodarilo spustiť.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Vyberte View Logs z setup.sh a Docker logov, aby ste si boli istí." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Vyberte View Logs z setup.sh a Docker logov, aby ste si boli istí."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -886,7 +886,8 @@
"in_progress": "Devam ediyor", "in_progress": "Devam ediyor",
"planned": "Planlandı", "planned": "Planlandı",
"paused": "Durduruldu", "paused": "Durduruldu",
"no_of": "{entity} sayısı" "no_of": "{entity} sayısı",
"resolved": "Çözüldü"
}, },
"chart": { "chart": {
"x_axis": "X ekseni", "x_axis": "X ekseni",
@ -2471,7 +2472,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane başlatılamadı. Bu, bir veya daha fazla Plane servisinin başlatılamaması nedeniyle olabilir.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane başlatılamadı. Bu, bir veya daha fazla Plane servisinin başlatılamaması nedeniyle olabilir.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Emin olmak için setup.sh ve Docker loglarından View Logs&apos;u seçin." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Emin olmak için setup.sh ve Docker loglarından View Logs&apos;u seçin."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"in_progress": "В процесі", "in_progress": "В процесі",
"planned": "Заплановано", "planned": "Заплановано",
"paused": "Призупинено", "paused": "Призупинено",
"no_of": "Кількість {entity}" "no_of": "Кількість {entity}",
"resolved": "Вирішено"
}, },
"chart": { "chart": {
"x_axis": "Вісь X", "x_axis": "Вісь X",
@ -2491,7 +2492,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane не запустився. Це може бути через те, що один або декілька сервісів Plane не змогли запуститися.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane не запустився. Це може бути через те, що один або декілька сервісів Plane не змогли запуститися.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Виберіть View Logs з setup.sh та логів Docker, щоб переконатися." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Виберіть View Logs з setup.sh та логів Docker, щоб переконатися."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -883,7 +883,8 @@
"in_progress": "Đang tiến hành", "in_progress": "Đang tiến hành",
"planned": "Đã lên kế hoạch", "planned": "Đã lên kế hoạch",
"paused": "Tạm dừng", "paused": "Tạm dừng",
"no_of": "Số lượng {entity}" "no_of": "Số lượng {entity}",
"resolved": "Đã giải quyết"
}, },
"chart": { "chart": {
"x_axis": "Trục X", "x_axis": "Trục X",
@ -2489,7 +2490,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane không khởi động được. Điều này có thể do một hoặc nhiều dịch vụ Plane không khởi động được.", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane không khởi động được. Điều này có thể do một hoặc nhiều dịch vụ Plane không khởi động được.",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Chọn View Logs từ setup.sh và log Docker để chắc chắn." "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "Chọn View Logs từ setup.sh và log Docker để chắc chắn."
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -883,7 +883,8 @@
"in_progress": "进行中", "in_progress": "进行中",
"planned": "已计划", "planned": "已计划",
"paused": "暂停", "paused": "暂停",
"no_of": "{entity} 的数量" "no_of": "{entity} 的数量",
"resolved": "已解决"
}, },
"chart": { "chart": {
"x_axis": "X轴", "x_axis": "X轴",
@ -2471,7 +2472,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane 未能启动。这可能是因为一个或多个 Plane 服务启动失败。", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane 未能启动。这可能是因为一个或多个 Plane 服务启动失败。",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "请选择“查看日志”来查看 setup.sh 和 Docker 日志,以确认问题。" "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "请选择“查看日志”来查看 setup.sh 和 Docker 日志,以确认问题。"
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -884,7 +884,8 @@
"planned": "已計劃", "planned": "已計劃",
"paused": "暫停", "paused": "暫停",
"at_risk": "有風險", "at_risk": "有風險",
"no_of": "{entity} 的數量" "no_of": "{entity} 的數量",
"resolved": "已解決"
}, },
"chart": { "chart": {
"x_axis": "X 軸", "x_axis": "X 軸",
@ -2492,7 +2493,6 @@
"plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane 未能啟動。這可能是因為一個或多個 Plane 服務啟動失敗。", "plane_didnt_start_up_this_could_be_because_one_or_more_plane_services_failed_to_start": "Plane 未能啟動。這可能是因為一個或多個 Plane 服務啟動失敗。",
"choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "從 setup.sh 和 Docker 日誌中選擇 View Logs 來確認。" "choose_view_logs_from_setup_sh_and_docker_logs_to_be_sure": "從 setup.sh 和 Docker 日誌中選擇 View Logs 來確認。"
}, },
"page_navigation_pane": { "page_navigation_pane": {
"tabs": { "tabs": {
"outline": { "outline": {

View file

@ -23,6 +23,7 @@ export const AreaChart = React.memo(<K extends string, T extends string>(props:
x: undefined, x: undefined,
y: 10, y: 10,
}, },
customTicks,
showTooltip = true, showTooltip = true,
comparisonLine, comparisonLine,
} = props; } = props;
@ -114,7 +115,10 @@ export const AreaChart = React.memo(<K extends string, T extends string>(props:
<CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} /> <CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} />
<XAxis <XAxis
dataKey={xAxis.key} dataKey={xAxis.key}
tick={(props) => <CustomXAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.x || CustomXAxisTick;
return <TickComponent {...props} />;
}}
tickLine={false} tickLine={false}
axisLine={false} axisLine={false}
label={ label={
@ -140,7 +144,10 @@ export const AreaChart = React.memo(<K extends string, T extends string>(props:
className: AXIS_LABEL_CLASSNAME, className: AXIS_LABEL_CLASSNAME,
} }
} }
tick={(props) => <CustomYAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.y || CustomYAxisTick;
return <TickComponent {...props} />;
}}
tickCount={tickCount.y} tickCount={tickCount.y}
allowDecimals={!!yAxis.allowDecimals} allowDecimals={!!yAxis.allowDecimals}
/> />

View file

@ -35,6 +35,7 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
x: undefined, x: undefined,
y: 10, y: 10,
}, },
customTicks,
showTooltip = true, showTooltip = true,
customTooltipContent, customTooltipContent,
} = props; } = props;
@ -52,7 +53,7 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
keys.push(bar.key); keys.push(bar.key);
labels[bar.key] = bar.label; labels[bar.key] = bar.label;
// For tooltip, we need a string color. If fill is a function, use a default color // For tooltip, we need a string color. If fill is a function, use a default color
colors[bar.key] = typeof bar.fill === "function" ? "#000000" : bar.fill; colors[bar.key] = typeof bar.fill === "function" ? bar.fill({}) : bar.fill;
} }
return { stackKeys: keys, stackLabels: labels, stackDotColors: colors }; return { stackKeys: keys, stackLabels: labels, stackDotColors: colors };
@ -65,6 +66,7 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
key={bar.key} key={bar.key}
dataKey={bar.key} dataKey={bar.key}
stackId={bar.stackId} stackId={bar.stackId}
fill={typeof bar.fill === "function" ? bar.fill({}) : bar.fill}
opacity={!!activeLegend && activeLegend !== bar.key ? 0.1 : 1} opacity={!!activeLegend && activeLegend !== bar.key ? 0.1 : 1}
shape={(shapeProps: any) => { shape={(shapeProps: any) => {
const shapeVariant = barShapeVariants[bar.shapeVariant ?? "bar"]; const shapeVariant = barShapeVariants[bar.shapeVariant ?? "bar"];
@ -96,7 +98,10 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
<CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} /> <CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} />
<XAxis <XAxis
dataKey={xAxis.key} dataKey={xAxis.key}
tick={(props) => <CustomXAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.x || CustomXAxisTick;
return <TickComponent {...props} />;
}}
tickLine={false} tickLine={false}
axisLine={false} axisLine={false}
label={{ label={{
@ -118,7 +123,10 @@ export const BarChart = React.memo(<K extends string, T extends string>(props: T
dx: yAxis.dx ?? -16, dx: yAxis.dx ?? -16,
className: AXIS_LABEL_CLASSNAME, className: AXIS_LABEL_CLASSNAME,
}} }}
tick={(props) => <CustomYAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.y || CustomYAxisTick;
return <TickComponent {...props} />;
}}
tickCount={tickCount.y} tickCount={tickCount.y}
allowDecimals={!!yAxis.allowDecimals} allowDecimals={!!yAxis.allowDecimals}
/> />

View file

@ -32,8 +32,10 @@ export const LineChart = React.memo(<K extends string, T extends string>(props:
x: undefined, x: undefined,
y: 10, y: 10,
}, },
customTicks,
legend, legend,
showTooltip = true, showTooltip = true,
customTooltipContent,
} = props; } = props;
// states // states
const [activeLine, setActiveLine] = useState<string | null>(null); const [activeLine, setActiveLine] = useState<string | null>(null);
@ -100,7 +102,10 @@ export const LineChart = React.memo(<K extends string, T extends string>(props:
<CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} /> <CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} />
<XAxis <XAxis
dataKey={xAxis.key} dataKey={xAxis.key}
tick={(props) => <CustomXAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.x || CustomXAxisTick;
return <TickComponent {...props} />;
}}
tickLine={false} tickLine={false}
axisLine={false} axisLine={false}
label={ label={
@ -126,7 +131,10 @@ export const LineChart = React.memo(<K extends string, T extends string>(props:
className: AXIS_LABEL_CLASSNAME, className: AXIS_LABEL_CLASSNAME,
} }
} }
tick={(props) => <CustomYAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.y || CustomYAxisTick;
return <TickComponent {...props} />;
}}
tickCount={tickCount.y} tickCount={tickCount.y}
allowDecimals={!!yAxis.allowDecimals} allowDecimals={!!yAxis.allowDecimals}
/> />
@ -148,17 +156,20 @@ export const LineChart = React.memo(<K extends string, T extends string>(props:
wrapperStyle={{ wrapperStyle={{
pointerEvents: "auto", pointerEvents: "auto",
}} }}
content={({ active, label, payload }) => ( content={({ active, label, payload }) => {
<CustomTooltip if (customTooltipContent) return customTooltipContent({ active, label, payload });
active={active} return (
activeKey={activeLine} <CustomTooltip
label={label} active={active}
payload={payload} activeKey={activeLine}
itemKeys={itemKeys} label={label}
itemLabels={itemLabels} payload={payload}
itemDotColors={itemDotColors} itemKeys={itemKeys}
/> itemLabels={itemLabels}
)} itemDotColors={itemDotColors}
/>
);
}}
/> />
)} )}
{renderLines} {renderLines}

View file

@ -28,6 +28,7 @@ export const ScatterChart = React.memo(<K extends string, T extends string>(prop
xAxis, xAxis,
yAxis, yAxis,
className, className,
customTicks,
tickCount = { tickCount = {
x: undefined, x: undefined,
y: 10, y: 10,
@ -85,7 +86,10 @@ export const ScatterChart = React.memo(<K extends string, T extends string>(prop
<CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} /> <CartesianGrid stroke="rgba(var(--color-border-100), 0.8)" vertical={false} />
<XAxis <XAxis
dataKey={xAxis.key} dataKey={xAxis.key}
tick={(props) => <CustomXAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.x || CustomXAxisTick;
return <TickComponent {...props} />;
}}
tickLine={false} tickLine={false}
axisLine={false} axisLine={false}
label={ label={
@ -111,7 +115,10 @@ export const ScatterChart = React.memo(<K extends string, T extends string>(prop
className: AXIS_LABEL_CLASSNAME, className: AXIS_LABEL_CLASSNAME,
} }
} }
tick={(props) => <CustomYAxisTick {...props} />} tick={(props) => {
const TickComponent = customTicks?.y || CustomYAxisTick;
return <TickComponent {...props} />;
}}
tickCount={tickCount.y} tickCount={tickCount.y}
allowDecimals={!!yAxis.allowDecimals} allowDecimals={!!yAxis.allowDecimals}
/> />

View file

@ -21,8 +21,17 @@ export type TChartData<K extends string, T extends string> = {
[key in K]: string | number; [key in K]: string | number;
} & Record<T, any>; } & Record<T, any>;
export type TChartProps<K extends string, T extends string> = { export type TBaseChartProps<K extends string, T extends string> = {
data: TChartData<K, T>[]; data: TChartData<K, T>[];
className?: string;
legend?: TChartLegend;
margin?: TChartMargin;
showTooltip?: boolean;
customTooltipContent?: (props: { active?: boolean; label: string; payload: any }) => React.ReactNode;
};
// Props specific to charts with X and Y axes
export type TAxisChartProps<K extends string, T extends string> = TBaseChartProps<K, T> & {
xAxis: { xAxis: {
key: keyof TChartData<K, T>; key: keyof TChartData<K, T>;
label?: string; label?: string;
@ -38,15 +47,14 @@ export type TChartProps<K extends string, T extends string> = {
offset?: number; offset?: number;
dx?: number; dx?: number;
}; };
className?: string;
legend?: TChartLegend;
margin?: TChartMargin;
tickCount?: { tickCount?: {
x?: number; x?: number;
y?: number; y?: number;
}; };
showTooltip?: boolean; customTicks?: {
customTooltipContent?: (props: { active?: boolean; label: string; payload: any }) => React.ReactNode; x?: React.ComponentType<unknown>;
y?: React.ComponentType<unknown>;
};
}; };
// ============================================================ // ============================================================
@ -67,7 +75,7 @@ export type TBarItem<T extends string> = {
shapeVariant?: TBarChartShapeVariant; shapeVariant?: TBarChartShapeVariant;
}; };
export type TBarChartProps<K extends string, T extends string> = TChartProps<K, T> & { export type TBarChartProps<K extends string, T extends string> = TAxisChartProps<K, T> & {
bars: TBarItem<T>[]; bars: TBarItem<T>[];
barSize?: number; barSize?: number;
}; };
@ -87,7 +95,7 @@ export type TLineItem<T extends string> = {
style?: Record<string, string | number>; style?: Record<string, string | number>;
}; };
export type TLineChartProps<K extends string, T extends string> = TChartProps<K, T> & { export type TLineChartProps<K extends string, T extends string> = TAxisChartProps<K, T> & {
lines: TLineItem<T>[]; lines: TLineItem<T>[];
}; };
@ -102,7 +110,7 @@ export type TScatterPointItem<T extends string> = {
stroke: string; stroke: string;
}; };
export type TScatterChartProps<K extends string, T extends string> = TChartProps<K, T> & { export type TScatterChartProps<K extends string, T extends string> = TAxisChartProps<K, T> & {
scatterPoints: TScatterPointItem<T>[]; scatterPoints: TScatterPointItem<T>[];
}; };
@ -123,7 +131,7 @@ export type TAreaItem<T extends string> = {
style?: Record<string, string | number>; style?: Record<string, string | number>;
}; };
export type TAreaChartProps<K extends string, T extends string> = TChartProps<K, T> & { export type TAreaChartProps<K extends string, T extends string> = TAxisChartProps<K, T> & {
areas: TAreaItem<T>[]; areas: TAreaItem<T>[];
comparisonLine?: { comparisonLine?: {
dashedLine: boolean; dashedLine: boolean;
@ -141,7 +149,7 @@ export type TCellItem<T extends string> = {
}; };
export type TPieChartProps<K extends string, T extends string> = Pick< export type TPieChartProps<K extends string, T extends string> = Pick<
TChartProps<K, T>, TBaseChartProps<K, T>,
"className" | "data" | "showTooltip" | "legend" | "margin" "className" | "data" | "showTooltip" | "legend" | "margin"
> & { > & {
dataKey: T; dataKey: T;
@ -223,7 +231,7 @@ export type TRadarItem<T extends string> = {
}; };
export type TRadarChartProps<K extends string, T extends string> = Pick< export type TRadarChartProps<K extends string, T extends string> = Pick<
TChartProps<K, T>, TBaseChartProps<K, T>,
"className" | "showTooltip" | "margin" | "data" | "legend" "className" | "showTooltip" | "margin" | "data" | "legend"
> & { > & {
dataKey: T; dataKey: T;