Skip to content

Commit

Permalink
Feat: LCFS - Implement Accessibility & Functional Enhancements for AG…
Browse files Browse the repository at this point in the history
… Grid Filtering Components #1585
  • Loading branch information
prv-proton committed Jan 7, 2025
1 parent 71a6856 commit 747384f
Show file tree
Hide file tree
Showing 22 changed files with 284 additions and 198 deletions.
16 changes: 15 additions & 1 deletion backend/lcfs/web/api/transaction/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,23 @@ def apply_transaction_filters(self, pagination, conditions):
else:
# Handle other filters
field = get_field_for_filter(TransactionView, filter.field)
filter_value = filter.filter
# check if the date string is selected for filter
if filter.filter is None:
filter_value = [
datetime.strptime(filter.date_from, "%Y-%m-%d %H:%M:%S").strftime(
"%Y-%m-%d"
)
]
if filter.date_to:
filter_value.append(
datetime.strptime(filter.date_to, "%Y-%m-%d %H:%M:%S").strftime(
"%Y-%m-%d"
)
)
conditions.append(
apply_filter_conditions(
field, filter.filter, filter.type, filter.filter_type
field, filter_value, filter.type, filter.filter_type
)
)

Expand Down
17 changes: 10 additions & 7 deletions backend/lcfs/web/api/user/repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,14 +607,17 @@ def _apply_login_history_filters(self, query, pagination):
filter_value = filter.filter
filter_option = filter.type
filter_type = filter.filter_type
if filter.field is not None:
if filter.field == "is_login_successful":
filter_option = "true" if filter_value == "Success" else "false"
field = get_field_for_filter(UserLoginHistory, "is_login_successful")
elif filter.field is not None:
field = get_field_for_filter(UserLoginHistory, filter.field)
if field is not None:
condition = apply_filter_conditions(
field, filter_value, filter_option, filter_type
)
if condition is not None:
conditions.append(condition)
if field is not None:
condition = apply_filter_conditions(
field, filter_value, filter_option, filter_type
)
if condition is not None:
conditions.append(condition)

query = query.where(and_(*conditions))
# Apply ordering
Expand Down
13 changes: 8 additions & 5 deletions frontend/src/components/BCDataGrid/BCDataGridServer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { useApiService } from '@/services/useApiService'
import BCAlert from '@/components/BCAlert'
import BCBox from '@/components/BCBox'
import DataGridLoading from '@/components/DataGridLoading'
import { BCPagination } from './components'
import { AccessibleHeader, BCPagination } from './components'
import { useTranslation } from 'react-i18next' // Import useTranslation
// Register the required AG Grid modules for row model and CSV export functionality
ModuleRegistry.registerModules([ClientSideRowModelModule, CsvExportModule])
Expand Down Expand Up @@ -122,7 +122,7 @@ const BCDataGridServer = ({
[apiService, apiEndpoint, page, size, sortModel]
)

// Hanlde page change
// Handle page change
const handleChangePage = useCallback((event, newPage) => {
setLoading(true)
setPage(newPage + 1)
Expand Down Expand Up @@ -189,7 +189,7 @@ const BCDataGridServer = ({
let localFilteredData = [...rowData]

// Handle the 'type' filter locally
const typeFilter = filterModel['type']
const typeFilter = filterModel.type

if (typeFilter) {
const filterText = typeFilter.filter?.toLowerCase() || ''
Expand All @@ -199,7 +199,7 @@ const BCDataGridServer = ({
})

// Remove 'type' from the filter model to prevent backend filtering
delete filterModel['type']
delete filterModel.type
}

// Handle other filters (backend filters)
Expand Down Expand Up @@ -269,10 +269,11 @@ const BCDataGridServer = ({
suppressDragLeaveHidesColumns: true,
suppressMovableColumns: true,
suppressColumnMoveAnimation: false,
rowSelection: 'multiple',
animateRows: true,
suppressPaginationPanel: true,
suppressScrollOnNewData: true,
suppressColumnVirtualisation: true,
enableBrowserTooltips: true,
suppressCsvExport: false,
// enableCellTextSelection: true, // enables text selection on the grid
// ensureDomOrder: true,
Expand All @@ -288,6 +289,8 @@ const BCDataGridServer = ({

// Memorized default column definition parameters
const defaultColDefParams = useMemo(() => ({
headerComponent: AccessibleHeader,
suppressHeaderFilterButton: true,
resizable: true,
sortable: true,
filter: true,
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/BCDataGrid/BCGridBase.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ export const BCGridBase = forwardRef(({ autoSizeStrategy, ...props }, ref) => {
suppressDragLeaveHidesColumns
suppressMovableColumns
suppressColumnMoveAnimation={false}
reactiveCustomComponents
suppressCsvExport={false}
suppressColumnVirtualisation={true}
enableBrowserTooltips={true}
suppressPaginationPanel
suppressScrollOnNewData
getRowStyle={getRowStyle}
rowHeight={45}
headerHeight={45}
headerHeight={40}
{...props}
/>
</>
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/BCDataGrid/BCGridViewer.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BCAlert, { FloatingAlert } from '@/components/BCAlert'
import BCBox from '@/components/BCBox'
import { BCGridBase } from '@/components/BCDataGrid/BCGridBase'
import { BCPagination } from '@/components/BCDataGrid/components'
import { AccessibleHeader, BCPagination } from '@/components/BCDataGrid/components'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-material.css'
import { useCallback, useMemo, useRef, useState } from 'react'
Expand Down Expand Up @@ -161,6 +161,8 @@ export const BCGridViewer = ({

const defaultColDefParams = useMemo(
() => ({
headerComponent: AccessibleHeader,
suppressHeaderFilterButton: true,
resizable: true,
sortable: true,
filter: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import {
} from '@mui/icons-material'
import { DatePicker } from '@mui/x-date-pickers'
import { format, isValid } from 'date-fns'
import dayjs from 'dayjs'
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'

export const BCDateFloatingFilter = ({
model,
onModelChange,
disabled = false,
minDate = '2013-01-01',
maxDate = '2040-01-01',
initialFilterType = 'equals',
label = 'Select Date'
}) => {
Expand Down Expand Up @@ -52,7 +57,7 @@ export const BCDateFloatingFilter = ({
return
}

if (model.filter) {
if (model?.dateFrom) {
const date = new Date(model.dateFrom)
setSelectedDate(isValid(date) ? date : null)
}
Expand All @@ -67,60 +72,68 @@ export const BCDateFloatingFilter = ({
aria-labelledby="date-picker-label"
sx={{
border: 'none',
'& .MuiOutlinedInput-root': { p: 0 },
'& .MuiOutlinedInput-notchedOutline': { border: 'none' },
'& .Mui-focused': {
border: '1px solid #495057',
boxShadow: '0 0 0 1px #495057'
}
}}
>
<DatePicker
id="date-picker"
aria-label="Date Picker"
aria-describedby="date-picker-description"
sx={{ border: 'none', borderBottom: '2px solid #495057' }}
value={selectedDate}
onChange={handleChange}
open={open}
onOpen={handleOpen}
onClose={handleClose}
disabled={disabled}
format="yyyy-MM-dd"
slotProps={{
textField: {
size: 'small',
label,
InputProps: {
startAdornment: (
<InputAdornment position="start">
<IconButton
size="small"
edge="start"
onClick={() => setOpen(true)}
aria-label="Open calendar"
>
<CalendarIcon fontSize="small" />
</IconButton>
</InputAdornment>
),
endAdornment: selectedDate && (
<InputAdornment position="end">
<IconButton
size="small"
onClick={handleClear}
onMouseDown={(event) => event.stopPropagation()}
edge="end"
aria-label="Clear date"
>
<ClearIcon fontSize="small" />
</IconButton>
</InputAdornment>
)
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
id="date-picker"
aria-label="Date Picker"
aria-describedby="date-picker-description"
sx={{
border: 'none',
borderBottom: '4px solid #495057',
}}
value={selectedDate}
minDate={dayjs(minDate)}
maxDate={dayjs(maxDate)}
onChange={handleChange}
open={open}
onOpen={handleOpen}
onClose={handleClose}
disabled={disabled}
format="YYYY-MM-DD"
slotProps={{
textField: {
size: 'small',
label,
InputProps: {
startAdornment: (
<InputAdornment position="start">
<IconButton
sx={{ marginLeft: 0, paddingLeft: '6px' }}
size="small"
edge="start"
onClick={() => setOpen(true)}
aria-label="Open calendar"
>
<CalendarIcon fontSize="small" />
</IconButton>
</InputAdornment>
),
endAdornment: selectedDate && (
<InputAdornment position="end">
<IconButton
sx={{ marginRight: 0, paddingRight: '6px' }}
size="small"
onClick={handleClear}
onMouseDown={(event) => event.stopPropagation()}
edge="end"
aria-label="Clear date"
>
<ClearIcon fontSize="small" />
</IconButton>
</InputAdornment>
)
}
}
}
}}
/>
}}
/>
</LocalizationProvider>
</FormControl>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export const BCSelectFloatingFilter = ({
} else {
setSelectedValues([model?.filter])
}
}, [model, initialSelectedValues])
}, [model])

return (
<div
Expand Down Expand Up @@ -128,6 +128,7 @@ export const BCSelectFloatingFilter = ({
onClick={handleClear}
onMouseDown={(event) => event.stopPropagation()}
aria-label="Clear selection"
tabIndex={-1}
>
<ClearIcon fontSize="small" />
</IconButton>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const AccessibleHeader = (props) => {
return (
<div role="columnheader" aria-label={props.column.colDef.headerName} data-ref="columnWrapper">
<span className="ag-header-cell-text">{props.column.colDef.headerName}</span>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const RequiredHeader = (props) => {
return (
<div>
<div role="columnheader" aria-label={props.column.colDef.headerName}>
<span style={{ color: 'red' }}>*</span>
<span>{props.column.colDef.headerName}</span>
<span className="ag-header-cell-text">{props.column.colDef.headerName}</span>
</div>
)
}
1 change: 1 addition & 0 deletions frontend/src/components/BCDataGrid/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { DateRangeCellEditor } from './Editors/DateRangeCellEditor'
export { ActionsRenderer } from './Renderers/ActionsRenderer'
export { ActionsRenderer2 } from './Renderers/ActionsRenderer2'
export { RequiredHeader } from './Renderers/RequiredHeader'
export { AccessibleHeader } from './Renderers/AccessibleHeader'
export { ValidationRenderer } from './Renderers/ValidationRenderer'
export { ValidationRenderer2 } from './Renderers/ValidationRenderer2'
export { BCColumnSetFilter } from './Filters/BCColumnSetFilter'
Expand Down
7 changes: 7 additions & 0 deletions frontend/src/constants/statuses.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,10 @@ export const FUEL_CODE_STATUSES = {
export function getAllFuelCodeStatuses() {
return Object.values(FUEL_CODE_STATUSES)
}

export const TRANSACTION_TYPES = {
TRANSFER: 'Transfer',
INITIATIVE_AGREEMENT: 'InitiativeAgreement',
COMPLIANCE_REPORT: 'ComplianceReport',
ADMINISTRATIVE_ADJUSTMENT: 'AdminAdjustment'
}
Loading

0 comments on commit 747384f

Please sign in to comment.