Skip to content

[ReponseOps][Reporting] Add search functionality to scheduled reports list#243841

Merged
cnasikas merged 15 commits intoelastic:mainfrom
umbopepato:2235-scheduled-reports-list-filters
Dec 3, 2025
Merged

[ReponseOps][Reporting] Add search functionality to scheduled reports list#243841
cnasikas merged 15 commits intoelastic:mainfrom
umbopepato:2235-scheduled-reports-list-filters

Conversation

@umbopepato
Copy link
Member

📄 Summary

  • Add a search query parameter to the list scheduled reports endpoint
  • Forward the search string to the SO find call, searching on fields title and createdBy
  • Add a search field and search button to the scheduled reports page

🧪 Verification steps

  1. Create multiple scheduled reports with different titles and authors
  2. Verify that searching by title and author filters the table accordingly

📷 Screenshots

image

⏪ Backport rationale

Not backporting since this is a new functionality

🔗 References

Closes https://github.com/elastic/kibana-team/issues/2235
Closes https://github.com/elastic/kibana-team/issues/2234

Release Notes

Added the possibility to search scheduled reports by title and creator.

☑️ Checklist

  • Any text added follows EUI's writing guidelines, uses sentence case text and includes i18n support
  • Documentation was added for features that require explanation or tutorials
  • Unit or functional tests were updated or added to match the most common scenarios
  • If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the docker list
  • This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The release_note:breaking label should be applied in these situations.
  • Flaky Test Runner was used on any tests changed
  • The PR description includes the appropriate Release Notes section, and the correct release_note:* label is applied per the guidelines
  • Review the backport guidelines and apply applicable backport:* labels.
@umbopepato umbopepato requested a review from a team as a code owner November 21, 2025 15:15
@umbopepato umbopepato added backport:skip This PR does not require backporting Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// release_note:feature Makes this part of the condensed release notes v9.3.0 labels Nov 21, 2025
@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@elastic-vault-github-plugin-prod elastic-vault-github-plugin-prod bot requested a review from a team as a code owner November 21, 2025 15:30
Copy link

@joana-cps joana-cps left a comment

Choose a reason for hiding this comment

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

Can we drop the search button for consistency with other pages?
Screenshot 2025-11-24 at 10 23 21
Screenshot 2025-11-24 at 10 23 06
Screenshot 2025-11-24 at 10 23 00
Screenshot 2025-11-24 at 10 22 48

I see that we use the refresh button in some pages 🤔 but we don't use this search button.

type: SCHEDULED_REPORT_SAVED_OBJECT_TYPE,
page,
perPage: size,
search,
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please update the unit tests accordingly? 👀

Copy link
Member

Choose a reason for hiding this comment

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

+1

Copy link
Member Author

Choose a reason for hiding this comment

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

search: string;
}

export const ReportSchedulesTable = (props: { apiClient: ReportingAPIClient }) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am confused by this, how was apiClient here without a warning? I don't see it used anywhere else.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was surprised too! But it seems like the apiClient wasn't used anymore

@adcoelho
Copy link
Contributor

I found a small bug when clicking the "clear text" icon on the search bar.

Screenshot 2025-11-24 at 13 25 11

This button deletes the search, but does not update the table immediately; it still requires an enter keypress.

onChange={tableOnChangeCallback}
rowProps={() => ({ 'data-test-subj': 'scheduledReportRow' })}
/>
<EuiFlexItem grow={false}>
Copy link
Contributor

@adcoelho adcoelho Nov 24, 2025

Choose a reason for hiding this comment

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

NBD but you could also update 'renders table correctly' in report_schedules_table.test.tsx to expect the search bar.

Maybe also asserting search gets called with text on button press in a different unit test.

Copy link
Member

@cnasikas cnasikas Nov 28, 2025

Choose a reason for hiding this comment

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

+1, let's put some unit tests.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added tests! ✅

Copy link
Contributor

@adcoelho adcoelho left a comment

Choose a reason for hiding this comment

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

Overall LGTM. I found a small bug and think 2 unit tests could be added 🙌

Copy link
Member

@cnasikas cnasikas left a comment

Choose a reason for hiding this comment

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

Code review only. I will test and review again after @joana-cps feedback is addressed.

placeholder={i18n.translate(
'xpack.reporting.schedules.table.searchPlaceholderTitle',
{
defaultMessage: 'Search scheduled reports by title or creator',
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
defaultMessage: 'Search scheduled reports by title or creator',
defaultMessage: 'Search scheduled reports',
useState<boolean>(false);
const [isDeleteModalConfirmationOpen, setIsDeleteModalConfirmationOpen] =
useState<boolean>(false);
const [searchText, setSearchText] = useState('');
Copy link
Member

Choose a reason for hiding this comment

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

Instead of having a new variable for the search, could we use the queryParams? The onChange can call the setQueryParams.

Copy link
Member Author

Choose a reason for hiding this comment

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

I though I needed an intermediate state to save the text and update the query params on all relevant events, but turns out it works perfectly with onSearch, thanks for the suggestion! 😊

}
)}
value={searchText}
onChange={(event) => {
Copy link
Member

Choose a reason for hiding this comment

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

nit: Let's use a useCallback.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed in favor of updating query params directly

@kibanamachine
Copy link
Contributor

Flaky Test Runner Stats

🎉 All tests passed! - kibana-flaky-test-suite-runner#9945

[✅] x-pack/platform/test/reporting_api_integration/reporting_and_security.config.ts: 200/200 tests passed.

see run history

@umbopepato umbopepato force-pushed the 2235-scheduled-reports-list-filters branch from 7287089 to 8ef978a Compare December 2, 2025 13:47
@umbopepato
Copy link
Member Author

Can we drop the search button for consistency with other pages? Screenshot 2025-11-24 at 10 23 21 Screenshot 2025-11-24 at 10 23 06 Screenshot 2025-11-24 at 10 23 00 Screenshot 2025-11-24 at 10 22 48

I see that we use the refresh button in some pages 🤔 but we don't use this search button.

This Search button resulted from a reasoning about invalidating/refetching differences between this and the other pages but I agree it doesn't make too much sense to compromise consistency. So I made sure to replicate a very similar behavior and switched to using the same button ✅

@umbopepato
Copy link
Member Author

umbopepato commented Dec 2, 2025

I found a small bug when clicking the "clear text" icon on the search bar.

Screenshot 2025-11-24 at 13 25 11 This button deletes the search, but does not update the table immediately; it still requires an enter keypress.

Yeah I was trying to rely solely on onSearch as a trigger, but I quickly realized that doesn't make too much sense (see here also) so I added blur as an additional trigger, and switched to a more consistent Refresh button that actually refetches the query

},
],
schemas: {
forwardCompatibility: rawScheduledReportSchemaV5.extends({}, { unknowns: 'ignore' }),
Copy link
Member Author

@umbopepato umbopepato Dec 2, 2025

Choose a reason for hiding this comment

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

I’ve never found myself having to introduce a new SO version that only changes the mappings, but not the schema. SO docs showed an example without schemas at all, but CI errored because of missing forwardCompatibility, so I added it. But using the schema v4 in model version 5 didn't feel right, so I advanced the schema version to 5, just re-exporting all from schema 4. I don't know if this is the best way to do it, so any suggestion is appreciated

Copy link
Member

Choose a reason for hiding this comment

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

I think what you did here is fine.

},
},
});
const mockValidateEmailAddresses = jest.fn().mockReturnValue([]);
Copy link
Member Author

Choose a reason for hiding this comment

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

Like in other tests, this was mocked incorrectly as async, but the original method is sync

},
],
schemas: {
forwardCompatibility: rawScheduledReportSchemaV5.extends({}, { unknowns: 'ignore' }),
Copy link
Member

Choose a reason for hiding this comment

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

I think what you did here is fine.

}
)}
onSearch={updateSearch}
onBlur={onSearchFieldBlur}
Copy link
Member

@cnasikas cnasikas Dec 3, 2025

Choose a reason for hiding this comment

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

It's great to see the search functionality coming together! Regarding the API call trigger: using onBlur for the final search results is likely to create a slightly confusing experience. We generally follow the pattern where the user explicitly signals their intent (e.g., pressing Enter) before firing the main search API call. I suggest we remove it. This will reduce unnecessary API calls and improve UX clarity. Wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

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

To be honest, this came from trying - and failing - to be consistent with other similar pages. Take Maintenance Windows for example, where we trigger searches only onSearch and when the user clears the input. This has some confusing implications too imo, for example if you trigger a search, then change the text without pressing enter, then press 🔄 Refresh, perhaps expecting that it would trigger a search with the changed text 👉 the list is refetched but with the old search text, leading to an inconsistent UI state...

To be even more honest, I think the cleanest experience is what the KQL bar offers: after editing the text, the 🔄 Refresh button changes to ➡️ Update to signal that the last run query doesn't correspond to the current search text and suggests to the user that pressing it not only will trigger a new query, but it will use the new search terms:
image

To get the best of both worlds, I could re-introduce an intermediate state to save the search text, then trigger searches only onSearch and when pressing 🔄 Refresh, making sure to update the search text in the query instead of only refetch()ing it, let me know what you prefer. Otherwise we can always stick to the onSearch + clear behavior of other pages.

(I could also implement the 🔄 Refresh vs ➡️ Update semantics, but we don't use it in other pages so that would lead to inconsistencies)

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for sharing the UX issues we have with the other pages. I was not aware of the UX nuances. I would suggest removing the onBlur handler, merging the PR, and opening an issue to address these UX issues on all of our pages. Wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure! Let's do that then 🙂

@cnasikas cnasikas enabled auto-merge (squash) December 3, 2025 14:40
@elasticmachine
Copy link
Contributor

⏳ Build in-progress, with failures

Failed CI Steps

Test Failures

  • [job] [logs] Jest Tests #21 / ReportSchedulesTable should search schedules with the provided search text on blur
  • [job] [logs] Jest Tests #21 / ReportSchedulesTable should search schedules with the provided search text on blur

History

@cnasikas cnasikas merged commit 1710de6 into elastic:main Dec 3, 2025
13 checks passed
JordanSh pushed a commit to JordanSh/kibana that referenced this pull request Dec 9, 2025
… list (elastic#243841)

## 📄 Summary

- Add a `search` query parameter to the list scheduled reports endpoint
- Forward the search string to the SO find call, searching on fields
`title` and `createdBy`
- Add a search field and search button to the scheduled reports page

<details>
<summary>

## 🧪 Verification steps

</summary>

1. Create multiple scheduled reports with different titles and authors
2. Verify that searching by title and author filters the table
accordingly

</details>

<details>
<summary>

## 📷 Screenshots

</summary>

<img width="1236" height="544" alt="image"
src="https://github.com/user-attachments/assets/882e5c72-c684-4b16-8ee9-d5ca85d7a095"
/>

</details>

## ⏪ Backport rationale

Not backporting since this is a new functionality

## 🔗 References

Closes elastic/kibana-team#2235
Closes elastic/kibana-team#2234

## Release Notes

Added the possibility to search scheduled reports by title and creator.

## ☑️ Checklist

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] ~~If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~~
- [ ] ~~This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.~~
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
- [x] Review the [backport
guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)
and apply applicable `backport:*` labels.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting release_note:feature Makes this part of the condensed release notes Team:ResponseOps Platform ResponseOps team (formerly the Cases and Alerting teams) t// v9.3.0

7 participants