Files
twenty/packages/twenty-front/src/modules/page-layout/widgets/components/PageLayoutWidgetForbiddenDisplay.tsx
T
Félix Malfait f7421c5fc0 Add queue management dashboard (#15202)
Adds a comprehensive queue management interface to the admin panel for
viewing and managing background jobs.

**Features:**
- Queue detail pages showing paginated job lists (50 per page)
- Filter jobs by state: completed, failed, active, waiting, delayed,
paused
- Checkbox selection with bulk actions (delete jobs, retry failed jobs)
- Per-job dropdown menu for individual retry/delete
- Expandable rows showing error messages, stack traces, and job data
- Relative timestamps with hover tooltips
- Display attempt counts on failed jobs
- Dynamic retention policy info from backend

**Changes:**
- Backend: New AdminPanelQueueService with GraphQL endpoints for job
listing, retry, and delete
- Frontend: Queue detail page with QueueJobsTable component
- Updated retention policy: completed jobs kept 4 hours, failed jobs
kept 7 days (max 1000 each)
- Added JobState enum for type safety

<img width="634" height="696" alt="Screenshot_2025-10-20_at_11 45 25"
src="https://github.com/user-attachments/assets/c67bcd27-26cf-47f5-9575-3cd5684d006b"
/>
<img width="484" height="680" alt="Screenshot_2025-10-20_at_11 45 14"
src="https://github.com/user-attachments/assets/68725cc6-b3ec-4098-99ca-f9a717d6f8f1"
/>
<img width="490" height="643" alt="Screenshot_2025-10-20_at_11 45 05"
src="https://github.com/user-attachments/assets/b68a5809-33ff-4452-b48b-741aff7f1dd6"
/>



<img width="685" height="662" alt="Screenshot 2025-10-20 at 13 15 01"
src="https://github.com/user-attachments/assets/eeb5207b-de5c-4b18-bdde-392892053dab"
/>
2025-10-21 16:02:50 +02:00

52 lines
1.6 KiB
TypeScript

import { ForbiddenFieldDisplay } from '@/object-record/record-field/ui/meta-types/display/components/ForbiddenFieldDisplay';
import { type WidgetAccessDenialInfo } from '@/page-layout/widgets/types/WidgetAccessDenialInfo';
import { plural, t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import { AppTooltip } from 'twenty-ui/display';
type PageLayoutWidgetForbiddenDisplayProps = {
widgetId: string;
restriction: WidgetAccessDenialInfo;
};
export const PageLayoutWidgetForbiddenDisplay = ({
widgetId,
restriction,
}: PageLayoutWidgetForbiddenDisplayProps) => {
const tooltipId = `widget-forbidden-tooltip-${widgetId}`;
const getTooltipContent = () => {
if (restriction.type === 'object' && isDefined(restriction.objectName)) {
const objectName = restriction.objectName;
return t`You do not have permission to access the ${objectName} object`;
}
if (
restriction.type === 'field' &&
isDefined(restriction.fieldNames) &&
restriction.fieldNames.length > 0
) {
const fieldsList = restriction.fieldNames.join(', ');
return plural(restriction.fieldNames.length, {
one: `You do not have permission to access the ${fieldsList} field`,
other: `You do not have permission to access the ${fieldsList} fields`,
});
}
return t`You do not have permission to view this widget`;
};
return (
<>
<div id={tooltipId}>
<ForbiddenFieldDisplay />
</div>
<AppTooltip
anchorSelect={`#${tooltipId}`}
content={getTooltipContent()}
place="top"
/>
</>
);
};