feat(settings): add Logs as a dedicated tab in General settings (#21180)

## What & why

The audit-log viewer lived as a full-screen page reachable only via a
"View Logs" button buried in the **Security** tab. This surfaces it as
the **third tab in General settings** (`General | Security | Logs`),
consistent with the other tabs.

## Changes

- **Relocated** the event-logs module
`pages/settings/security/event-logs/` → `modules/settings/event-logs/`
and render it as tab content instead of a `FullScreenContainer` page.
Dropped `SettingsPath.EventLogs`, its route, and the fullscreen handling
in favor of the `general#logs` hash tab.
- **Security tab:** removed the "View Logs" entry; kept the
log-retention setting there.
- **In-tab gating** (shown to users with the Security permission):
Enterprise upgrade card when not entitled, a clear "ClickHouse not
configured" placeholder otherwise (derived from client config), and the
query is skipped when disabled. Replaces a bespoke error component that
string-matched error messages with the shared `SettingsEmptyPlaceholder`
/ `SettingsEnterpriseFeatureGateCard`.
- **Layout:** boxed content column with the table selector + filters
grouped in a `Card` and the results table below, matching settings
conventions. Kept the existing fixed filters (page/event name, member,
period) rather than recreating the record-view filter chips (those are
tightly coupled to record/view context).

Frontend + `twenty-shared` only — no changes to the log query or data.

## Test plan

- [x] `npx nx typecheck twenty-front` and `npx nx lint twenty-front`
pass
- [x] Settings → General shows three tabs; Logs is the third; breadcrumb
stays "Workspace / General"
- [x] With Enterprise + ClickHouse: table selector, filters, refresh,
and the paginated table work
- [x] Non-Enterprise: Enterprise upgrade card shown; no failing query
fires
- [ ] Enterprise without ClickHouse: shows the "ClickHouse not
configured" placeholder
- [ ] Security tab still shows the log-retention setting and the "View
Logs" button is gone
- [ ] A user without the Security permission sees neither the Security
nor Logs tab
This commit is contained in:
Félix Malfait
2026-06-04 08:47:23 +02:00
committed by GitHub
parent e6614299c6
commit 2ac515894b
21 changed files with 358 additions and 408 deletions
@@ -1,6 +1,5 @@
import { styled } from '@linaria/react';
import { useLingui } from '@lingui/react/macro';
import { Link } from 'react-router-dom';
import { useDebouncedCallback } from 'use-debounce';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
@@ -26,8 +25,6 @@ import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { CombinedGraphQLErrors } from '@apollo/client/errors';
import { useMutation } from '@apollo/client/react';
import { SettingsPath } from 'twenty-shared/types';
import { getSettingsPath } from 'twenty-shared/utils';
import { Tag } from 'twenty-ui/components';
import {
H2Title,
@@ -37,7 +34,6 @@ import {
IconMail,
IconTrash,
} from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Card, Section } from 'twenty-ui/layout';
import { themeCssVariables } from 'twenty-ui/theme-constants';
import { UpdateWorkspaceDocument } from '~/generated-metadata/graphql';
@@ -57,16 +53,6 @@ const StyledSectionContainer = styled.div`
flex-shrink: 0;
`;
const StyledLinkContainer = styled.div`
> a {
text-decoration: none;
&[data-disabled='true'] {
pointer-events: none;
}
}
`;
export const SettingsSecuritySettings = () => {
const { t } = useLingui();
const { enqueueErrorSnackBar } = useSnackBar();
@@ -259,7 +245,7 @@ export const SettingsSecuritySettings = () => {
<Section>
<H2Title
title={t`Audit Logs`}
description={t`View workspace activity logs`}
description={t`Configure how long audit logs are retained`}
adornment={
<Tag
text={t`Enterprise`}
@@ -271,44 +257,23 @@ export const SettingsSecuritySettings = () => {
/>
{hasEnterpriseAccess ? (
<Card rounded>
<SettingsOptionCardContentButton
Icon={IconHistory}
title={t`Workspace Events`}
description={
!isClickHouseConfigured
? t`ClickHouse is required for audit logs. Contact your administrator.`
: t`View and filter events, page views, object changes`
}
Button={
<StyledLinkContainer>
<Link
to={getSettingsPath(SettingsPath.EventLogs)}
data-disabled={!isEventLogsEnabled}
>
<Button
title={t`View Logs`}
variant="secondary"
size="small"
disabled={!isEventLogsEnabled}
/>
</Link>
</StyledLinkContainer>
}
/>
{isEventLogsEnabled && (
<>
<Separator />
<SettingsOptionCardContentCounter
Icon={IconClockHour8}
title={t`Log retention`}
description={t`Number of days to retain audit logs (30-1095 days)`}
value={currentWorkspace?.eventLogRetentionDays ?? 90}
onChange={handleEventLogRetentionDaysChange}
minValue={30}
maxValue={1095}
showButtons={false}
/>
</>
{isEventLogsEnabled ? (
<SettingsOptionCardContentCounter
Icon={IconClockHour8}
title={t`Log retention`}
description={t`Number of days to retain audit logs (30-1095 days)`}
value={currentWorkspace?.eventLogRetentionDays ?? 90}
onChange={handleEventLogRetentionDaysChange}
minValue={30}
maxValue={1095}
showButtons={false}
/>
) : (
<SettingsOptionCardContentButton
Icon={IconHistory}
title={t`Audit Logs`}
description={t`ClickHouse is required for audit logs. Contact your administrator.`}
/>
)}
</Card>
) : (