mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-21 13:47:39 +02:00
feat: add download and delete all buttons to sign-on log UI (#3231)
Adds `Download sign-on log` and `Clear sign-on log` buttons to the UI, making it easy for admins to manage their sign-on log.  
This commit is contained in:
parent
5e1886fe93
commit
45cfaece6f
@ -0,0 +1,28 @@
|
|||||||
|
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
||||||
|
|
||||||
|
interface IServiceAccountDeleteAllDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
onConfirm: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SignOnLogDeleteAllDialog = ({
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
onConfirm,
|
||||||
|
}: IServiceAccountDeleteAllDialogProps) => (
|
||||||
|
<Dialogue
|
||||||
|
title="Clear sign-on log?"
|
||||||
|
open={open}
|
||||||
|
primaryButtonText="Clear sign-on log"
|
||||||
|
secondaryButtonText="Cancel"
|
||||||
|
onClick={onConfirm}
|
||||||
|
onClose={() => {
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
You are about to clear the sign-on log.
|
||||||
|
<br />
|
||||||
|
This will delete all the sign-on events.
|
||||||
|
</Dialogue>
|
||||||
|
);
|
@ -5,7 +5,7 @@ import useToast from 'hooks/useToast';
|
|||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { useMediaQuery } from '@mui/material';
|
import { IconButton, Tooltip, useMediaQuery } from '@mui/material';
|
||||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table';
|
import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||||
import { sortTypes } from 'utils/sortTypes';
|
import { sortTypes } from 'utils/sortTypes';
|
||||||
@ -25,6 +25,8 @@ import { useSignOnLogApi } from 'hooks/api/actions/useSignOnLogApi/useSignOnLogA
|
|||||||
import { formatDateYMDHMS } from 'utils/formatDate';
|
import { formatDateYMDHMS } from 'utils/formatDate';
|
||||||
import { useSearchParams } from 'react-router-dom';
|
import { useSearchParams } from 'react-router-dom';
|
||||||
import { createLocalStorage } from 'utils/createLocalStorage';
|
import { createLocalStorage } from 'utils/createLocalStorage';
|
||||||
|
import { Delete, Download } from '@mui/icons-material';
|
||||||
|
import { SignOnLogDeleteAllDialog } from './SignOnLogDeleteAllDialog/SignOnLogDeleteAllDialog';
|
||||||
|
|
||||||
export type PageQueryType = Partial<
|
export type PageQueryType = Partial<
|
||||||
Record<'sort' | 'order' | 'search', string>
|
Record<'sort' | 'order' | 'search', string>
|
||||||
@ -48,7 +50,7 @@ export const SignOnLogTable = () => {
|
|||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
|
||||||
const { events, loading, refetch } = useSignOnLog();
|
const { events, loading, refetch } = useSignOnLog();
|
||||||
const { removeEvent } = useSignOnLogApi();
|
const { removeEvent, removeAllEvents, downloadCSV } = useSignOnLogApi();
|
||||||
|
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
const [initialState] = useState(() => ({
|
const [initialState] = useState(() => ({
|
||||||
@ -65,8 +67,9 @@ export const SignOnLogTable = () => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
const [searchValue, setSearchValue] = useState(initialState.globalFilter);
|
const [searchValue, setSearchValue] = useState(initialState.globalFilter);
|
||||||
const [deleteOpen, setDeleteOpen] = useState(false);
|
|
||||||
const [selectedEvent, setSelectedEvent] = useState<ISignOnEvent>();
|
const [selectedEvent, setSelectedEvent] = useState<ISignOnEvent>();
|
||||||
|
const [deleteOpen, setDeleteOpen] = useState(false);
|
||||||
|
const [deleteAllOpen, setDeleteAllOpen] = useState(false);
|
||||||
|
|
||||||
const onDeleteConfirm = async (event: ISignOnEvent) => {
|
const onDeleteConfirm = async (event: ISignOnEvent) => {
|
||||||
try {
|
try {
|
||||||
@ -82,6 +85,20 @@ export const SignOnLogTable = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onDeleteAllConfirm = async () => {
|
||||||
|
try {
|
||||||
|
await removeAllEvents();
|
||||||
|
setToastData({
|
||||||
|
title: `Log has been cleared`,
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
refetch();
|
||||||
|
setDeleteAllOpen(false);
|
||||||
|
} catch (error: unknown) {
|
||||||
|
setToastApiError(formatUnknownError(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
@ -223,17 +240,50 @@ export const SignOnLogTable = () => {
|
|||||||
<PageHeader
|
<PageHeader
|
||||||
title={`Sign-on log (${rows.length})`}
|
title={`Sign-on log (${rows.length})`}
|
||||||
actions={
|
actions={
|
||||||
<ConditionallyRender
|
<>
|
||||||
condition={!isSmallScreen}
|
<ConditionallyRender
|
||||||
show={
|
condition={!isSmallScreen}
|
||||||
<Search
|
show={
|
||||||
initialValue={searchValue}
|
<Search
|
||||||
onChange={setSearchValue}
|
initialValue={searchValue}
|
||||||
hasFilters
|
onChange={setSearchValue}
|
||||||
getSearchContext={getSearchContext}
|
hasFilters
|
||||||
/>
|
getSearchContext={getSearchContext}
|
||||||
}
|
/>
|
||||||
/>
|
}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={rows.length > 0}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={!isSmallScreen}
|
||||||
|
show={<PageHeader.Divider />}
|
||||||
|
/>
|
||||||
|
<Tooltip
|
||||||
|
title="Download sign-on log"
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<IconButton onClick={downloadCSV}>
|
||||||
|
<Download />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip
|
||||||
|
title="Clear sign-on log"
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
onClick={() =>
|
||||||
|
setDeleteAllOpen(true)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Delete />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
@ -283,6 +333,11 @@ export const SignOnLogTable = () => {
|
|||||||
setOpen={setDeleteOpen}
|
setOpen={setDeleteOpen}
|
||||||
onConfirm={onDeleteConfirm}
|
onConfirm={onDeleteConfirm}
|
||||||
/>
|
/>
|
||||||
|
<SignOnLogDeleteAllDialog
|
||||||
|
open={deleteAllOpen}
|
||||||
|
setOpen={setDeleteAllOpen}
|
||||||
|
onConfirm={onDeleteAllConfirm}
|
||||||
|
/>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,23 @@ export const useSignOnLogApi = () => {
|
|||||||
propagateErrors: true,
|
propagateErrors: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const downloadCSV = async () => {
|
||||||
|
const requestId = 'downloadCSV';
|
||||||
|
const req = createRequest(
|
||||||
|
'api/admin/signons',
|
||||||
|
{
|
||||||
|
method: 'GET',
|
||||||
|
responseType: 'blob',
|
||||||
|
headers: { Accept: 'text/csv' },
|
||||||
|
},
|
||||||
|
requestId
|
||||||
|
);
|
||||||
|
|
||||||
|
const file = await (await makeRequest(req.caller, req.id)).blob();
|
||||||
|
const url = window.URL.createObjectURL(file);
|
||||||
|
window.location.assign(url);
|
||||||
|
};
|
||||||
|
|
||||||
const removeEvent = async (eventId: number) => {
|
const removeEvent = async (eventId: number) => {
|
||||||
const requestId = 'removeEvent';
|
const requestId = 'removeEvent';
|
||||||
const req = createRequest(
|
const req = createRequest(
|
||||||
@ -16,8 +33,21 @@ export const useSignOnLogApi = () => {
|
|||||||
await makeRequest(req.caller, req.id);
|
await makeRequest(req.caller, req.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const removeAllEvents = async () => {
|
||||||
|
const requestId = 'removeAllEvents';
|
||||||
|
const req = createRequest(
|
||||||
|
'api/admin/signons',
|
||||||
|
{ method: 'DELETE' },
|
||||||
|
requestId
|
||||||
|
);
|
||||||
|
|
||||||
|
await makeRequest(req.caller, req.id);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
downloadCSV,
|
||||||
removeEvent,
|
removeEvent,
|
||||||
|
removeAllEvents,
|
||||||
errors,
|
errors,
|
||||||
loading,
|
loading,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user