Skip to content

Commit

Permalink
feat: show time summary for today, yesterday, this week and this month
Browse files Browse the repository at this point in the history
  • Loading branch information
falkoschumann committed Nov 17, 2022
1 parent 46760a7 commit 5932519
Show file tree
Hide file tree
Showing 21 changed files with 425 additions and 108 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ and this project adheres to

## [Unreleased]

## [1.1.0] - 2022-11-17

### Added

- Show time summary for today, yesterday, this week and this month.

## [1.0.0] - 2022-11-16

### Added
Expand All @@ -18,5 +24,6 @@ and this project adheres to
- Ask at a fixed intervall like 15, 20 30 or 60 minutes.
- Notify when interval expired.

[Unreleased]: https://github.com/falkoschumann/activity-sampling-java/compare/v1.0.0...HEAD
[Unreleased]: https://github.com/falkoschumann/activity-sampling-java/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/falkoschumann/activity-sampling-java/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/falkoschumann/activity-sampling-java/releases/tag/v1.0.0
2 changes: 1 addition & 1 deletion activitysampling-application/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ if (Os.isFamily(Os.FAMILY_WINDOWS)) {
jlink {
jpackage {
imageName = 'Activity Sampling'
installerName = 'activity-sampling'
installerName = 'Activity Sampling'
installerOptions += [
'--win-upgrade-uuid', '755510a8-d4c0-4517-94a9-6c6a1d95bfd6'
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ public class ActivitySamplingView {
@FXML private Label countdownLabel;
@FXML private ProgressBar countdown;
@FXML private ListView<ActivityItem> recentActivities;
@FXML private Label hoursTodayLabel;
@FXML private Label hoursYesterdayLabel;
@FXML private Label hoursThisWeekLabel;
@FXML private Label hoursThisMonthLabel;

private final ActivitySamplingViewModel viewModel = new ActivitySamplingViewModel();

Expand Down Expand Up @@ -47,6 +51,10 @@ private void initialize() {
countdown.progressProperty().bind(viewModel.countdownProgressProperty());
recentActivities.setCellFactory(view -> new ActivityListCell(viewModel::setActivity));
recentActivities.setItems(viewModel.getRecentActivities());
hoursTodayLabel.textProperty().bind(viewModel.hoursTodayLabelTextProperty());
hoursYesterdayLabel.textProperty().bind(viewModel.hoursYesterdayLabelTextProperty());
hoursThisWeekLabel.textProperty().bind(viewModel.hoursThisWeekLabelTextProperty());
hoursThisMonthLabel.textProperty().bind(viewModel.hoursThisMonthLabelTextProperty());
}

public void run() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ class ActivitySamplingViewModel {
private final ReadOnlyStringWrapper countdownLabelText = new ReadOnlyStringWrapper("00:00:00");
private final ReadOnlyDoubleWrapper countdownProgress = new ReadOnlyDoubleWrapper(0.0);
private final ObservableList<ActivityItem> recentActivities = FXCollections.observableArrayList();
private final ReadOnlyStringWrapper hoursTodayLabelText = new ReadOnlyStringWrapper("00:00");
private final ReadOnlyStringWrapper hoursYesterdayLabelText = new ReadOnlyStringWrapper("00:00");
private final ReadOnlyStringWrapper hoursThisWeekLabelText = new ReadOnlyStringWrapper("00:00");
private final ReadOnlyStringWrapper hoursThisMonthLabelText = new ReadOnlyStringWrapper("00:00");

private final ActivitiesService activitiesService;

Expand Down Expand Up @@ -71,15 +75,33 @@ ObservableList<ActivityItem> getRecentActivities() {
return recentActivities;
}

ReadOnlyStringProperty hoursTodayLabelTextProperty() {
return hoursTodayLabelText.getReadOnlyProperty();
}

ReadOnlyStringProperty hoursYesterdayLabelTextProperty() {
return hoursYesterdayLabelText.getReadOnlyProperty();
}

ReadOnlyStringProperty hoursThisWeekLabelTextProperty() {
return hoursThisWeekLabelText.getReadOnlyProperty();
}

ReadOnlyStringProperty hoursThisMonthLabelTextProperty() {
return hoursThisMonthLabelText.getReadOnlyProperty();
}

void run() {
load();
}

void load() {
var recentActivities = activitiesService.selectRecentActivities();

var items = new ArrayList<ActivityItem>();
var dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
var timeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
for (var day : activitiesService.selectRecentActivities().workingDays()) {
for (var day : recentActivities.workingDays()) {
items.add(new ActivityItem(day.date().format(dateFormatter)));
for (var activity : day.activities()) {
items.add(
Expand All @@ -88,7 +110,23 @@ void load() {
activity));
}
}
recentActivities.setAll(items);

var timeFormat = "%1$02d:%2$02d";
var timeSummary = recentActivities.timeSummary();
hoursTodayLabelText.set(
timeFormat.formatted(
timeSummary.hoursToday().toHours(), timeSummary.hoursToday().toMinutesPart()));
hoursYesterdayLabelText.set(
timeFormat.formatted(
timeSummary.hoursYesterday().toHours(), timeSummary.hoursYesterday().toMinutesPart()));
hoursThisWeekLabelText.set(
timeFormat.formatted(
timeSummary.hoursThisWeek().toHours(), timeSummary.hoursThisWeek().toMinutesPart()));
hoursThisMonthLabelText.set(
timeFormat.formatted(
timeSummary.hoursThisMonth().toHours(), timeSummary.hoursThisMonth().toMinutesPart()));

this.recentActivities.setAll(items);
}

void logActivity() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<?import javafx.scene.control.ProgressBar?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.stage.Stage?>

Expand Down Expand Up @@ -71,6 +72,39 @@
<padding>
<Insets bottom="8.0" left="8.0" right="8.0" top="8.0" />
</padding>
<bottom>
<FlowPane alignment="CENTER" columnHalignment="CENTER" hgap="4.0" prefWrapLength="240.0" vgap="4.0">
<children>
<VBox alignment="CENTER" prefWidth="120.0">
<children>
<Label style="-fx-font-size: 0.8em;" text="Hours Today" />
<Label fx:id="hoursTodayLabel" text="00:00" />
</children>
</VBox>
<VBox alignment="CENTER" layoutX="10.0" layoutY="10.0" prefWidth="120.0">
<children>
<Label style="-fx-font-size: 0.8em;" text="Hours Yesterday" />
<Label fx:id="hoursYesterdayLabel" text="00:00" />
</children>
</VBox>
<VBox alignment="CENTER" layoutX="92.0" layoutY="10.0" prefWidth="120.0">
<children>
<Label style="-fx-font-size: 0.8em;" text="Hours this Week" />
<Label fx:id="hoursThisWeekLabel" text="00:00" />
</children>
</VBox>
<VBox alignment="CENTER" layoutX="174.0" layoutY="10.0" prefWidth="120.0">
<children>
<Label style="-fx-font-size: 0.8em;" text="Hours this Month" />
<Label fx:id="hoursThisMonthLabel" text="00:00" />
</children>
</VBox>
</children>
<BorderPane.margin>
<Insets top="8.0" />
</BorderPane.margin>
</FlowPane>
</bottom>
</BorderPane>
</children>
</VBox>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,27 @@ void mainScenario() {
sut.activityTextProperty().set("Lorem ipsum");
sut.logActivity();

assertEquals(
List.of(
new ActivityItem("Mittwoch, 16. November 2022"),
new ActivityItem(
"18:05 - Lorem ipsum",
new Activity(LocalDateTime.of(2022, 11, 16, 18, 5), "Lorem ipsum"))),
sut.getRecentActivities(),
"Step 1 - Recent activities");
assertAll(
() ->
assertEquals(
List.of(
new ActivityItem("Mittwoch, 16. November 2022"),
new ActivityItem(
"18:05 - Lorem ipsum",
new Activity(LocalDateTime.of(2022, 11, 16, 18, 5), "Lorem ipsum"))),
sut.getRecentActivities(),
"Step 1 - Recent activities"),
() ->
assertEquals("00:20", sut.hoursTodayLabelTextProperty().get(), "Step 1 - Hours today"),
() ->
assertEquals(
"00:00", sut.hoursYesterdayLabelTextProperty().get(), "Step 1 - Hours yesterday"),
() ->
assertEquals(
"00:20", sut.hoursThisWeekLabelTextProperty().get(), "Step 1 - Hours this week"),
() ->
assertEquals(
"00:20", sut.hoursThisMonthLabelTextProperty().get(), "Step 1 - Hours this month"));

//
// Step 2 - Log second activity
Expand All @@ -50,16 +63,30 @@ void mainScenario() {
sut.activityTextProperty().set("Foobar");
sut.logActivity();

assertEquals(
List.of(
new ActivityItem("Mittwoch, 16. November 2022"),
new ActivityItem(
"18:25 - Foobar", new Activity(LocalDateTime.of(2022, 11, 16, 18, 25), "Foobar")),
new ActivityItem(
"18:05 - Lorem ipsum",
new Activity(LocalDateTime.of(2022, 11, 16, 18, 5), "Lorem ipsum"))),
sut.getRecentActivities(),
"Step 2 - Recent activities");
assertAll(
() ->
assertEquals(
List.of(
new ActivityItem("Mittwoch, 16. November 2022"),
new ActivityItem(
"18:25 - Foobar",
new Activity(LocalDateTime.of(2022, 11, 16, 18, 25), "Foobar")),
new ActivityItem(
"18:05 - Lorem ipsum",
new Activity(LocalDateTime.of(2022, 11, 16, 18, 5), "Lorem ipsum"))),
sut.getRecentActivities(),
"Step 2 - Recent activities"),
() ->
assertEquals("00:40", sut.hoursTodayLabelTextProperty().get(), "Step 2 - Hours today"),
() ->
assertEquals(
"00:00", sut.hoursYesterdayLabelTextProperty().get(), "Step 2 - Hours yesterday"),
() ->
assertEquals(
"00:40", sut.hoursThisWeekLabelTextProperty().get(), "Step 2 - Hours this week"),
() ->
assertEquals(
"00:40", sut.hoursThisMonthLabelTextProperty().get(), "Step 2 - Hours this month"));

//
// Step 2 - Select first activity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ void init() {
new WorkingDay(
LocalDate.of(2022, 11, 16),
List.of(
new Activity(
LocalDateTime.of(2022, 11, 16, 16, 16), "Lorem ipsum"))))));
new Activity(LocalDateTime.of(2022, 11, 16, 16, 16), "Lorem ipsum")))),
new TimeSummary(
Duration.ofMinutes(5),
Duration.ofMinutes(10),
Duration.ofMinutes(15),
Duration.ofMinutes(20))));

sut = new ActivitySamplingViewModel(activitiesService);
sut.onCountdownElapsed = mock(Runnable.class);
Expand All @@ -43,7 +47,11 @@ void run_ViewIsInitialized() {
"16:16 - Lorem ipsum",
new Activity(LocalDateTime.of(2022, 11, 16, 16, 16), "Lorem ipsum"))),
sut.getRecentActivities(),
"Recent activities"));
"Recent activities"),
() -> assertEquals("00:05", sut.hoursTodayLabelTextProperty().get()),
() -> assertEquals("00:10", sut.hoursYesterdayLabelTextProperty().get()),
() -> assertEquals("00:15", sut.hoursThisWeekLabelTextProperty().get()),
() -> assertEquals("00:20", sut.hoursThisMonthLabelTextProperty().get()));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ class TickingClock extends Clock {
private Instant instant;
private final ZoneId zone;

public TickingClock(Instant start) {
TickingClock(Instant start) {
this(start, ZoneId.systemDefault());
}

public TickingClock(Instant start, ZoneId zone) {
TickingClock(Instant start, ZoneId zone) {
this.instant = start;
this.zone = zone;
}

public void tick(Duration interval) {
void tick(Duration interval) {
instant = instant.plus(interval);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package de.muspellheim.activitysampling.domain;

import java.time.*;
import java.time.temporal.*;
import java.util.*;
import java.util.stream.*;

public class ActivitiesServiceImpl implements ActivitiesService {
private final EventStore eventStore;
Expand All @@ -20,38 +17,22 @@ public ActivitiesServiceImpl(EventStore eventStore, Clock clock) {

@Override
public void logActivity(String description) {
eventStore.record(new ActivityLoggedEvent(clock.instant(), description));
eventStore.record(
new ActivityLoggedEvent(clock.instant(), Duration.ofMinutes(20), description));
}

@Override
public RecentActivities selectRecentActivities() {
var startDate = LocalDateTime.ofInstant(clock.instant(), ZoneId.systemDefault());
startDate = startDate.minusDays(30).truncatedTo(ChronoUnit.DAYS);
var startTimestamp = startDate.toInstant(ZoneOffset.UTC);
var workingDays =
eventStore
.replay()
.filter(e -> e.timestamp().isAfter(startTimestamp))
.filter(e -> e instanceof ActivityLoggedEvent)
.map(e -> (ActivityLoggedEvent) e)
.map(
e ->
new Activity(
LocalDateTime.ofInstant(e.timestamp(), ZoneId.systemDefault()),
e.description()))
.collect(Collectors.groupingBy(e -> e.timestamp().toLocalDate()))
.entrySet()
.stream()
.map(
e ->
new WorkingDay(
e.getKey(),
List.copyOf(
e.getValue().stream()
.sorted((a1, a2) -> a2.timestamp().compareTo(a1.timestamp()))
.toList())))
.sorted((w1, w2) -> w2.date().compareTo(w1.date()))
.toList();
return new RecentActivities(List.copyOf(workingDays));
var today = LocalDate.ofInstant(clock.instant(), ZoneId.systemDefault());
var workingDaysProjection = new WorkingDaysProjection(today);
var timeSummaryProjection = new TimeSummaryProjection(today);
eventStore
.replay()
.forEach(
e -> {
workingDaysProjection.apply(e);
timeSummaryProjection.apply(e);
});
return new RecentActivities(workingDaysProjection.get(), timeSummaryProjection.get());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import java.time.*;
import java.util.*;

public record ActivityLoggedEvent(Instant timestamp, String description)
implements EventStore.Event {
public record ActivityLoggedEvent(Instant timestamp, Duration duration, String description)
implements Event {
public ActivityLoggedEvent {
Objects.requireNonNull(timestamp, "timestamp");
Objects.requireNonNull(duration, "duration");
Objects.requireNonNull(description, "description");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package de.muspellheim.activitysampling.domain;

import java.time.*;

public interface Event {
Instant timestamp();
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package de.muspellheim.activitysampling.domain;

import java.time.*;
import java.util.*;
import java.util.stream.*;

Expand All @@ -12,8 +11,4 @@ default void record(Event event) {
void record(Iterable<Event> events);

Stream<Event> replay();

interface Event {
Instant timestamp();
}
}
Loading

0 comments on commit 5932519

Please sign in to comment.