Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions jsapp/js/UniversalTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,36 @@ export interface PaginatedListResponseData<Datum = never> {
results: Datum[]
}

export type PaginatedListResponse<Datum = never> = PaginatedListResponse.Ok<Datum> | PaginatedListResponse.NotFound
export type PaginatedListResponse<Datum = never> =
| PaginatedListResponse.Ok<Datum>
| PaginatedListResponse.Unauthorized
| PaginatedListResponse.Forbidden
| PaginatedListResponse.NotFound
export namespace PaginatedListResponse {
export interface Ok<Datum = never> {
data: PaginatedListResponseData<Datum>
status: 200
}
export interface Unauthorized {
data: unknown
status: 401
}
export interface Forbidden {
data: unknown
status: 403
}
export interface NotFound {
data: unknown
status: 404
}
}

interface UniversalTableProps<Datum> {
interface UniversalTableProps<Datum, TError = Error> {
// Below are props from `UniversalTable` that should come from the parent
// component (these are kind of "configuration" props). The other
// `UniversalTable` props are being handled here internally.
columns: Array<UniversalTableColumn<Datum>>
queryResult: UseQueryResult<PaginatedListResponse<Datum>>
queryResult: UseQueryResult<PaginatedListResponse<Datum>, TError>
pagination: Pagination
setPagination: (pagination: Pagination) => unknown
}
Expand Down Expand Up @@ -74,12 +86,12 @@ export const DEFAULT_PAGE_SIZE = PAGE_SIZES[0]
* }
* ```
*/
export default function UniversalTable<Datum>({
export default function UniversalTable<Datum, TError = Error>({
columns,
pagination,
queryResult,
setPagination,
}: UniversalTableProps<Datum>) {
}: UniversalTableProps<Datum, TError>) {
const availablePages = useMemo(
() => (queryResult.data?.status === 200 ? Math.ceil(queryResult.data?.data?.count / pagination.limit) : 0),
[pagination.limit, queryResult.data?.status, (queryResult.data?.data as PaginatedListResponseData<Datum>)?.count],
Expand Down
48 changes: 0 additions & 48 deletions jsapp/js/account/security/accessLogs/accessLogs.query.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,34 +1,52 @@
import React, { useState } from 'react'

import { keepPreviousData, useQuery } from '@tanstack/react-query'
import { keepPreviousData } from '@tanstack/react-query'
import UniversalTable, { DEFAULT_PAGE_SIZE } from '#/UniversalTable'
import securityStyles from '#/account/security/securityRoute.module.scss'
import type { AccessLogResponse } from '#/api/models/accessLogResponse'
import type { ErrorDetail } from '#/api/models/errorDetail'
import {
getAccessLogsMeListQueryKey,
useAccessLogsMeExportCreate,
useAccessLogsMeList,
} from '#/api/react-query/logging'
import Button from '#/components/common/button'
import ExportToEmailButton from '#/components/exportToEmailButton/exportToEmailButton.component'
import { QueryKeys } from '#/query/queryKeys'
import type { FailResponse } from '#/dataInterface'
import sessionStore from '#/stores/session'
import { formatTime } from '#/utils'
import { type AccessLog, getAccessLogs, startAccessLogsExport } from './accessLogs.query'

export default function AccessLogsSection() {
const [pagination, setPagination] = useState({
limit: DEFAULT_PAGE_SIZE,
offset: 0,
})
const queryResult = useQuery({
queryKey: [QueryKeys.accessLogs, pagination.limit, pagination.offset],
queryFn: () => getAccessLogs(pagination.limit, pagination.offset),
placeholderData: keepPreviousData,
// We might want to improve this in future, for now let's not retry
retry: false,
// The `refetchOnWindowFocus` option is `true` by default, I'm setting it
// here so we don't forget about it.
refetchOnWindowFocus: true,
const queryResult = useAccessLogsMeList(pagination, {
query: {
queryKey: getAccessLogsMeListQueryKey(pagination),
placeholderData: keepPreviousData,
},
})
const accessLogsMeExport = useAccessLogsMeExportCreate({
request: {
notifyAboutError: false,
},
})

function logOutAllSessions() {
sessionStore.logOutAll()
}
const handleStartExport = async () => {
try {
await accessLogsMeExport.mutateAsync()
} catch (error) {
const failResponse: FailResponse = {
status: 500,
statusText: (error as Error).message || t('An error occurred while exporting the logs'),
}
throw failResponse
}
}

return (
<>
Expand All @@ -43,11 +61,11 @@ export default function AccessLogsSection() {
startIcon='logout'
/>

<ExportToEmailButton label={t('Export log data')} exportFunction={startAccessLogsExport} />
<ExportToEmailButton label={t('Export log data')} exportFunction={handleStartExport} />
</div>
</header>

<UniversalTable<AccessLog>
<UniversalTable<AccessLogResponse, ErrorDetail>
pagination={pagination}
setPagination={setPagination}
queryResult={queryResult}
Expand All @@ -57,7 +75,7 @@ export default function AccessLogsSection() {
{
key: 'metadata.source',
label: t('Source'),
cellFormatter: (log: AccessLog) => {
cellFormatter: (log: AccessLogResponse) => {
if (log.metadata.auth_type === 'submission-group') {
return t('Data Submissions (##count##)').replace('##count##', String(log.count))
} else {
Expand All @@ -68,7 +86,7 @@ export default function AccessLogsSection() {
{
key: 'date_created',
label: t('Last activity'),
cellFormatter: (log: AccessLog) => formatTime(log.date_created),
cellFormatter: (log: AccessLogResponse) => formatTime(log.date_created),
},
{ key: 'metadata.ip_address', label: t('IP Address') },
]}
Expand Down
2 changes: 0 additions & 2 deletions jsapp/js/api.endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ export const endpoints = {
PROJECT_HISTORY_LOGS: '/api/v2/project-history-logs/',
/** Expected parameters: price_id and subscription_id **/
CHANGE_PLAN_URL: '/api/v2/stripe/change-plan',
ACCESS_LOGS_URL: '/api/v2/access-logs/me',
ACCESS_LOGS_EXPORT_URL: '/api/v2/access-logs/me/export/',
LOGOUT_ALL: '/logout-all/',
LANGUAGES_LIST_URL: '/api/v2/languages/',
LANGUAGE_DETAIL_URL: '/api/v2/languages/:language_id/',
Expand Down
1 change: 0 additions & 1 deletion jsapp/js/query/queryKeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* Keep keys sorted alphabetically.
*/
export enum QueryKeys {
accessLogs = 'accessLogs',
activityLogs = 'activityLogs',
activityLogsFilter = 'activityLogsFilter',
organization = 'organization',
Expand Down