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 = () => {
{queueStatsStatusList.map((status) => {
const displayStatus = t(`QUEUE.STATUS.${status.toUpperCase()}`).toLocaleUpperCase();
+ const isActive = query.get('status') === status;
- return (-
-
- {displayStatus}
-
-
);
+ return (
+ -
+ isActive}
+ >
+ {displayStatus}
+
+
+ );
})}
);
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 (
-
- {queues?.filter((queue) => overviewPageStatus === 'latest' || queue.counts[overviewPageStatus] > 0).map((queue) => (
- -
-
-
- ))}
-
+ {queuesToView.length > 0 && (
+
+ {queuesToView.map((queue) => (
+ -
+
+
+ ))}
+
+ )}
+ {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 = {}