Skip to content

Commit

Permalink
feat: add translation ability, #653
Browse files Browse the repository at this point in the history
  • Loading branch information
felixmosh committed Nov 29, 2023
1 parent 3d9ee8f commit 615daa4
Show file tree
Hide file tree
Showing 30 changed files with 476 additions and 178 deletions.
1 change: 1 addition & 0 deletions packages/api/typings/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ export type UIConfig = Partial<{
boardLogo: { path: string; width?: number | string; height?: number | string };
miscLinks: Array<IMiscLink>;
favIcon: FavIcon;
locale: { lng?: string };
}>;

export type FavIcon = {
Expand Down
4 changes: 4 additions & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
"fork-ts-checker-webpack-plugin": "^7.2.7",
"highlight.js": "^11.5.1",
"html-webpack-plugin": "^5.5.0",
"i18next": "^23.7.7",
"i18next-hmr": "^3.0.3",
"i18next-http-backend": "^2.4.2",
"mini-css-extract-plugin": "^2.6.0",
"nanoid": "^4.0.1",
"postcss": "^8.4.12",
Expand All @@ -66,6 +69,7 @@
"pretty-bytes": "^6.0.0",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-i18next": "^13.5.0",
"react-paginate": "^8.1.3",
"react-refresh": "^0.12.0",
"react-router-dom": "^5.3.1",
Expand Down
5 changes: 2 additions & 3 deletions packages/ui/src/components/Button/Button.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
cursor: pointer;
outline: none;
white-space: nowrap;
padding: .65em .92857143em;
padding: 0.65em 0.92857143em;
color: inherit;
font-family: inherit;
vertical-align: baseline;
Expand All @@ -18,7 +18,7 @@
}

.button + .button {
margin-inline-start: 0.25em;
margin-inline-start: 0.5rem;
}

.button.default > svg {
Expand Down Expand Up @@ -81,4 +81,3 @@
.button.primary:focus {
background-color: hsl(216, 15%, 37%);
}

6 changes: 4 additions & 2 deletions packages/ui/src/components/ConfirmModal/ConfirmModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from '@radix-ui/react-alert-dialog';
import cn from 'clsx';
import React from 'react';
import { useTranslation } from 'react-i18next';
import s from './ConfirmModal.module.css';
import modalStyles from '../Modal/Modal.module.css';
import { Button } from '../Button/Button';
Expand All @@ -23,6 +24,7 @@ export interface ConfirmProps {
}

export const ConfirmModal = ({ open, onConfirm, title, onCancel, description }: ConfirmProps) => {
const { t } = useTranslation();
const closeOnOpenChange = (open: boolean) => {
if (!open) {
onCancel();
Expand All @@ -44,12 +46,12 @@ export const ConfirmModal = ({ open, onConfirm, title, onCancel, description }:
<div className={modalStyles.actions}>
<Action asChild>
<Button theme="primary" onClick={onConfirm}>
Confirm
{t('CONFIRM.CONFIRM_BTN')}
</Button>
</Action>
<Cancel asChild>
<Button theme="basic" onClick={onCancel}>
Cancel
{t('CONFIRM.CANCEL_BTN')}
</Button>
</Cancel>
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const Header = ({ children }: PropsWithChildren<any>) => {

return (
<header className={s.header}>
<NavLink to={'/'} className={s.logo}>
<NavLink to="/" className={s.logo}>
{!!logoPath && (
<img
src={logoPath}
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/components/JobCard/Details/Details.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useDetailsTabs } from '../../../hooks/useDetailsTabs';
import { Button } from '../../Button/Button';
import s from './Details.module.css';
Expand All @@ -13,6 +14,7 @@ interface DetailsProps {

export const Details = ({ status, job, actions }: DetailsProps) => {
const { tabs, selectedTab } = useDetailsTabs(status, job.isFailed);
const { t } = useTranslation();

if (tabs.length === 0) {
return null;
Expand All @@ -24,7 +26,7 @@ export const Details = ({ status, job, actions }: DetailsProps) => {
{tabs.map((tab) => (
<li key={tab.title}>
<Button onClick={tab.selectTab} isActive={tab.isActive}>
{tab.title}
{t(`JOB.TABS.${tab.title.toUpperCase()}`)}
</Button>
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AppJob } from '@bull-board/api/typings/app';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { TabsType } from '../../../../hooks/useDetailsTabs';
import { useSettingsStore } from '../../../../hooks/useSettings';
import { Highlight } from '../../../Highlight/Highlight';
Expand All @@ -16,6 +17,7 @@ interface DetailsContentProps {
}

export const DetailsContent = ({ selectedTab, job, actions }: DetailsContentProps) => {
const { t } = useTranslation();
const { collapseJobData, collapseJobOptions, collapseJobError } = useSettingsStore();
const [collapseState, setCollapse] = useState({ data: false, options: false, error: false });
const { stacktrace, data, returnValue, opts, failedReason } = job;
Expand All @@ -24,27 +26,27 @@ export const DetailsContent = ({ selectedTab, job, actions }: DetailsContentProp
case 'Data':
return collapseJobData && !collapseState.data ? (
<Button onClick={() => setCollapse({ ...collapseState, data: true })}>
Show data <ArrowDownIcon />
{t('JOB.SHOW_DATA_BTN')} <ArrowDownIcon />
</Button>
) : (
<Highlight language="json">{JSON.stringify({ data, returnValue }, null, 2)}</Highlight>
);
case 'Options':
return collapseJobOptions && !collapseState.options ? (
<Button onClick={() => setCollapse({ ...collapseState, options: true })}>
Show options <ArrowDownIcon />
{t('JOB.SHOW_OPTIONS_BTN')} <ArrowDownIcon />
</Button>
) : (
<Highlight language="json">{JSON.stringify(opts, null, 2)}</Highlight>
);
case 'Error':
if (stacktrace.length === 0) {
return <div className="error">{!!failedReason ? failedReason : 'NA'}</div>;
return <div className="error">{!!failedReason ? failedReason : t('JOB.NA')}</div>;
}

return collapseJobError && !collapseState.error ? (
<Button onClick={() => setCollapse({ ...collapseState, error: true })}>
Show errors <ArrowDownIcon />
{t('JOB.SHOW_ERRORS_BTN')} <ArrowDownIcon />
</Button>
) : (
<Highlight language="stacktrace" key="stacktrace">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { AppJob } from '@bull-board/api/typings/app';
import React, { SyntheticEvent, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useInterval } from '../../../../../hooks/useInterval';
import { InputField } from '../../../../Form/InputField/InputField';
import { FullscreenIcon } from '../../../../Icons/Fullscreen';
Expand Down Expand Up @@ -39,6 +40,7 @@ function formatLogs(logs: string[]) {
}

export const JobLogs = ({ actions, job }: JobLogsProps) => {
const { t } = useTranslation();
const [logs, setLogs] = useState<LogType[]>([]);
const [liveLogs, setLiveLogs] = useState(false);
const [keyword, setKeyword] = useState('');
Expand Down Expand Up @@ -96,7 +98,7 @@ export const JobLogs = ({ actions, job }: JobLogsProps) => {
className={s.searchBar}
name="searchQuery"
type="search"
placeholder="Filters"
placeholder={t('JOB.LOGS.FILTER_PLACEHOLDER')}
onChange={onSearch}
/>
</form>
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/components/JobCard/JobActions/JobActions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { STATUSES } from '@bull-board/api/src/constants/statuses';
import { Status } from '@bull-board/api/typings/app';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Button } from '../../Button/Button';
import { PromoteIcon } from '../../Icons/Promote';
import { RetryIcon } from '../../Icons/Retry';
Expand Down Expand Up @@ -39,6 +40,7 @@ const statusToButtonsMap: Record<string, ButtonType[]> = {

export const JobActions = ({ actions, status, allowRetries }: JobActionsProps) => {
let buttons = statusToButtonsMap[status];
const { t } = useTranslation();
if (!buttons) {
return null;
}
Expand All @@ -51,7 +53,7 @@ export const JobActions = ({ actions, status, allowRetries }: JobActionsProps) =
<ul className={s.jobActions}>
{buttons.map((type) => (
<li key={type.title}>
<Tooltip title={type.title}>
<Tooltip title={t(`JOB.ACTIONS.${type.title.toUpperCase()}`)}>
<Button onClick={actions[type.actionKey]} className={s.button}>
<type.Icon />
</Button>
Expand Down
84 changes: 45 additions & 39 deletions packages/ui/src/components/JobCard/JobCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { STATUSES } from '@bull-board/api/src/constants/statuses';
import { AppJob, Status } from '@bull-board/api/typings/app';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { Card } from '../Card/Card';
import { Details } from './Details/Details';
Expand Down Expand Up @@ -32,46 +33,51 @@ export const JobCard = ({
readOnlyMode,
allowRetries,
jobUrl,
}: JobCardProps) => (
<Card className={s.card}>
<div className={s.sideInfo}>
{jobUrl ? (
<Link className={s.jobLink} to={jobUrl}>
}: JobCardProps) => {
const { t } = useTranslation();
return (
<Card className={s.card}>
<div className={s.sideInfo}>
{jobUrl ? (
<Link className={s.jobLink} to={jobUrl}>
<span title={`#${job.id}`}>#{job.id}</span>
</Link>
) : (
<span title={`#${job.id}`}>#{job.id}</span>
</Link>
) : (
<span title={`#${job.id}`}>#{job.id}</span>
)}
<Timeline job={job} status={status} />
</div>
<div className={s.contentWrapper}>
<div className={s.title}>
<h4>
{job.name}
{job.attempts > 1 && <span>attempt #{job.attempts}</span>}
{!!job.opts?.repeat?.count && (
<span>
repeat {job.opts?.repeat?.count}
{!!job.opts?.repeat?.limit && ` / ${job.opts?.repeat?.limit}`}
</span>
)}
</h4>
{!readOnlyMode && (
<JobActions status={status} actions={actions} allowRetries={allowRetries} />
)}
<Timeline job={job} status={status} />
</div>
<div className={s.content}>
<Details status={status} job={job} actions={actions} />
{typeof job.progress === 'number' && (
<Progress
percentage={job.progress}
status={
job.isFailed && !greenStatuses.includes(status as any) ? STATUSES.failed : status
}
className={s.progress}
/>
)}
<div className={s.contentWrapper}>
<div className={s.title}>
<h4>
{job.name}
{job.attempts > 1 && <span>{t('JOB.ATTEMPTS', { attempts: job.attempts })}</span>}
{!!job.opts?.repeat?.count && (
<span>
{t(`JOB.REPEAT${!!job.opts?.repeat?.limit ? '_WITH_LIMIT' : ''}`, {
count: job.opts.repeat.count,
limit: job.opts?.repeat?.limit,
})}
</span>
)}
</h4>
{!readOnlyMode && (
<JobActions status={status} actions={actions} allowRetries={allowRetries} />
)}
</div>
<div className={s.content}>
<Details status={status} job={job} actions={actions} />
{typeof job.progress === 'number' && (
<Progress
percentage={job.progress}
status={
job.isFailed && !greenStatuses.includes(status as any) ? STATUSES.failed : status
}
className={s.progress}
/>
)}
</div>
</div>
</div>
</Card>
);
</Card>
);
};
Loading

0 comments on commit 615daa4

Please sign in to comment.