@@ -150,6 +150,7 @@ public class MessageBrowser extends javax.swing.JPanel {
150150 private String channelId ;
151151 protected List <String > channelIds = new ArrayList <String >();
152152 private String channelName ;
153+ private MessageBrowserRecentFilterStore recentFilterStore ;
153154 private boolean isChannelDeployed ;
154155 private boolean isCURESPHILoggingOn ;
155156 protected boolean isChannelMessagesPanelFirstLoadSearch ;
@@ -331,6 +332,7 @@ public void loadChannel(MessageBrowserChannelModel channelModel) {
331332
332333 this .channelId = channelId ;
333334 this .channelName = channelName ;
335+ this .recentFilterStore = new MessageBrowserRecentFilterStore (channelId );
334336 this .connectors = connectors ;
335337 this .connectors .put (null , "Deleted Connectors" );
336338 initMetaDataColumns (channelModel );
@@ -340,6 +342,7 @@ public void loadChannel(MessageBrowserChannelModel channelModel) {
340342 resetSearchCriteria ();
341343 advancedSearchPopup .setSelectedMetaDataIds (selectedMetaDataIds );
342344 updateAdvancedSearchButtonFont ();
345+ recentFiltersButton .setEnabled (!recentFilterStore .getRecentFilters ().isEmpty ());
343346
344347 lastUserSelectedMessageType = "Raw" ;
345348 updateMessageRadioGroup ();
@@ -452,6 +455,75 @@ public void updateAdvancedSearchButtonFont() {
452455 }
453456 }
454457
458+ private void restoreRecentFilter () {
459+ // Multi-channel browse may be null
460+ if (recentFilterStore == null ) return ;
461+
462+ JPopupMenu popupMenu = new JPopupMenu ();
463+ for (MessageFilter filter : recentFilterStore .getRecentFilters ()) {
464+ var menuItem = new JMenuItem (filter .toString (connectors , "; " , /* includeEmptyCriteria: */ false ));
465+ menuItem .addActionListener (e -> applyMessageFilter (filter ));
466+ popupMenu .add (menuItem );
467+ }
468+ popupMenu .show (recentFiltersButton , 0 , recentFiltersButton .getHeight ());
469+ }
470+
471+ private void applyMessageFilter (MessageFilter filter ) {
472+ resetSearchCriteria ();
473+
474+ boolean allDay = inferAllDay (filter );
475+
476+ mirthDatePicker1 .setDate ((filter .getStartDate () == null ) ? null : filter .getStartDate ().getTime ());
477+ mirthDatePicker2 .setDate ((filter .getEndDate () == null ) ? null : filter .getEndDate ().getTime ());
478+ allDayCheckBox .setSelected (allDay );
479+ mirthTimePicker1 .setEnabled (mirthDatePicker1 .getDate () != null && !allDay );
480+ mirthTimePicker2 .setEnabled (mirthDatePicker2 .getDate () != null && !allDay );
481+
482+ if (filter .getStartDate () != null ) {
483+ mirthTimePicker1 .setDate (new SimpleDateFormat ("HH:mm" ).format (filter .getStartDate ().getTime ()));
484+ }
485+ if (filter .getEndDate () != null && !allDay ) {
486+ mirthTimePicker2 .setDate (new SimpleDateFormat ("HH:mm" ).format (filter .getEndDate ().getTime ()));
487+ }
488+
489+ textSearchField .setText (StringUtils .defaultString (filter .getTextSearch ()));
490+ regexTextSearchCheckBox .setSelected (Boolean .TRUE .equals (filter .getTextSearchRegex ()));
491+
492+ Set <Status > statuses = filter .getStatuses ();
493+ statusBoxReceived .setSelected (statuses != null && statuses .contains (Status .RECEIVED ));
494+ statusBoxTransformed .setSelected (statuses != null && statuses .contains (Status .TRANSFORMED ));
495+ statusBoxFiltered .setSelected (statuses != null && statuses .contains (Status .FILTERED ));
496+ statusBoxQueued .setSelected (statuses != null && statuses .contains (Status .QUEUED ));
497+ statusBoxPending .setSelected (statuses != null && statuses .contains (Status .PENDING ));
498+ statusBoxSent .setSelected (statuses != null && statuses .contains (Status .SENT ));
499+ statusBoxError .setSelected (statuses != null && statuses .contains (Status .ERROR ));
500+
501+ advancedSearchPopup .applyFilter (filter );
502+ updateAdvancedSearchButtonFont ();
503+ updateFilterButtonFont (Font .BOLD );
504+ }
505+
506+ private boolean inferAllDay (MessageFilter filter ) {
507+ if (filter == null ) {
508+ return false ;
509+ }
510+
511+ Calendar endDate = filter .getEndDate ();
512+ if (endDate != null ) {
513+ return endDate .get (Calendar .HOUR_OF_DAY ) == 23
514+ && endDate .get (Calendar .MINUTE ) == 59
515+ && endDate .get (Calendar .SECOND ) == 59
516+ && endDate .get (Calendar .MILLISECOND ) == 999 ;
517+ }
518+
519+ Calendar startDate = filter .getStartDate ();
520+ return startDate != null
521+ && startDate .get (Calendar .HOUR_OF_DAY ) == 0
522+ && startDate .get (Calendar .MINUTE ) == 0
523+ && startDate .get (Calendar .SECOND ) == 0
524+ && startDate .get (Calendar .MILLISECOND ) == 0 ;
525+ }
526+
455527 public String getChannelId () {
456528 return channelId ;
457529 }
@@ -654,6 +726,13 @@ protected boolean generateMessageFilter() {
654726 advancedSearchPopup .applySelectionsToFilter (messageFilter );
655727 selectedMetaDataIds = messageFilter .getIncludedMetaDataIds ();
656728
729+ if (recentFilterStore != null && !messageFilter .isEmpty ()) {
730+ recentFilterStore .addRecentFilter (messageFilter );
731+ recentFiltersButton .setEnabled (true );
732+ }
733+
734+ // To keep page results consistent, the search is "capped" to the most
735+ // recent message that has been received by the channel.
657736 if (messageFilter .getMaxMessageId () == null ) {
658737 try {
659738 Long maxMessageId = parent .mirthClient .getMaxMessageId (channelId );
@@ -684,7 +763,7 @@ protected void runSearch() {
684763 clearCache ();
685764 loadPageNumber (1 );
686765
687- updateSearchCriteriaPane ( );
766+ lastSearchCriteria . setText ( messageFilter . toString ( connectors , " \n " , /* includeEmptyCriteria: */ true ) );
688767 auditSearch ();
689768 }
690769 }
@@ -2648,6 +2727,11 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
26482727 }
26492728 });
26502729
2730+ recentFiltersButton = new javax .swing .JButton ();
2731+ recentFiltersButton .setText ("Recent..." );
2732+ recentFiltersButton .setEnabled (false );
2733+ recentFiltersButton .addActionListener (e -> restoreRecentFilter ());
2734+
26512735 statusBoxFiltered .setBackground (new java .awt .Color (255 , 255 , 255 ));
26522736 statusBoxFiltered .setText ("FILTERED" );
26532737 statusBoxFiltered .setFont (new java .awt .Font ("Lucida Grande" , 0 , 11 )); // NOI18N
@@ -2775,8 +2859,9 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
27752859 .addPreferredGap (javax .swing .LayoutStyle .ComponentPlacement .RELATED )
27762860 .addGroup (jPanel1Layout .createParallelGroup (javax .swing .GroupLayout .Alignment .LEADING )
27772861 .addComponent (allDayCheckBox , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )
2778- .addComponent (filterButton , javax .swing .GroupLayout .PREFERRED_SIZE , 63 , javax .swing .GroupLayout .PREFERRED_SIZE )
2779- .addComponent (regexTextSearchCheckBox , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE ))
2862+ .addComponent (recentFiltersButton , javax .swing .GroupLayout .PREFERRED_SIZE , 63 , javax .swing .GroupLayout .PREFERRED_SIZE )
2863+ .addComponent (regexTextSearchCheckBox , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )
2864+ .addComponent (filterButton , javax .swing .GroupLayout .PREFERRED_SIZE , 63 , javax .swing .GroupLayout .PREFERRED_SIZE ))
27802865 .addPreferredGap (javax .swing .LayoutStyle .ComponentPlacement .UNRELATED )
27812866 .addGroup (jPanel1Layout .createParallelGroup (javax .swing .GroupLayout .Alignment .LEADING )
27822867 .addComponent (statusBoxQueued , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )
@@ -2830,7 +2915,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
28302915 .addComponent (mirthTimePicker2 , javax .swing .GroupLayout .Alignment .TRAILING , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )
28312916 .addGroup (jPanel1Layout .createParallelGroup (javax .swing .GroupLayout .Alignment .BASELINE )
28322917 .addComponent (mirthDatePicker2 , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )
2833- .addComponent (jLabel2 , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )))
2918+ .addComponent (jLabel2 , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE ))
2919+ .addComponent (recentFiltersButton ))
28342920 .addGap (7 , 7 , 7 )
28352921 .addGroup (jPanel1Layout .createParallelGroup (javax .swing .GroupLayout .Alignment .BASELINE )
28362922 .addComponent (textSearchField , javax .swing .GroupLayout .PREFERRED_SIZE , javax .swing .GroupLayout .DEFAULT_SIZE , javax .swing .GroupLayout .PREFERRED_SIZE )
@@ -3110,6 +3196,7 @@ private void textSearchFieldActionPerformed(java.awt.event.ActionEvent evt) {//G
31103196 private javax .swing .JLabel processedResponseLabel ;
31113197 private javax .swing .JLabel processedResponseStatusLabel ;
31123198 private com .mirth .connect .client .ui .components .MirthSyntaxTextArea processedResponseStatusTextArea ;
3199+ private javax .swing .JButton recentFiltersButton ;
31133200 private com .mirth .connect .client .ui .components .MirthCheckBox regexTextSearchCheckBox ;
31143201 private javax .swing .JButton resetButton ;
31153202 private javax .swing .JLabel responseLabel ;
0 commit comments