From b821a84c4e3fdb24598121570ec9be3d7376c69a Mon Sep 17 00:00:00 2001 From: Felix Mosheev <9304194+felixmosh@users.noreply.github.com> Date: Wed, 23 Oct 2024 19:42:09 +0300 Subject: [PATCH] feat: refactor styles and some behavior of dashboard queue filter --- .../StatusLegend/StatusLegend.module.css | 89 ++++++++++--------- .../components/StatusLegend/StatusLegend.tsx | 24 ++--- .../StatusMenu/StatusMenu.module.css | 2 +- packages/ui/src/hooks/useSelectedStatuses.ts | 4 +- packages/ui/src/index.css | 6 +- .../OverviewPage/OverviewPage.module.css | 15 ++++ .../src/pages/OverviewPage/OverviewPage.tsx | 42 ++++++--- .../ui/src/static/locales/en-US/messages.json | 3 +- .../ui/src/static/locales/es-ES/messages.json | 11 ++- .../ui/src/static/locales/fr-FR/messages.json | 3 +- .../ui/src/static/locales/pt-BR/messages.json | 3 +- .../ui/src/static/locales/zh-CN/messages.json | 3 +- packages/ui/src/utils/links.ts | 9 +- 13 files changed, 135 insertions(+), 79 deletions(-) diff --git a/packages/ui/src/components/StatusLegend/StatusLegend.module.css b/packages/ui/src/components/StatusLegend/StatusLegend.module.css index dfe647d2a..45eb9eade 100644 --- a/packages/ui/src/components/StatusLegend/StatusLegend.module.css +++ b/packages/ui/src/components/StatusLegend/StatusLegend.module.css @@ -4,57 +4,58 @@ padding: 0; margin: 0; text-transform: uppercase; -} + gap: 2em; -.legend > li { - display: flex; - align-items: center; - border-bottom: 2px solid transparent; -} + > li { + display: flex; + align-items: center; -.legend > li.isSelected { - border-color: var(--status-menu-active-border); - color: var(--status-menu-active-text); - font-weight: 500; -} + &:before { + content: ''; + background-color: var(--item-bg); + border-radius: 50%; + width: 0.5rem; + height: 0.5rem; + display: inline-block; + margin-right: 0.5rem; + } -.legend > li > a { - text-decoration: none; - margin: 0 0 -2px; - padding: 0.5em 1em; - color: var(--status-menu-text); - transition: border-bottom-color 200ms ease-in-out, color 0.1s ease; - display: flex; - align-items: center; -} + > a { + text-decoration: none; + margin: 0 0 -2px; + padding: 0.5em 0; + color: var(--status-menu-text); + transition: border-bottom-color 200ms ease-in-out, color 0.1s ease; + display: flex; + align-items: center; + border-bottom: 2px solid transparent; -.legend > li > a:before { - content: ''; - background-color: var(--item-bg); - border-radius: 50%; - width: 0.5rem; - height: 0.5rem; - display: inline-block; - margin-right: 0.5rem; -} + &:hover, + &:active { + border-color: var(--status-menu-hover-text); + } -.legend > li > a span { - flex: 1; - white-space: nowrap; -} + &.active { + border-color: var(--status-menu-active-border); + color: var(--status-menu-active-text); + font-weight: 500; + } -.legend > li > a span:before { - display: block; - content: attr(title); - font-weight: 600; - height: 0; - overflow: hidden; - visibility: hidden; -} + > span { + flex: 1; + white-space: nowrap; -.legend > li > a:hover, -.legend > li > a:active { - border-color: #7a8085; + &:before { + display: block; + content: attr(title); + font-weight: 600; + height: 0; + overflow: hidden; + visibility: hidden; + } + } + } + } } .waiting { diff --git a/packages/ui/src/components/StatusLegend/StatusLegend.tsx b/packages/ui/src/components/StatusLegend/StatusLegend.tsx index 4383aaf8b..27f567e63 100644 --- a/packages/ui/src/components/StatusLegend/StatusLegend.tsx +++ b/packages/ui/src/components/StatusLegend/StatusLegend.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { queueStatsStatusList } from '../../constants/queue-stats-status'; +import { links } from '../../utils/links'; import s from './StatusLegend.module.css'; import { NavLink } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { toCamelCase } from '../../utils/toCamelCase'; -import cn from 'clsx'; import { useQuery } from '../../hooks/useQuery'; export const StatusLegend = () => { @@ -15,17 +15,19 @@ export const StatusLegend = () => { ); diff --git a/packages/ui/src/components/StatusMenu/StatusMenu.module.css b/packages/ui/src/components/StatusMenu/StatusMenu.module.css index 02b0c1df4..b30048d38 100644 --- a/packages/ui/src/components/StatusMenu/StatusMenu.module.css +++ b/packages/ui/src/components/StatusMenu/StatusMenu.module.css @@ -31,7 +31,7 @@ .statusMenu > a:hover, .statusMenu > a:active { - border-color: #7a8085; + border-color: var(--status-menu-hover-text); } .statusMenu > a.active { diff --git a/packages/ui/src/hooks/useSelectedStatuses.ts b/packages/ui/src/hooks/useSelectedStatuses.ts index c974ca1ca..015bd7a68 100644 --- a/packages/ui/src/hooks/useSelectedStatuses.ts +++ b/packages/ui/src/hooks/useSelectedStatuses.ts @@ -19,7 +19,9 @@ export function useSelectedStatuses(): SelectedStatuses { useEffect(() => { const status = getActiveStatus(search); - setSelectedStatuses({ ...selectedStatuses, [activeQueueName]: status }); + if (activeQueueName) { + setSelectedStatuses({ ...selectedStatuses, [activeQueueName]: status }); + } }, [search, activeQueueName]); return selectedStatuses; diff --git a/packages/ui/src/index.css b/packages/ui/src/index.css index 6f3d271e5..57a1ec126 100644 --- a/packages/ui/src/index.css +++ b/packages/ui/src/index.css @@ -63,9 +63,10 @@ --modal-content-bg: var(--card-bg); --modal-overlay-bg: rgba(0, 0, 0, 0.85); --status-menu-active-border: #1b1c1d; - --status-menu-active-text: rgba(0, 0, 0, 0.87); --status-menu-border-color: #e0e7eb; - --status-menu-text: rgba(0, 0, 0, 0.87); + --status-menu-text: var(--text-color); + --status-menu-active-text: rgba(0, 0, 0, 0.87); + --status-menu-hover-text: var(--text-secondary-color); --sticky-header-bg: rgba(245, 248, 250, 0.85); --tooltip-bg: rgba(45, 55, 72, 0.95); --tooltip-text-color: #fff; @@ -157,6 +158,7 @@ --status-menu-border-color: var(--separator-color); --status-menu-text: var(--card-text-secondary-color); + --status-menu-hover-text: var(--text-secondary-color); --status-menu-active-text: var(--text-color); --status-menu-active-border: var(--accent-color); --sticky-header-bg: rgba(24, 29, 36, 0.9); diff --git a/packages/ui/src/pages/OverviewPage/OverviewPage.module.css b/packages/ui/src/pages/OverviewPage/OverviewPage.module.css index 97f15145f..bac24fe63 100644 --- a/packages/ui/src/pages/OverviewPage/OverviewPage.module.css +++ b/packages/ui/src/pages/OverviewPage/OverviewPage.module.css @@ -6,3 +6,18 @@ margin: 2rem 0 0; padding: 0; } + +.message { + margin-top: 2rem; + white-space: pre-line; + line-height: 1.5rem; + + a { + color: var(--accent-color); + text-decoration: none; + + &:hover { + color: var(--accent-color-d1); + } + } +} diff --git a/packages/ui/src/pages/OverviewPage/OverviewPage.tsx b/packages/ui/src/pages/OverviewPage/OverviewPage.tsx index 48c2003bf..56068b045 100644 --- a/packages/ui/src/pages/OverviewPage/OverviewPage.tsx +++ b/packages/ui/src/pages/OverviewPage/OverviewPage.tsx @@ -1,28 +1,46 @@ +import { Status } from '@bull-board/api/dist/typings/app'; import React from 'react'; +import { Trans, useTranslation } from 'react-i18next'; +import { NavLink } from 'react-router-dom'; import { QueueCard } from '../../components/QueueCard/QueueCard'; import { StatusLegend } from '../../components/StatusLegend/StatusLegend'; +import { useQuery } from '../../hooks/useQuery'; import { useQueues } from '../../hooks/useQueues'; +import { links } from '../../utils/links'; import s from './OverviewPage.module.css'; -import { useSelectedStatuses } from '../../hooks/useSelectedStatuses'; export const OverviewPage = () => { + const { t } = useTranslation(); const { actions, queues } = useQueues(); - actions.pollQueues(); - - const selectedStatus = useSelectedStatuses(); - const overviewPageStatus = selectedStatus['']; + const query = useQuery(); + actions.pollQueues(); + const selectedStatus = query.get('status') as Status; + const queuesToView = + queues?.filter((queue) => !selectedStatus || queue.counts[selectedStatus] > 0) || []; return (
- + {queuesToView.length > 0 && ( + + )} + {queuesToView.length === 0 && !!selectedStatus && ( +
+ }} + /> +
+ )}
); }; diff --git a/packages/ui/src/static/locales/en-US/messages.json b/packages/ui/src/static/locales/en-US/messages.json index 5946b6f56..d3caa4a71 100644 --- a/packages/ui/src/static/locales/en-US/messages.json +++ b/packages/ui/src/static/locales/en-US/messages.json @@ -7,7 +7,8 @@ }, "DASHBOARD": { "JOBS_COUNT_one": "{{count}} Job", - "JOBS_COUNT": "{{count}} Jobs" + "JOBS_COUNT": "{{count}} Jobs", + "NO_FILTERED_MESSAGE": "There are no queues that have a job with \"{{status}}\" status.\nClick here to clear the filter." }, "JOB": { "DELAY_CHANGED": "*Delay changed; the new run time is currently unknown", diff --git a/packages/ui/src/static/locales/es-ES/messages.json b/packages/ui/src/static/locales/es-ES/messages.json index 1ff77b193..b372611ac 100644 --- a/packages/ui/src/static/locales/es-ES/messages.json +++ b/packages/ui/src/static/locales/es-ES/messages.json @@ -7,7 +7,10 @@ }, "DASHBOARD": { "JOBS_COUNT_one": "{{count}} Tarea", - "JOBS_COUNT": "{{count}} Tareas" + "JOBS_COUNT_many": "{{count}} Job", + "JOBS_COUNT_other": "{{count}} Job", + "JOBS_COUNT": "{{count}} Tareas", + "NO_FILTERED_MESSAGE": "No hay colas que tengan un trabajo con el estado \"{{status}}\".\nHaz clic aquí para borrar el filtro." }, "JOB": { "DELAY_CHANGED": "*Retraso modificado; el nuevo tiempo de ejecución es actualmente desconocido", @@ -116,7 +119,9 @@ "OFF": "Desactivado", "SECS": "{{count}} segundos", "MINS": "{{count}} minutos", - "MINS_one": "{{count}} minuto" + "MINS_one": "{{count}} minuto", + "MINS_many": "{{count}} minute", + "MINS_other": "{{count}} minute" }, "DEFAULT_JOB_TAB": "Pestaña de tarea predeterminada", "JOBS_PER_PAGE": "Tareas por página (1-50)", @@ -143,4 +148,4 @@ "UPDATE": "Actualizar", "JOB_DATA": "Datos de la tarea" } -} \ No newline at end of file +} diff --git a/packages/ui/src/static/locales/fr-FR/messages.json b/packages/ui/src/static/locales/fr-FR/messages.json index 672abcb6d..5030e32f1 100644 --- a/packages/ui/src/static/locales/fr-FR/messages.json +++ b/packages/ui/src/static/locales/fr-FR/messages.json @@ -9,7 +9,8 @@ "JOBS_COUNT_one": "{{count}} Tâche", "JOBS_COUNT_many": "{{count}} Job", "JOBS_COUNT_other": "{{count}} Job", - "JOBS_COUNT": "{{count}} Tâches" + "JOBS_COUNT": "{{count}} Tâches", + "NO_FILTERED_MESSAGE": "Il n'y a aucune file d'attente avec un travail ayant le statut \"{{status}}\".\nCliquez ici pour effacer le filtre." }, "JOB": { "DELAY_CHANGED": "*Délai modifié; le nouveau temps d'exécution est actuellement inconnu", diff --git a/packages/ui/src/static/locales/pt-BR/messages.json b/packages/ui/src/static/locales/pt-BR/messages.json index fe5e7a580..48d7070de 100644 --- a/packages/ui/src/static/locales/pt-BR/messages.json +++ b/packages/ui/src/static/locales/pt-BR/messages.json @@ -9,7 +9,8 @@ "JOBS_COUNT_one": "{{count}} Tarefa", "JOBS_COUNT_many": "{{count}} Tarefas", "JOBS_COUNT_other": "{{count}} Tarefas", - "JOBS_COUNT": "{{count}} Tarefas" + "JOBS_COUNT": "{{count}} Tarefas", + "NO_FILTERED_MESSAGE": "Não há filas com um trabalho com o status \"{{status}}\".\nClique aqui para limpar o filtro." }, "JOB": { "DELAY_CHANGED": "*Delay changed; the new run time is currently unknown", diff --git a/packages/ui/src/static/locales/zh-CN/messages.json b/packages/ui/src/static/locales/zh-CN/messages.json index 19f54f00e..9b1f5ebd5 100644 --- a/packages/ui/src/static/locales/zh-CN/messages.json +++ b/packages/ui/src/static/locales/zh-CN/messages.json @@ -6,7 +6,8 @@ "PAUSED": "已暂停" }, "DASHBOARD": { - "JOBS_COUNT": "{{count}} 个作业" + "JOBS_COUNT": "{{count}} 个作业", + "NO_FILTERED_MESSAGE": "没有具有 \"{{status}}\" 状态的队列。\n点击这里 清除过滤器。" }, "JOB": { "DELAY_CHANGED": "*延迟已更改;新的运行时间目前未知", diff --git a/packages/ui/src/utils/links.ts b/packages/ui/src/utils/links.ts index c8cae46d6..e7e0b774c 100644 --- a/packages/ui/src/utils/links.ts +++ b/packages/ui/src/utils/links.ts @@ -1,6 +1,13 @@ -import { SelectedStatuses } from '../../typings/app'; +import { SelectedStatuses, Status } from '../../typings/app'; export const links = { + dashboardPage(status?: Status) { + const search = status ? new URLSearchParams({ status }).toString() : ''; + return { + pathname: '/', + search, + }; + }, queuePage( queueName: string, selectedStatuses: SelectedStatuses = {}