Skip to content

Commit

Permalink
Improve monthly report (#273)
Browse files Browse the repository at this point in the history
* Add prev/next buttons to monthly report

---------

Co-authored-by: kaklakariada <[email protected]>
  • Loading branch information
kaklakariada and kaklakariada authored Apr 14, 2024
1 parent b2e2081 commit 20fb4d7
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 67 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ jobs:
./gradlew -status
./gradlew -stop
- name: Archive test reports for ${{ runner.os }}
uses: actions/upload-artifact@v4
if: ${{ always() }}
with:
name: test-reports-${{ runner.os }}
path: "**/build/reports/tests/*/**"

- name: Archive native package for ${{ runner.os }}
uses: actions/upload-artifact@v4
if: ${{ env.DEFAULT_JAVA == matrix.java }}
Expand Down
16 changes: 14 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,24 @@
"source.fixAll": "explicit"
},
"java.codeGeneration.useBlocks": true,
"java.compile.nullAnalysis.mode": "disabled",
"java.configuration.updateBuildConfiguration": "automatic",
"java.test.config": {
"vmArgs": [
"-Djava.awt.headless=true",
"-Dtestfx.headless=true",
"-Dtestfx.robot=glass",
"-Dglass.platform=Monocle",
"-Dmonocle.platform=Headless"
]
},
"[java]": {
"editor.indentSize": 4
},
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"sonarlint.connectedMode.project": {
"connectionId": "itsallcode",
"projectKey": "white-rabbit"
},
"java.compile.nullAnalysis.mode": "automatic",
"java.configuration.updateBuildConfiguration": "automatic"
}
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ This release requires Java 21.
* [#245](https://github.com/itsallcode/white-rabbit/pull/245): Removed webstart deployment.
* [#265](https://github.com/itsallcode/white-rabbit/pull/265): Upgraded dependencies, require Java 21.

### Changes / Bugfixes
### New Features

* [#273](https://github.com/itsallcode/white-rabbit/pull/273): Added buttons to monthly report for jumping to the previous/next month

### Bugfixes

* [#241](https://github.com/itsallcode/white-rabbit/pull/241): Fix automatic interruption dialog popup after resume.
* [#233](https://github.com/itsallcode/white-rabbit/pull/233): Upgrade dependencies, use [Gradle versions catalog](https://docs.gradle.org/current/userguide/platforms.html).
Expand Down
2 changes: 1 addition & 1 deletion jfxui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ task uiTest(type: Test, group: 'verification') {
}

forkEvery 5
jvmArgs '-XX:+HeapDumpOnOutOfMemoryError'
jvmArgs '-XX:+HeapDumpOnOutOfMemoryError', '-XX:+EnableDynamicAgentLoading'

if(!project.hasProperty("uiTestsHeadless") || project.property("uiTestsHeadless") != "false") {
systemProperty 'java.awt.headless', 'true'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.itsallcode.whiterabbit.api.model.ProjectReport;
import org.itsallcode.whiterabbit.jfxui.service.DesktopService;
import org.itsallcode.whiterabbit.jfxui.ui.*;
import org.itsallcode.whiterabbit.jfxui.ui.DailyProjectReportViewer;
import org.itsallcode.whiterabbit.jfxui.ui.MonthlyProjectReportViewer;
import org.itsallcode.whiterabbit.jfxui.ui.PluginManagerViewer;
import org.itsallcode.whiterabbit.jfxui.ui.VacationReportViewer;
import org.itsallcode.whiterabbit.logic.Config;
import org.itsallcode.whiterabbit.logic.model.MonthIndex;
import org.itsallcode.whiterabbit.logic.report.vacation.VacationReport;
Expand Down Expand Up @@ -133,8 +138,7 @@ public void showMonthlyProjectReport()
LOG.warn("No month selected, can't generate project report");
return;
}
final ProjectReport report = appService.generateProjectReport(monthIndex.getYearMonth());
new MonthlyProjectReportViewer(getPrimaryStage(), state.uiState, appService, report).show();
new MonthlyProjectReportViewer(getPrimaryStage(), state.uiState, appService, monthIndex.getYearMonth()).show();
}

public void showPluginManager()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jdt.annotation.NonNull;
import org.itsallcode.whiterabbit.jfxui.table.EditListener;
import org.itsallcode.whiterabbit.jfxui.table.RecordPropertyAdapter;
import org.itsallcode.whiterabbit.logic.model.Activity;
Expand All @@ -25,7 +24,7 @@ public final class ActivityPropertyAdapter extends RecordPropertyAdapter<Activit
final ObjectProperty<Boolean> remainder;
final ObjectProperty<String> comment;

private ActivityPropertyAdapter(EditListener<DayRecord> editListener, Activity act)
private ActivityPropertyAdapter(final EditListener<DayRecord> editListener, final Activity act)
{
super(dayRecord -> editListener.recordUpdated(dayRecord.getDay()));
setRecord(act);
Expand All @@ -36,7 +35,7 @@ private ActivityPropertyAdapter(EditListener<DayRecord> editListener, Activity a
update();
}

public void setActivity(Activity activity)
public void setActivity(final Activity activity)
{
super.setRecord(activity);
update();
Expand All @@ -50,12 +49,13 @@ public void update()
});
}

public static ActivityPropertyAdapter wrap(EditListener<DayRecord> editListener, Activity activity)
public static ActivityPropertyAdapter wrap(final EditListener<DayRecord> editListener, final Activity activity)
{
return new ActivityPropertyAdapter(editListener, activity);
}

static List<@NonNull ActivityPropertyAdapter> wrap(EditListener<DayRecord> editListener, List<Activity> activities)
static List<ActivityPropertyAdapter> wrap(final EditListener<DayRecord> editListener,
final List<Activity> activities)
{
return activities.stream()
.map(a -> wrap(editListener, a))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.jdt.annotation.NonNull;

class AwtTrayIcon implements Tray
{
Expand All @@ -27,13 +26,13 @@ class AwtTrayIcon implements Tray
private final SystemTray tray;
private final TrayIcon trayIcon;

private AwtTrayIcon(SystemTray tray, TrayIcon trayIcon)
private AwtTrayIcon(final SystemTray tray, final TrayIcon trayIcon)
{
this.tray = tray;
this.trayIcon = trayIcon;
}

static @NonNull Tray createAwtTray(TrayCallback callback)
static Tray createAwtTray(final TrayCallback callback)
{
try
{
Expand All @@ -52,7 +51,7 @@ private AwtTrayIcon(SystemTray tray, TrayIcon trayIcon)
}
}

private static Image loadImage(final String resourceName, Dimension size)
private static Image loadImage(final String resourceName, final Dimension size)
{
final URL imageUrl = AwtTrayIcon.class.getResource(resourceName);
try
Expand All @@ -67,7 +66,7 @@ private static Image loadImage(final String resourceName, Dimension size)
}
}

private static PopupMenu createPopupMenu(TrayCallback callback)
private static PopupMenu createPopupMenu(final TrayCallback callback)
{
final PopupMenu popupMenu = new PopupMenu("White Rabbit Time Recording");
popupMenu.add(menuItem("Show", KeyEvent.VK_S, callback::showMainWindow));
Expand All @@ -77,21 +76,21 @@ private static PopupMenu createPopupMenu(TrayCallback callback)
return popupMenu;
}

private static MenuItem menuItem(String label, int shortcutKey, Runnable action)
private static MenuItem menuItem(final String label, final int shortcutKey, final Runnable action)
{
final MenuItem menuItem = new MenuItem(label, new MenuShortcut(shortcutKey));
menuItem.addActionListener(event -> action.run());
return menuItem;
}

@Override
public void setTooltip(String tooltip)
public void setTooltip(final String tooltip)
{
trayIcon.setToolTip(tooltip);
}

@Override
public void displayMessage(String caption, String text, MessageType messageType)
public void displayMessage(final String caption, final String text, final MessageType messageType)
{
SwingUtilities.invokeLater(() -> trayIcon.displayMessage(caption, text, messageType));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package org.itsallcode.whiterabbit.jfxui.ui;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

import java.time.Duration;
import java.time.YearMonth;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.itsallcode.whiterabbit.api.model.ProjectReport;
import org.itsallcode.whiterabbit.api.model.ProjectReportActivity;
import org.itsallcode.whiterabbit.jfxui.table.converter.DurationStringConverter;
Expand All @@ -19,39 +20,62 @@

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.control.TableView;
import javafx.stage.Stage;
import javafx.util.converter.DefaultStringConverter;

public class MonthlyProjectReportViewer
{
private final ProjectReport report;
private static final Logger LOG = LogManager.getLogger(MonthlyProjectReportViewer.class);

private final ReportWindow reportWindow;
private final UiStateService uiState;
private final AppService appService;
private YearMonth yearMonth;

public MonthlyProjectReportViewer(Stage primaryStage, UiStateService uiState, AppService appService,
ProjectReport report)
public MonthlyProjectReportViewer(final Stage primaryStage, final UiStateService uiState,
final AppService appService, final YearMonth yearMonth)
{
this.uiState = uiState;
this.appService = appService;
this.reportWindow = new ReportWindow(primaryStage, uiState, "monthly-project-report", "Monthly Project Report");
this.report = report;
this.yearMonth = yearMonth;
this.reportWindow = new ReportWindow(primaryStage, uiState, "monthly-project-report", getWindowTitle());
}

public void show()
{
final TableView<ReportRow> treeTable = createTreeTable();
reportWindow.show(treeTable);
updateTable(treeTable);
final Node previousMonthButton = UiWidget.button("prev-month-button", "< Previous Month",
e -> gotoMonth(treeTable, -1));
final Node nextMonthButton = UiWidget.button("next-month-button", "Next Month >",
e -> gotoMonth(treeTable, +1));
reportWindow.show(treeTable, previousMonthButton, nextMonthButton);
uiState.register(treeTable);
}

private void gotoMonth(final TableView<ReportRow> treeTable, final int count)
{
yearMonth = yearMonth.plusMonths(count);
LOG.debug("Go {} months to {}", count, yearMonth);
updateTable(treeTable);
reportWindow.updateTitle(getWindowTitle());
}

private void updateTable(final TableView<ReportRow> treeTable)
{
treeTable.setItems(createRows());
}

private String getWindowTitle()
{
return "Monthly Project Report " + yearMonth;
}

private TableView<ReportRow> createTreeTable()
{
final ObservableList<ReportRow> rows = FXCollections.observableList(
report.getProjects().stream()
.map(project -> createRow(report.getMonth(), project)).collect(toList()));
final TableView<ReportRow> treeTable = new TableView<>(rows);
final TableView<ReportRow> treeTable = new TableView<>();
treeTable.getColumns().addAll(List.of(
UiWidget.readOnlyColumn("yearMonth", "Month",
new YearMonthStringConverter(), ReportRow::getMonth),
Expand All @@ -67,7 +91,14 @@ private TableView<ReportRow> createTreeTable()
return treeTable;
}

private ReportRow createRow(YearMonth month, ProjectReportActivity project)
private final ObservableList<ReportRow> createRows()
{
final ProjectReport report = appService.generateProjectReport(yearMonth);
return FXCollections.observableList(
report.getProjects().stream().map(project -> createRow(report.getMonth(), project)).toList());
}

private ReportRow createRow(final YearMonth month, final ProjectReportActivity project)
{
return new ReportRow(month, project);
}
Expand All @@ -77,7 +108,7 @@ public static class ReportRow
private final YearMonth month;
private final ProjectReportActivity project;

private ReportRow(YearMonth month, ProjectReportActivity project)
private ReportRow(final YearMonth month, final ProjectReportActivity project)
{
this.month = month;
this.project = project;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.util.ArrayList;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.itsallcode.whiterabbit.jfxui.ui.UiResources;
import org.itsallcode.whiterabbit.jfxui.ui.UiWidget;
import org.itsallcode.whiterabbit.jfxui.uistate.UiStateService;
Expand All @@ -20,27 +22,30 @@

public class ReportWindow
{
private static final Logger LOG = LogManager.getLogger(ReportWindow.class);
private final Stage primaryStage;
private final String windowTitle;
private final UiStateService uiState;
private final String id;
private Stage stage;

public ReportWindow(Stage primaryStage, UiStateService uiState, String id, String windowTitle)
public ReportWindow(final Stage primaryStage, final UiStateService uiState, final String id,
final String windowTitle)
{
this.primaryStage = primaryStage;
this.uiState = uiState;
this.id = id;
this.windowTitle = windowTitle;
}

public void show(Node reportView, Node... toolBarItems)
public void show(final Node reportView, final Node... toolBarItems)
{
stage = createStage(reportView, toolBarItems);
LOG.debug("Show report window");
stage.show();
}

private Stage createStage(Node reportView, Node... toolBarItems)
private Stage createStage(final Node reportView, final Node... toolBarItems)
{
final BorderPane pane = new BorderPane();
pane.setTop(createToolBar(toolBarItems));
Expand All @@ -49,7 +54,7 @@ private Stage createStage(Node reportView, Node... toolBarItems)
return createStage(pane);
}

private ToolBar createToolBar(Node... items)
private ToolBar createToolBar(final Node... items)
{
final Node closeButton = UiWidget.button("close-button", "Close Report", e -> closeReportWindow());
final List<Node> allItems = new ArrayList<>();
Expand Down Expand Up @@ -77,8 +82,15 @@ private Stage createStage(final Parent root)
return newStage;
}

public void updateTitle(final String title)
{
LOG.debug("Update window title to '{}'", title);
stage.setTitle(title);
}

private void closeReportWindow()
{
LOG.debug("Closing window '{}'", stage.getTitle());
this.stage.close();
}
}
Loading

0 comments on commit 20fb4d7

Please sign in to comment.