Add date range picker and update backups and audit logs to use it

This commit is contained in:
Andrew Kingston 2024-04-11 08:57:34 +01:00
parent 0a4dfef8cf
commit b1bd8993a6
3 changed files with 113 additions and 52 deletions

View File

@ -0,0 +1,89 @@
<script>
import { DatePicker } from "@budibase/bbui"
import dayjs from "dayjs"
import { createEventDispatcher } from "svelte"
import { memo } from "@budibase/frontend-core"
export let value
const dispatch = createEventDispatcher()
const valueStore = memo(value)
let date1
let date2
$: valueStore.set(value)
$: parseValue($valueStore)
const parseValue = value => {
if (!Array.isArray(value) || !value[0] || !value[1]) {
date1 = null
date2 = null
} else {
date1 = value[0]
date2 = value[1]
}
}
const onChangeDate1 = e => {
date1 = e.detail ? dayjs(e.detail).startOf("day") : null
if (date1 && (!date2 || date1.isAfter(date2))) {
date2 = date1.endOf("day")
} else if (!date1) {
date2 = null
}
broadcastChange()
}
const onChangeDate2 = e => {
date2 = e.detail ? dayjs(e.detail).endOf("day") : null
if (date2 && (!date1 || date2.isBefore(date1))) {
date1 = date2.startOf("day")
} else if (!date2) {
date1 = null
}
broadcastChange()
}
const broadcastChange = () => {
dispatch("change", [date1, date2])
}
</script>
<div class="date-range-picker">
<DatePicker
value={date1}
label="Date range"
enableTime={false}
on:change={onChangeDate1}
/>
<DatePicker value={date2} enableTime={false} on:change={onChangeDate2} />
</div>
<style>
.date-range-picker {
display: flex;
flex-direction: row;
align-items: flex-end;
}
/* Overlap date pickers to remove double border, but put the focused one on top */
.date-range-picker :global(.spectrum-InputGroup.is-focused) {
z-index: 1;
}
.date-range-picker :global(> :last-child) {
margin-left: -1px;
}
/* Remove border radius at the join */
.date-range-picker :global(> :first-child .spectrum-InputGroup),
.date-range-picker :global(> :first-child .spectrum-Picker) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.date-range-picker :global(> :last-child .spectrum-InputGroup),
.date-range-picker :global(> :last-child .spectrum-Textfield-input) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
</style>

View File

@ -1,7 +1,6 @@
<script> <script>
import { import {
Button, Button,
DatePicker,
Divider, Divider,
Layout, Layout,
notifications, notifications,
@ -25,14 +24,13 @@
import BackupsDefault from "assets/backups-default.png" import BackupsDefault from "assets/backups-default.png"
import { BackupTrigger, BackupType } from "constants/backend/backups" import { BackupTrigger, BackupType } from "constants/backend/backups"
import { onMount } from "svelte" import { onMount } from "svelte"
import dayjs from "dayjs" import DateRangePicker from "components/common/DateRangePicker.svelte"
let loading = true let loading = true
let backupData = null let backupData = null
let pageInfo = createPaginationStore() let pageInfo = createPaginationStore()
let filterOpt = null let filterOpt = null
let startDate = null let dateRange = []
let endDate = null
let filters = [ let filters = [
{ {
label: "Manual backup", label: "Manual backup",
@ -53,7 +51,7 @@
] ]
$: page = $pageInfo.page $: page = $pageInfo.page
$: fetchBackups(filterOpt, page, startDate, endDate) $: fetchBackups(filterOpt, page, dateRange)
let schema = { let schema = {
type: { type: {
@ -100,13 +98,13 @@
}) })
} }
async function fetchBackups(filters, page, startDate, endDate) { async function fetchBackups(filters, page, dateRange) {
const response = await backups.searchBackups({ const response = await backups.searchBackups({
appId: $appStore.appId, appId: $appStore.appId,
...filters, ...filters,
page, page,
startDate: startDate ? dayjs(startDate).startOf("day") : null, startDate: dateRange[0],
endDate: endDate ? dayjs(endDate).endOf("day") : null, endDate: dateRange[1],
}) })
pageInfo.fetched(response.hasNextPage, response.nextPage) pageInfo.fetched(response.hasNextPage, response.nextPage)
@ -166,7 +164,7 @@
} }
onMount(async () => { onMount(async () => {
await fetchBackups(filterOpt, page, startDate, endDate) await fetchBackups(filterOpt, page, dateRange)
loading = false loading = false
}) })
</script> </script>
@ -208,7 +206,7 @@
View plans View plans
</Button> </Button>
</div> </div>
{:else if !backupData?.length && !loading && !filterOpt && !startDate} {:else if !backupData?.length && !loading && !filterOpt && !dateRange?.length}
<div class="center"> <div class="center">
<Layout noPadding gap="S" justifyItems="center"> <Layout noPadding gap="S" justifyItems="center">
<img height="130px" src={BackupsDefault} alt="BackupsDefault" /> <img height="130px" src={BackupsDefault} alt="BackupsDefault" />
@ -237,21 +235,9 @@
bind:value={filterOpt} bind:value={filterOpt}
/> />
</div> </div>
<DatePicker <DateRangePicker
value={startDate} value={dateRange}
label="From" on:change={e => (dateRange = e.detail)}
enableTime={false}
on:change={e => {
startDate = e.detail
}}
/>
<DatePicker
value={endDate}
label="Until"
enableTime={false}
on:change={e => {
endDate = e.detail
}}
/> />
</div> </div>
<div> <div>

View File

@ -27,6 +27,7 @@
import TimeRenderer from "./_components/TimeRenderer.svelte" import TimeRenderer from "./_components/TimeRenderer.svelte"
import AppColumnRenderer from "./_components/AppColumnRenderer.svelte" import AppColumnRenderer from "./_components/AppColumnRenderer.svelte"
import { cloneDeep } from "lodash" import { cloneDeep } from "lodash"
import DateRangePicker from "components/common/DateRangePicker.svelte"
import dayjs from "dayjs" import dayjs from "dayjs"
const schema = { const schema = {
@ -70,15 +71,13 @@
let sidePanelVisible = false let sidePanelVisible = false
let wideSidePanel = false let wideSidePanel = false
let timer let timer
let endDate = dayjs() let dateRange = [dayjs().subtract(30, "days"), dayjs()]
let startDate = endDate.subtract(30, "days")
$: fetchUsers(userPage, userSearchTerm) $: fetchUsers(userPage, userSearchTerm)
$: fetchLogs({ $: fetchLogs({
logsPage, logsPage,
logSearchTerm, logSearchTerm,
startDate, dateRange,
endDate,
selectedUsers, selectedUsers,
selectedApps, selectedApps,
selectedEvents, selectedEvents,
@ -136,8 +135,7 @@
const fetchLogs = async ({ const fetchLogs = async ({
logsPage, logsPage,
logSearchTerm, logSearchTerm,
startDate, dateRange,
endDate,
selectedUsers, selectedUsers,
selectedApps, selectedApps,
selectedEvents, selectedEvents,
@ -155,8 +153,8 @@
logsPageInfo.loading() logsPageInfo.loading()
await auditLogs.search({ await auditLogs.search({
bookmark: logsPage, bookmark: logsPage,
startDate: startDate ? dayjs(startDate).startOf("day") : null, startDate: dateRange[0],
endDate: endDate ? dayjs(endDate).endOf("day") : null, endDate: dateRange[1],
fullSearch: logSearchTerm, fullSearch: logSearchTerm,
userIds: selectedUsers, userIds: selectedUsers,
appIds: selectedApps, appIds: selectedApps,
@ -214,8 +212,8 @@
const downloadLogs = async () => { const downloadLogs = async () => {
try { try {
window.location = auditLogs.getDownloadUrl({ window.location = auditLogs.getDownloadUrl({
startDate, startDate: dateRange[0],
endDate, endDate: dateRange[1],
fullSearch: logSearchTerm, fullSearch: logSearchTerm,
userIds: selectedUsers, userIds: selectedUsers,
appIds: selectedApps, appIds: selectedApps,
@ -302,21 +300,9 @@
</div> </div>
<div class="date-picker"> <div class="date-picker">
<DatePicker <DateRangePicker
value={startDate} value={dateRange}
label="From" on:change={e => (dateRange = e.detail)}
enableTime={false}
on:change={e => {
startDate = e.detail
}}
/>
<DatePicker
value={endDate}
label="Until"
enableTime={false}
on:change={e => {
endDate = e.detail
}}
/> />
</div> </div>
<div class="freeSearch"> <div class="freeSearch">
@ -506,9 +492,9 @@
min-width: 100px; min-width: 100px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
gap: var(--spacing-l);
} }
.date-picker :global(> *) { .date-picker :global(.date-range-picker),
.date-picker :global(.spectrum-Form-item) {
flex: 1 1 auto; flex: 1 1 auto;
width: 0; width: 0;
} }