mirror of
https://github.com/hanzoai/sentinel.git
synced 2026-09-29 22:34:33 +00:00
198 lines
4.9 KiB
TypeScript
198 lines
4.9 KiB
TypeScript
import {Fragment} from 'react';
|
|
import styled from '@emotion/styled';
|
|
|
|
import {Button} from 'sentry/components/button';
|
|
import Confirm from 'sentry/components/confirm';
|
|
import Link from 'sentry/components/links/link';
|
|
import LoadingIndicator from 'sentry/components/loadingIndicator';
|
|
import Placeholder from 'sentry/components/placeholder';
|
|
import TimeSince from 'sentry/components/timeSince';
|
|
import {Tooltip} from 'sentry/components/tooltip';
|
|
import {IconSubtract} from 'sentry/icons';
|
|
import {t, tct} from 'sentry/locale';
|
|
import {space} from 'sentry/styles/space';
|
|
import type {Organization, OrgAuthToken, Project} from 'sentry/types';
|
|
import getDynamicText from 'sentry/utils/getDynamicText';
|
|
import {tokenPreview} from 'sentry/views/settings/organizationAuthTokens';
|
|
|
|
function LastUsed({
|
|
organization,
|
|
dateLastUsed,
|
|
projectLastUsed,
|
|
}: {
|
|
organization: Organization;
|
|
dateLastUsed?: Date;
|
|
projectLastUsed?: Project;
|
|
}) {
|
|
if (dateLastUsed && projectLastUsed) {
|
|
return (
|
|
<Fragment>
|
|
{tct('[date] in project [project]', {
|
|
date: (
|
|
<TimeSince
|
|
date={getDynamicText({
|
|
value: dateLastUsed,
|
|
fixed: new Date(1508208080000), // National Pasta Day
|
|
})}
|
|
/>
|
|
),
|
|
project: (
|
|
<Link to={`/settings/${organization.slug}/${projectLastUsed.slug}/`}>
|
|
{projectLastUsed.name}
|
|
</Link>
|
|
),
|
|
})}
|
|
</Fragment>
|
|
);
|
|
}
|
|
|
|
if (dateLastUsed) {
|
|
return (
|
|
<Fragment>
|
|
<TimeSince
|
|
date={getDynamicText({
|
|
value: dateLastUsed,
|
|
fixed: new Date(1508208080000), // National Pasta Day
|
|
})}
|
|
/>
|
|
</Fragment>
|
|
);
|
|
}
|
|
|
|
if (projectLastUsed) {
|
|
return (
|
|
<Fragment>
|
|
{tct('in project [project]', {
|
|
project: (
|
|
<Link to={`/settings/${organization.slug}/${projectLastUsed.slug}/`}>
|
|
{projectLastUsed.name}
|
|
</Link>
|
|
),
|
|
})}
|
|
</Fragment>
|
|
);
|
|
}
|
|
|
|
return <NeverUsed>{t('never used')}</NeverUsed>;
|
|
}
|
|
|
|
export function OrganizationAuthTokensAuthTokenRow({
|
|
organization,
|
|
isRevoking,
|
|
token,
|
|
revokeToken,
|
|
projectLastUsed,
|
|
isProjectLoading,
|
|
}: {
|
|
isRevoking: boolean;
|
|
organization: Organization;
|
|
token: OrgAuthToken;
|
|
isProjectLoading?: boolean;
|
|
projectLastUsed?: Project;
|
|
revokeToken?: (token: OrgAuthToken) => void;
|
|
}) {
|
|
return (
|
|
<Fragment>
|
|
<div>
|
|
<Label>
|
|
<Link to={`/settings/${organization.slug}/auth-tokens/${token.id}/`}>
|
|
{token.name}
|
|
</Link>
|
|
</Label>
|
|
|
|
{token.tokenLastCharacters && (
|
|
<TokenPreview aria-label={t('Token preview')}>
|
|
{tokenPreview(
|
|
getDynamicText({
|
|
value: token.tokenLastCharacters,
|
|
fixed: 'ABCD',
|
|
}),
|
|
'sntrys_'
|
|
)}
|
|
</TokenPreview>
|
|
)}
|
|
</div>
|
|
|
|
<DateTime>
|
|
{isProjectLoading ? (
|
|
<Placeholder height="1.25em" />
|
|
) : (
|
|
<Fragment>
|
|
<TimeSince
|
|
date={getDynamicText({
|
|
value: token.dateCreated,
|
|
fixed: new Date(1508208080000), // National Pasta Day
|
|
})}
|
|
/>
|
|
</Fragment>
|
|
)}
|
|
</DateTime>
|
|
|
|
<DateTime>
|
|
{isProjectLoading ? (
|
|
<Placeholder height="1.25em" />
|
|
) : (
|
|
<LastUsed
|
|
dateLastUsed={token.dateLastUsed}
|
|
projectLastUsed={projectLastUsed}
|
|
organization={organization}
|
|
/>
|
|
)}
|
|
</DateTime>
|
|
|
|
<Actions>
|
|
<Tooltip
|
|
title={t(
|
|
'You must be an organization owner, manager or admin to revoke a token.'
|
|
)}
|
|
disabled={!!revokeToken}
|
|
>
|
|
<Confirm
|
|
disabled={!revokeToken || isRevoking}
|
|
onConfirm={revokeToken ? () => revokeToken(token) : undefined}
|
|
message={t(
|
|
'Are you sure you want to revoke this token? The token will not be usable anymore, and this cannot be undone.'
|
|
)}
|
|
>
|
|
<Button
|
|
size="sm"
|
|
disabled={isRevoking || !revokeToken}
|
|
aria-label={t('Revoke %s', token.name)}
|
|
icon={
|
|
isRevoking ? (
|
|
<LoadingIndicator mini />
|
|
) : (
|
|
<IconSubtract isCircled size="xs" />
|
|
)
|
|
}
|
|
>
|
|
{t('Revoke')}
|
|
</Button>
|
|
</Confirm>
|
|
</Tooltip>
|
|
</Actions>
|
|
</Fragment>
|
|
);
|
|
}
|
|
|
|
const Label = styled('div')``;
|
|
|
|
const Actions = styled('div')`
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
`;
|
|
|
|
const DateTime = styled('div')`
|
|
display: flex;
|
|
align-items: center;
|
|
gap: ${space(0.5)};
|
|
`;
|
|
|
|
const NeverUsed = styled('div')`
|
|
color: ${p => p.theme.gray300};
|
|
`;
|
|
|
|
const TokenPreview = styled('div')`
|
|
color: ${p => p.theme.gray300};
|
|
`;
|