Skip to content

[APP-526] feat: Use NBS components for Advanced Filter UI#3315

Open
emyl3 wants to merge 39 commits into
mainfrom
el/app-526/adv-filter-nbs-components
Open

[APP-526] feat: Use NBS components for Advanced Filter UI#3315
emyl3 wants to merge 39 commits into
mainfrom
el/app-526/adv-filter-nbs-components

Conversation

@emyl3

@emyl3 emyl3 commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Description

  • Use NBS components from design system for the advanced filter
  • This PR does not address displaying the error handling in a nice way. All validation errors are in an Alert.

Screenshot 📸

Screenshot 2026-06-12 at 16 03 54 Screenshot 2026-06-12 at 16 04 00

Tickets

Checklist before requesting a review

  • PR focuses on a single story
  • Code has been fully tested to meet acceptance criteria
  • PR is reasonably small and reviewable (Generally less than 10 files and 500 changed lines)
  • All new functions/classes/components reasonably small
  • Functions/classes/components focused on one responsibility
  • Code easy to understand and modify (clarity over concise/clever)
  • PRs containing TypeScript follow the Do's and Don'ts
  • PR does not contain hardcoded values (Uses constants)
  • All code is covered by unit or feature tests

@emyl3 emyl3 force-pushed the el/app-526/adv-filter-nbs-components branch 2 times, most recently from 2e9574c to 33c1d00 Compare June 12, 2026 18:31
Comment thread apps/modernization-ui/src/design-system/select/single/Select.tsx Outdated

const dateRangePickerRef = useRef<HTMLDivElement>(null);

useLayoutEffect(() => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Had to remove since it was causing wonkiness when having multiple date range pickers

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(q, nb): Given that, is the dateRangePickerRef still needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed!

@emyl3 emyl3 force-pushed the el/app-526/adv-filter-nbs-components branch from 33c1d00 to 736da60 Compare June 12, 2026 21:06
@emyl3 emyl3 marked this pull request as ready for review June 15, 2026 12:18
@emyl3 emyl3 requested a review from a team as a code owner June 15, 2026 12:18
@emyl3 emyl3 requested review from JordanGuinn and brick-green and removed request for a team June 15, 2026 12:18
Comment on lines +23 to +31
svg {
fill: colors.$error;
}

&:hover {
svg {
fill: colors.$error-dark;
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit, maybe-b): can we use the "destructive" option instead of custom styling here?

another trash/delete icon in ManageSectionTile.tsx looks like


                                <Button
                                    type="button"
                                    className={styles.iconBtn}
                                    outline
                                    disabled={onAction}
                                    onClick={() => {
                                        setSelectedForDelete(section);
                                        setOnAction(true);
                                    }}
                                >
                                    <Icon.Delete data-testId="deleteIcon" style={{ cursor: 'pointer' }} size={3} />
                                </Button>

I wonder if we should be coalescing on this format?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the destructive prop on the button and removed that styling!
The button in ManageSectionTile.tsx looks slightly different than the designs so I am leaning towards keeping the current implementation as-is. What do you think?

Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/AdvancedFilter.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/AdvancedFilter.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/AdvancedFilter.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/AdvancedFilter.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/ValueEditor.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/ValueSetSelector.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/report-configuration-page.module.scss Outdated
Comment thread apps/modernization-ui/src/design-system/date/criteria/range/DateRangeField.tsx Outdated
emyl3 and others added 3 commits June 22, 2026 10:08
Co-authored-by: Mary McGrath <m.c.mcgrath13@gmail.com>
rules: [{ id: crypto.randomUUID(), field: '~', operator: '~', value: '' }],
};

type NbsOperator = Operator & { nbsCd: string };

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ moved to a separate operators.ts file

@emyl3 emyl3 marked this pull request as ready for review June 22, 2026 21:38
@emyl3 emyl3 requested a review from mcmcgrath13 June 22, 2026 21:38

@JordanGuinn JordanGuinn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handful of questions/thoughts, but this is looking good!!

@@ -0,0 +1,17 @@
import React from 'react';
import { ActionProps } from 'react-querybuilder';
import { Button } from '../../../../../design-system/button';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(thought, super-nb): ENTIRELY unrelated to this PR, but it'd be great if we could get path aliasing working at some point, and remove the need to traverse up the codebase like this for some of our dependencies!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Agree! Do you prefer I create a separate ticket to keep track of this or just a good thing to keep in mind when we are out of the crunch period? 👀

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A tech debt ticket couldn't hurt! Thanks Elisa 🙏

import { ValueInput } from './ValueInput.tsx';

const ValueEditor = (props: ValueEditorProps<ValueSetMetadata & FullField>) => {
const ValueEditor = (props: ValueEditorProps<ValueSetMetadata & FullField & FullOperator>) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit, nb): Thoughts on renaming our ValueEditor something that isn't identical to what's provided by react-querybuilder? Just to indicate that they are slightly different, and remove the potential for anyone using the react-querybuilder version by mistake

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to ValueEditorSwitch 😅 let me know if you have a different name in mind 👀

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me!

if (isRuleType(rule)) {
const { id, field, operator, value, label } = rule;

if (!id) return; // no key for the map, shouldn't happen in practice

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit, nb): I wonder if we want to log a warning or throw or something here, if this shouldn't happen in practice?

@emyl3 emyl3 Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a console.warn! Thank you!!

result[id] = { valid: true };

// empty rules are fine
if (!field || field === '~') return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(q, nb): Out of curiosity, why are empty rules fine? Do they get compacted at a later point prior to hitting the API?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It gets ignored and we do not send an empty rule over.

Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/ValueInput.tsx Outdated
@@ -0,0 +1,65 @@
export const validateDateRange = (value, field) => {
if (rangeValuesMissing(value)) return getRangeValErrorMsg(field, false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(thought, nb): I feel like there's gotta be a way to assert the presence of value[0] and value[1] here with an assertion on rangeValuesMissing, but a thought for another time!

const fromDate = new Date(value[0]!); // can't be undefined because of above checks
const toDate = new Date(value[1]!); // can't be undefined because of above checks
for (const { date, ind, str } of [
{ date: fromDate, ind: 0, str: 'From' },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit, nb): Could we just reference the underlying value in the array, rather than including an index in the list we're iterating against?

Also, given this is just two entries, it could arguably be a bit simpler if it was just two if statements, without the for loop entirely?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took your first suggestion and passed the value directly instead of the index! Thank you!!

return typeof val === 'number';
};

export const isDateFormat = (val) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(q, nb): I think date-fns supports something like this out of the box? Assuming it supports the formats we're matching against here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified it to use date-fns to validate the date and caught some edge cases in the process -- thank you!!

@emyl3 emyl3 requested a review from a team as a code owner June 25, 2026 13:51
@emyl3

emyl3 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@JordanGuinn @brick-green ready for re-review!

@emyl3 emyl3 requested a review from JordanGuinn June 25, 2026 14:42

@JordanGuinn JordanGuinn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! 🚀

Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/validator.ts Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/advanced/ValueInput.tsx Outdated
Comment thread apps/modernization-ui/src/apps/report/run/filters/utils/rangeValidator.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants