Skip to content

Commit

Permalink
Merge pull request #261 from msupply-foundation/256-filter-events-by-…
Browse files Browse the repository at this point in the history
…config

256 filter events by config
  • Loading branch information
lache-melvin authored Nov 22, 2023
2 parents f26163d + 4d2535d commit ae7f78e
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 48 deletions.
2 changes: 2 additions & 0 deletions backend/graphql/notification_event/src/types/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ impl NotificationEventSortInput {
#[derive(Clone, InputObject)]
pub struct NotificationEventFilterInput {
pub id: Option<EqualFilterStringInput>,
pub notification_config_id: Option<EqualFilterStringInput>,
pub search: Option<String>,
pub status: Option<EqualFilterEventStatusInput>,
pub created_at: Option<DatetimeFilterInput>,
Expand All @@ -70,6 +71,7 @@ impl From<NotificationEventFilterInput> for NotificationEventFilter {
fn from(f: NotificationEventFilterInput) -> Self {
NotificationEventFilter {
id: f.id.map(EqualFilter::from),
notification_config_id: f.notification_config_id.map(EqualFilter::from),
search: f.search,
status: f.status.map(|t| map_filter!(t, EventStatus::to_domain)),
created_at: f.created_at.map(DatetimeFilter::from),
Expand Down
12 changes: 12 additions & 0 deletions backend/repository/src/db_diesel/notification_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub type NotificationEvent = NotificationEventRow;
pub struct NotificationEventFilter {
pub id: Option<EqualFilter<String>>,
pub search: Option<String>,
pub notification_config_id: Option<EqualFilter<String>>,
pub status: Option<EqualFilter<NotificationEventStatus>>,
pub created_at: Option<DatetimeFilter>,
}
Expand All @@ -32,6 +33,11 @@ impl NotificationEventFilter {
self
}

pub fn notification_config_id(mut self, filter: EqualFilter<String>) -> Self {
self.id = Some(filter);
self
}

pub fn search(mut self, filter: String) -> Self {
self.search = Some(filter);
self
Expand Down Expand Up @@ -146,10 +152,16 @@ fn create_filtered_query(filter: Option<NotificationEventFilter>) -> BoxedQuery
search,
status,
created_at,
notification_config_id,
} = f;

apply_equal_filter!(query, id, notification_event_dsl::id);
apply_equal_filter!(query, status, notification_event_dsl::status);
apply_equal_filter!(
query,
notification_config_id,
notification_event_dsl::notification_config_id
);
apply_date_time_filter!(query, created_at, notification_event_dsl::created_at);

if let Some(search) = search {
Expand Down
3 changes: 3 additions & 0 deletions frontend/packages/common/src/intl/locales/en/system.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"button.return-to-home": "Home",
"button.return-to-login": "Login",
"button.send-password-reset": "Send Password Reset",
"button.view-recent-events": "View Recent Events",
"config-kind.COLD_CHAIN": "Cold Chain",
"config-kind.SCHEDULED": "Scheduled",
"config-status.DISABLED": "Disabled",
Expand Down Expand Up @@ -38,6 +39,7 @@
"label.edit-parameters": "Edit Parameters",
"label.parameters-as-json": "JSON Parameters",
"label.error": "Error",
"label.filter-by-notification-config": "Filter by Notification Config",
"label.invite-user": "Invite User",
"label.new-recipient": "New Recipient",
"label.new-recipient-list": "New Recipient List",
Expand All @@ -54,6 +56,7 @@
"label.phone-number": "Phone Number",
"label.primary-email": "Primary Email",
"label.remove-members": "Remove members from list",
"label.select-notification-config": "Select Notification Config",
"label.select-notification-type": "Select Notification Type",
"label.select-recipients": "Select Recipients",
"label.send-password-reset": "Send Password Reset",
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/common/src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ export type NotificationEventConnector = {
export type NotificationEventFilterInput = {
createdAt?: InputMaybe<DatetimeFilterInput>;
id?: InputMaybe<EqualFilterStringInput>;
notificationConfigId?: InputMaybe<EqualFilterStringInput>;
search?: InputMaybe<Scalars['String']['input']>;
status?: InputMaybe<EqualFilterEventStatusInput>;
};
Expand Down
157 changes: 110 additions & 47 deletions frontend/packages/system/src/NotificationEvents/ListView/FilterBar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import React, { useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import {
useTranslation,
FilterController,
SearchBar,
Box,
Select,
EventStatus,
useEditModal,
LoadingButton,
FilterIcon,
useUrlQuery,
} from '@notify-frontend/common';
import { NotificationConfigModal } from './NotificationConfigModal';
import { useNotificationConfigs } from '../../Notifications/api';

function relativeStartTime(hoursAgo: string) {
return new Date(Date.now() - parseInt(hoursAgo) * 60 * 60 * 1000);
Expand All @@ -23,6 +29,7 @@ export const FilterBar = ({
}) => {
const t = useTranslation('system');
const [timeRange, setTimeRange] = React.useState('all');
const { isOpen, onClose, onOpen } = useEditModal();

const filterString = (filter.filterBy?.[searchFilterKey] as string) || '';

Expand Down Expand Up @@ -75,55 +82,111 @@ export const FilterBar = ({
return options;
}, []);

return (
<Box
sx={{
justifyContent: 'space-between',
display: 'flex',
}}
>
<SearchBar
placeholder={t('placeholder.search')}
value={filterString}
onChange={newValue =>
filter.onChangeStringRule(searchFilterKey, newValue)
}
/>
const { urlQuery, updateQuery } = useUrlQuery();
const notificationConfigId = urlQuery.notificationConfigId;

<Select
value={statusValue()}
options={statusOptions}
onChange={e => {
if (e.target.value === 'all') {
filter.onClearFilterRule('status');
} else {
filter.onChangeStringFilterRule(
'status',
'equalTo',
e.target.value
);
}
const setFilterConfig = (id: string) => {
updateQuery({ ...urlQuery, notificationConfigId: id });
};

useEffect(() => {
if (!notificationConfigId) {
filter.onClearFilterRule('notificationConfigId');
} else {
filter.onChangeStringFilterRule(
'notificationConfigId',
'equalTo',
notificationConfigId
);
}
}, [notificationConfigId]);

const { data } = useNotificationConfigs({
filterBy: { id: { equalTo: notificationConfigId } },
});
const selectedConfig = notificationConfigId && data?.nodes[0];

return (
<>
{isOpen && (
<NotificationConfigModal
isOpen={isOpen}
onClose={onClose}
setSelectedConfigId={setFilterConfig}
selectedConfigId={notificationConfigId}
/>
)}
<Box
sx={{
gap: '14px',
justifyContent: 'space-between',
display: 'flex',
flexWrap: 'wrap',
}}
/>
<Select
value={timeRange}
options={timeRangeOptions}
onChange={e => {
setTimeRange(e.target.value);
if (e.target.value === 'all') {
filter.onClearFilterRule('createdAt');
} else {
filter.onChangeDateFilterRule(
'createdAt',
'afterOrEqualTo',
relativeStartTime(e.target.value)
);
>
<SearchBar
placeholder={t('placeholder.search')}
value={filterString}
onChange={newValue =>
filter.onChangeStringRule(searchFilterKey, newValue)
}
}}
/>
<Box sx={{ gap: '10px', display: 'flex' }}>
<ActionButtons />
/>
<Box
sx={{
gap: '14px',
display: 'flex',
alignItems: 'center',
}}
>
<Select
value={statusValue()}
options={statusOptions}
onChange={e => {
if (e.target.value === 'all') {
filter.onClearFilterRule('status');
} else {
filter.onChangeStringFilterRule(
'status',
'equalTo',
e.target.value
);
}
}}
/>
<Select
value={timeRange}
options={timeRangeOptions}
onChange={e => {
setTimeRange(e.target.value);
if (e.target.value === 'all') {
filter.onClearFilterRule('createdAt');
} else {
filter.onChangeDateFilterRule(
'createdAt',
'afterOrEqualTo',
relativeStartTime(e.target.value)
);
}
}}
/>

<LoadingButton
isLoading={false}
startIcon={<FilterIcon />}
onClick={() => onOpen()}
variant="outlined"
disableRipple
>
{selectedConfig
? `Events for: ${selectedConfig.title}`
: t('label.filter-by-notification-config')}
</LoadingButton>

<Box sx={{ gap: '10px', display: 'flex' }}>
<ActionButtons />
</Box>
</Box>
</Box>
</Box>
</>
);
};
Loading

0 comments on commit ae7f78e

Please sign in to comment.