77import java .util .Map ;
88import java .util .ResourceBundle ;
99
10+ import org .apache .commons .lang3 .StringUtils ;
11+
1012import com .jfoenix .controls .JFXComboBox ;
1113import com .jfoenix .controls .JFXListView ;
1214
15+ import javafx .application .Platform ;
1316import javafx .event .ActionEvent ;
17+ import javafx .event .Event ;
18+ import javafx .event .EventHandler ;
1419import javafx .fxml .FXML ;
1520import javafx .fxml .Initializable ;
21+ import javafx .geometry .Insets ;
1622import javafx .scene .control .Alert .AlertType ;
1723import javafx .scene .control .DatePicker ;
24+ import javafx .scene .control .ScrollPane ;
25+ import javafx .scene .control .ScrollPane .ScrollBarPolicy ;
26+ import javafx .scene .control .TextField ;
27+ import javafx .scene .input .KeyCode ;
28+ import javafx .scene .input .KeyEvent ;
1829import javafx .scene .layout .AnchorPane ;
30+ import javafx .scene .layout .HBox ;
1931import javafx .scene .layout .StackPane ;
32+ import lombok .extern .slf4j .Slf4j ;
2033import root .common .server .implement .JschServer ;
2134import root .core .domain .AlertLog ;
2235import root .core .domain .JschConnectionInfo ;
3346import root .core .usecase .implement .ServerMonitoringUsecaseImpl ;
3447import root .javafx .CustomView .AlertLogListViewCell ;
3548import root .javafx .CustomView .AlertLogMonitoringSummaryAP ;
49+ import root .javafx .CustomView .NumberTextFormatter ;
50+ import root .javafx .CustomView .TagBar ;
3651import root .javafx .CustomView .dateCell .DisableAfterTodayDateCell ;
3752import root .utils .AlertUtils ;
3853
54+ @ Slf4j
3955public class AlertLogMonitoringMenuController implements Initializable {
4056
4157 /* Dependency Injection */
@@ -60,12 +76,23 @@ public class AlertLogMonitoringMenuController implements Initializable {
6076 @ FXML
6177 StackPane alertLogSummarySP ;
6278
79+ @ FXML
80+ HBox searchKeywordHBox ;
81+
82+ @ FXML
83+ TextField navigatorTF ;
84+
85+ @ FXML
86+ TextField statusTF ;
87+
6388 @ FXML
6489 AnchorPane mainNodataAP ;
6590
6691 @ FXML
6792 AnchorPane summaryNodataAP ;
6893
94+ TagBar tagBar = new TagBar ();
95+
6996 Map <String , AlertLog > alertLogMonitoringResultMap ;
7097
7198 public AlertLogMonitoringMenuController () {
@@ -107,12 +134,20 @@ public void initialize(URL location, ResourceBundle resources) {
107134 }
108135
109136 private void changeAlertLogListViewData (String serverID ) {
137+ // AlertLog ListView
138+ String [] hightlightKeywords = tagBar .getTags ().toArray (new String [0 ]);
139+ alertLogLV .setCellFactory (categoryList -> new AlertLogListViewCell (hightlightKeywords ));
140+
110141 alertLogLV .getItems ().clear ();
111142 AlertLog alertLog = alertLogMonitoringResultMap .get (serverID );
112143 if (alertLog != null ) {
113144 // Alert Log ListView
114145 alertLogLV .getItems ().addAll (alertLog .getAlertLogs ());
115-
146+ Platform .runLater (() -> {
147+ alertLogLV .scrollTo (0 );
148+ alertLogLV .getSelectionModel ().select (0 );
149+ });
150+
116151 // Alert Log Summary
117152 alertLogSummarySP .getChildren ().add (new AlertLogMonitoringSummaryAP (alertLog ));
118153 } else {
@@ -151,8 +186,32 @@ private void initAlertLogMonitoringElements() {
151186 }
152187 });
153188
154- // AlertLog ListView
155- alertLogLV .setCellFactory (categoryList -> new AlertLogListViewCell ());
189+ // AlertLog Navigator
190+ navigatorTF .setTextFormatter (new NumberTextFormatter ());
191+ navigatorTF .setOnKeyReleased (new EventHandler <KeyEvent >() {
192+ @ Override
193+ public void handle (KeyEvent e ) {
194+ if (e .getCode ().equals (KeyCode .ENTER )) {
195+ focusAlertLog (e );
196+ e .consume ();
197+ }
198+ }
199+ });
200+
201+ // Search Keyword Tagbar
202+ ScrollPane tagBarWrapper = new ScrollPane (tagBar );
203+ tagBarWrapper .setStyle ("-fx-border-width: 0.2px; -fx-border-color: gray;" );
204+ tagBarWrapper .getStyleClass ().add ("gray-scrollbar" );
205+ tagBarWrapper .setMaxWidth (375 );
206+ tagBarWrapper .setMinHeight (45 );
207+ tagBarWrapper .setFitToHeight (true );
208+ tagBarWrapper .prefHeightProperty ().bind (searchKeywordHBox .heightProperty ());
209+ tagBarWrapper .setHbarPolicy (ScrollBarPolicy .AS_NEEDED );
210+ HBox .setMargin (tagBarWrapper , new Insets (0 , 0 , 0 , 25 ));
211+ searchKeywordHBox .getChildren ().add (tagBarWrapper );
212+
213+ tagBar .setMaxWidth (355 );
214+ tagBarWrapper .vvalueProperty ().bind (tagBar .heightProperty ());
156215
157216 // Set view visible
158217 mainNodataAP .setVisible (true );
@@ -219,7 +278,9 @@ public void monitoringAlertLog(ActionEvent e) throws Exception {
219278 }
220279 ServerMonitoringUsecase usecase = new ServerMonitoringUsecaseImpl (repo , ReportFileRepo .getInstance ());
221280
222- AlertLog result = usecase .getAlertLogDuringPeriod (connInfo .getAlc (), alertLogStartDay , alertLogEndDay );
281+ String [] searchKeywords = tagBar .getTags ().toArray (new String [0 ]);
282+ AlertLog result = usecase .getAlertLogDuringPeriod (connInfo .getAlc (), alertLogStartDay , alertLogEndDay ,
283+ searchKeywords );
223284 alertLogMonitoringResultMap .put (selectedServer , result );
224285
225286 changeAlertLogListViewData (alertLogServerComboBox .getSelectionModel ().getSelectedItem ());
@@ -230,4 +291,100 @@ public void monitoringAlertLog(ActionEvent e) throws Exception {
230291 summaryNodataAP .setVisible (false );
231292 summaryNodataAP .toBack ();
232293 }
294+
295+ public void prevAlertLog (ActionEvent e ) {
296+ String input = navigatorTF .getText ();
297+ if (!validateAlertLogNavigatorInput (input )) {
298+ return ;
299+ }
300+
301+ int toIndex = Integer .parseInt (input ) - 1 ;
302+ if (toIndex == 0 ) {
303+ updateStatusMessage ("첫번째 Log입니다." );
304+ return ;
305+ }
306+
307+ navigatorTF .setText (String .valueOf (toIndex ));
308+ focusAlertLog (e );
309+ }
310+
311+ public void nextAlertLog (ActionEvent e ) {
312+ String input = navigatorTF .getText ();
313+ if (!validateAlertLogNavigatorInput (input )) {
314+ return ;
315+ }
316+
317+ int toIndex = Integer .parseInt (input ) + 1 ;
318+ if (toIndex > alertLogLV .getItems ().size ()) {
319+ updateStatusMessage ("마지막 Log입니다." );
320+ return ;
321+ }
322+
323+ navigatorTF .setText (String .valueOf (toIndex ));
324+ focusAlertLog (e );
325+ }
326+
327+ public void focusAlertLog (Event e ) {
328+ String input = navigatorTF .getText ();
329+ if (!validateAlertLogNavigatorInput (input )) {
330+ return ;
331+ }
332+
333+ int toIndex = Integer .parseInt (input );
334+ alertLogLV .scrollTo (toIndex - 1 );
335+ alertLogLV .getSelectionModel ().select (toIndex - 1 );
336+ updateStatusMessage (String .format ("[%d]번째 Log로 이동합니다." , toIndex ));
337+ }
338+
339+ private boolean validateAlertLogNavigatorInput (String input ) {
340+ if (StringUtils .isEmpty (input )) {
341+ updateStatusMessage ("조회를 원하는 Log index를 입력해주세요." );
342+ return false ;
343+ }
344+
345+ int toIndex = 0 ;
346+ try {
347+ toIndex = Integer .parseInt (input );
348+ } catch (NumberFormatException ex ) {
349+ updateStatusMessage ("숫자만 입력하실 수 있습니다." );
350+ return false ;
351+ }
352+
353+ int alertLogSize = alertLogLV .getItems ().size ();
354+ if (alertLogSize == 0 ) {
355+ updateStatusMessage ("Alert Log 조회 후 이용해주세요." );
356+ return false ;
357+ }
358+
359+ if (toIndex <= 0 || toIndex > alertLogSize ) {
360+ updateStatusMessage (String .format ("Log index를 올바르게 입력해주세요. (가능한 입력값 범위: 1 ~ %d)" , alertLogSize ));
361+ return false ;
362+ }
363+
364+ return true ;
365+ }
366+
367+ /**
368+ * Update message at bottom status TextField region
369+ *
370+ * @param message
371+ */
372+ private void updateStatusMessage (String message ) {
373+ Thread statusTextUpdateThread = new Thread (() -> {
374+ Platform .runLater (() -> {
375+ statusTF .setText (message );
376+ });
377+
378+ try {
379+ Thread .sleep (1000 );
380+ } catch (InterruptedException e ) {
381+ log .error (e .getMessage ());
382+ }
383+ Platform .runLater (() -> {
384+ statusTF .setText ("" );
385+ });
386+ });
387+ statusTextUpdateThread .setDaemon (true );
388+ statusTextUpdateThread .start ();
389+ }
233390}
0 commit comments