feat(activity): update summary cards to toggles and introduce export menu
This commit is contained in:
1 parent
73f4b539fe
commit
03b39e64f2
30 files changed
+2376
-238
No files matched your search
+62
-12
@@ -110,6 +110,15 @@ export function summaryRangeChanged(a: ActivityFilters, b: ActivityFilters) {
|
||||
return a.range !== b.range || a.from !== b.from || a.to !== b.to
|
||||
}
|
||||
|
||||
function rangeParams(range: ExportRange, from: string, to: string) {
|
||||
const params = new URLSearchParams({ range })
|
||||
if (range === 'custom') {
|
||||
params.set('from', from)
|
||||
params.set('to', to)
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
function filterParams(filters: ActivityFilters) {
|
||||
const params = new URLSearchParams()
|
||||
if (filters.q) params.set('q', filters.q)
|
||||
@@ -117,11 +126,9 @@ function filterParams(filters: ActivityFilters) {
|
||||
if (filters.category) params.set('category', filters.category)
|
||||
if (filters.outcome !== 'all') params.set('outcome', filters.outcome)
|
||||
if (filters.security) params.set('security', 'true')
|
||||
params.set('range', filters.range)
|
||||
if (filters.range === 'custom') {
|
||||
params.set('from', filters.from)
|
||||
params.set('to', filters.to)
|
||||
}
|
||||
rangeParams(filters.range, filters.from, filters.to).forEach((value, key) =>
|
||||
params.set(key, value),
|
||||
)
|
||||
return params
|
||||
}
|
||||
|
||||
@@ -136,13 +143,55 @@ export function exportQuery(filters: ActivityFilters) {
|
||||
return filterParams(filters).toString()
|
||||
}
|
||||
|
||||
export const OWNERS_ONLY_COPY = 'Only owners and admins can export all activity.'
|
||||
export const NOTHING_TO_EXPORT_COPY = 'Nothing to export. No events match these filters.'
|
||||
|
||||
export type ExportRange = 'all' | RangeKey
|
||||
|
||||
export const EXPORT_RANGE_KEYS: ExportRange[] = ['all', 'today', '7d', '30d', 'custom']
|
||||
|
||||
export function exportRangeLabel(range: ExportRange) {
|
||||
return range === 'all' ? t('All time') : rangeLabel(range)
|
||||
}
|
||||
|
||||
export function exportAllQuery(range: ExportRange, from: string, to: string) {
|
||||
return rangeParams(range, from, to).toString()
|
||||
}
|
||||
|
||||
export function isExportRangeValid(range: ExportRange, from: string, to: string) {
|
||||
return range !== 'custom' || (from !== '' && to !== '' && from <= to)
|
||||
}
|
||||
|
||||
function localDateStamp() {
|
||||
const now = new Date()
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||
const day = String(now.getDate()).padStart(2, '0')
|
||||
return `${now.getFullYear()}-${month}-${day}`
|
||||
}
|
||||
|
||||
export function currentViewFileName() {
|
||||
return `activity-${localDateStamp()}.csv`
|
||||
}
|
||||
|
||||
export function allActivityFileName() {
|
||||
return `activity-all-${localDateStamp()}.csv`
|
||||
}
|
||||
|
||||
export function readBlobText(blob: Blob) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => resolve(String(reader.result))
|
||||
reader.onerror = () => reject(reader.error)
|
||||
reader.readAsText(blob)
|
||||
})
|
||||
}
|
||||
|
||||
export function isHeaderOnlyCsv(text: string) {
|
||||
return text.trim().split(/\r?\n/).length <= 1
|
||||
}
|
||||
|
||||
export function summaryQuery(filters: ActivityFilters) {
|
||||
const params = new URLSearchParams({ range: filters.range })
|
||||
if (filters.range === 'custom') {
|
||||
params.set('from', filters.from)
|
||||
params.set('to', filters.to)
|
||||
}
|
||||
return params.toString()
|
||||
return rangeParams(filters.range, filters.from, filters.to).toString()
|
||||
}
|
||||
|
||||
export function categoryLabel(category: ActivityCategory) {
|
||||
@@ -231,7 +280,8 @@ export function activeChips(filters: ActivityFilters): ActivityChip[] {
|
||||
key: 'outcome',
|
||||
label: t('Outcome: {0}', [outcomeFilterLabel(filters.outcome)]),
|
||||
})
|
||||
if (filters.security) chips.push({ key: 'security', label: t('Security events') })
|
||||
if (filters.security)
|
||||
chips.push({ key: 'security', label: t('Type: {0}', [t('Security events')]) })
|
||||
if (filters.range !== DEFAULT_RANGE) {
|
||||
const value =
|
||||
filters.range === 'custom'
|
||||
|
||||
Reference in new issue
Block a user