diff --git a/README.md b/README.md index 1e4a9df8..9b2483a1 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Application to track your time spent on different projects each day. Aim was to Create projects and choose if they are counted as 'work time'. Select the project you work on. Before you switch the project, write a comment on what u did. Change the project. Repeat. +KeepTime can connect to [Heimat](https://heimat-software.com/) so you can import Heimat projects and sync your tracked time back to Heimat. Details: [heimat.md](readme/heimat.md). + ## Usage ### Main view: @@ -29,9 +31,25 @@ Create projects and choose if they are counted as 'work time'. Select the projec + Export: export database for backup and later import (import currently not yet implemented) ### Reports: -![Report Screen](readme/images/reportDescription.png?raw=true "Report") -+ the report screen gives you a summary for every day +KeepTime’s reporting workflow works by tracking daily work and synchronizing project activities with external task management. Here’s how you use it: + +1. **Track Your Work** + Throughout your workday, log activities and assign them to projects. Each entry includes a timeslot, duration, and optional notes. + +2. **Review Your Daily Report** + At any time, open the report view to see an overview of your day, including all logged activities, their durations, and project associations. + +3. **Edit and Manage Entries** + Use the controls in the report to copy, edit, or delete individual work entries as needed. You can also copy notes or summaries for external use. + +4. **Select the Day to View** + Use the calendar widget to select which day’s report you want to review. Only days with recorded work are available. + +5. **Synchronize Projects with Heimat** + If you want you can syncronize the current date with Heimat. See [heimat.md](readme/heimat.md) + +![Report Dialog](readme/images/reportDescription.png) ## Install diff --git a/readme/heimat.md b/readme/heimat.md new file mode 100644 index 00000000..6639205c --- /dev/null +++ b/readme/heimat.md @@ -0,0 +1,53 @@ +# Heimat integration + +[Heimat](https://heimat-software.com/) is external project and time-tracking software. KeepTime can connect to it so you can: + +- **Import** projects from Heimat into KeepTime, or **link** Heimat projects to projects you already have in KeepTime. +- **Push** the time you logged in KeepTime for a given day into Heimat when you choose to sync. + +**Important:** KeepTime never writes to Heimat on its own. Data is sent to Heimat only when you run the sync from the report view. + +--- + +## 1. Connect KeepTime to Heimat + +1. Open **Settings** and go to the **HEIMAT** section. + + ![Settings Heimat](images/settingsHeimat.png "Settings Heimat") + +2. Fill in: + + | Field | What to enter | + | ---------------- | -------------------------------------------------------------------------------------------------------------------- | + | **URL** | Your Heimat instance URL (the same base URL you use in the browser), for example `https://your-company.example.com`. | + | **Access token** | Create or copy a token in Heimat (under your account or API settings) and paste it here. | + + ![Heimat Website](images/heimatWebsite.png "Heimat Website") + +3. Click **Validate connection**. If it succeeds, the integration is ready to use. + +--- + +## 2. Match Heimat projects to KeepTime + +After a successful connection, use **Map projects** (button in Heimat settings dialog) to either: + +- Map each Heimat project to an existing KeepTime project, or +- Import Heimat projects as new KeepTime projects. + +Do this once (or whenever your project lists change) so KeepTime knows where each Heimat project should go. + +--- + +## 3. Sync a day’s work to Heimat + +When you want to upload time for the **currently selected day** in the report: + +1. Open the **report** view for that day. +2. Click the **sync** button (Heimat / external sync). +3. In the dialog, choose which projects to include and add any **note** you want stored with the sync. +4. Click **Sync** to send that day’s tracked time to Heimat. + +![External Project Dialog](images/externalProjectDialog.png) + +Until you complete step 4, nothing is written to Heimat. diff --git a/readme/images/externalProjectDialog.png b/readme/images/externalProjectDialog.png new file mode 100644 index 00000000..77c28fb8 Binary files /dev/null and b/readme/images/externalProjectDialog.png differ diff --git a/readme/images/heimatWebsite.png b/readme/images/heimatWebsite.png new file mode 100644 index 00000000..45ed9a5d Binary files /dev/null and b/readme/images/heimatWebsite.png differ diff --git a/readme/images/reportDescription.png b/readme/images/reportDescription.png index bda4588a..8bb86ac3 100644 Binary files a/readme/images/reportDescription.png and b/readme/images/reportDescription.png differ diff --git a/readme/images/settingsHeimat.png b/readme/images/settingsHeimat.png new file mode 100644 index 00000000..a0bee6de Binary files /dev/null and b/readme/images/settingsHeimat.png differ diff --git a/src/main/java/de/doubleslash/keeptime/controller/HeimatController.java b/src/main/java/de/doubleslash/keeptime/controller/HeimatController.java index d6ba0af6..0e4df426 100644 --- a/src/main/java/de/doubleslash/keeptime/controller/HeimatController.java +++ b/src/main/java/de/doubleslash/keeptime/controller/HeimatController.java @@ -85,7 +85,7 @@ public void tryLogin() { try { heimatAPI.isLoginValid(); } catch (Exception e) { - throw new SecurityException("Could not connect to HEIMAT API. Maybe wrong configuration?", e); + throw new SecurityException("Could not connect to Heimat API. Maybe wrong configuration?", e); } } @@ -237,7 +237,7 @@ public List getTableRows(final LocalDate currentReportDate, final List< long heimatTimeSeconds = addHeimatTimes(times); StyledMessage syncMessage = StyledMessage.of( - new StyledMessage.TextSegment("Present in HEIMAT but not KeepTime\n\nSync to "), + new StyledMessage.TextSegment("Present in Heimat but not KeepTime\n\nSync to "), new StyledMessage.TextSegment(externalProjectMapping.getExternalTaskName(), true), new StyledMessage.TextSegment("\n(" + externalProjectMapping.getExternalProjectName() + ")")); @@ -408,7 +408,7 @@ public ExistingAndInvalidMappings getExistingProjectMappings(List ex .filter(ep -> ep.id() == mapping.get().getExternalTaskId()) .findAny(); if (any.isEmpty()) { - LOG.warn("A mapping exists but task does not exist anymore in HEIMAT! '{}'->'{}'.", + LOG.warn("A mapping exists but task does not exist anymore in Heimat! '{}'->'{}'.", mapping.get().getProject(), mapping.get().getExternalTaskId()); invalidExternalMappings.add(mapping.get()); return new ProjectMapping(p, null); diff --git a/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsMapController.java b/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsMapController.java index 53a94f64..7124493d 100644 --- a/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsMapController.java +++ b/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsMapController.java @@ -108,7 +108,7 @@ private void initialize() { externalProjects); externalProjectsObservableList.add(0, null); // option to clear selection - TableColumn externalColumn = new TableColumn<>("HEIMAT project"); + TableColumn externalColumn = new TableColumn<>("Heimat project"); externalColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue().getHeimatTask())); externalColumn.setCellFactory(col -> new TableCell<>() { // TODO search in box would be nice @@ -199,7 +199,7 @@ protected void updateItem(HeimatTask item, boolean empty) { private List showMultiSelectDialog(final List externalProjects, List unmappedHeimatTasks) { Dialog> dialog = new Dialog<>(); - dialog.setTitle("Import HEIMAT projects"); + dialog.setTitle("Import Heimat projects"); dialog.setHeaderText("You can select mutliple items"); dialog.initOwner(this.thisStage); dialog.setWidth(600); @@ -211,7 +211,7 @@ private List showMultiSelectDialog(final List externalPr dialog.getDialogPane().getButtonTypes().addAll(okButtonType, cancelButtonType); TableView tableView = new TableView<>(); - TableColumn nameColumn = new TableColumn<>("HEIMAT project"); + TableColumn nameColumn = new TableColumn<>("Heimat project"); nameColumn.setCellValueFactory(data -> new SimpleObjectProperty<>(data.getValue())); nameColumn.setCellFactory(param -> new TableCell<>() { @Override diff --git a/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsSyncController.java b/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsSyncController.java index 50c844c6..987a8f6b 100644 --- a/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsSyncController.java +++ b/src/main/java/de/doubleslash/keeptime/view/ExternalProjectsSyncController.java @@ -325,7 +325,7 @@ protected void updateItem(TableRow item, boolean empty) { } else { keeptimeLabel.setText("KeepTime: " + localTimeStringConverter.toString( LocalTime.ofSecondOfDay(item.keeptimeTimeSeconds.get()))); - heimatLabel.setText("HEIMAT: " + localTimeStringConverter.toString( + heimatLabel.setText("Heimat: " + localTimeStringConverter.toString( LocalTime.ofSecondOfDay(item.heimatTimeSeconds.get()))); timeSpinner.setDisable(!item.mapping.canBeSynced()); timeSpinner.getValueFactory().setValue(LocalTime.ofSecondOfDay(0)); @@ -384,7 +384,7 @@ protected void updateItem(TableRow item, boolean empty) { final Label keeptimeLabel = new Label("KeepTime:"); keeptimeLabel.setMinWidth(60); hbox.getChildren().addAll(copyKeepTimeNotes, keeptimeLabel, keepTimeNotesLabel); - final Label heimatLabel = new Label("HEIMAT:"); + final Label heimatLabel = new Label("Heimat:"); heimatLabel.setMinWidth(60); hbox2.getChildren().addAll(copyHeimatNotes, heimatLabel, heimatNotesLabel); container.getChildren().addAll(textArea, hbox, hbox2); diff --git a/src/main/java/de/doubleslash/keeptime/view/ReportController.java b/src/main/java/de/doubleslash/keeptime/view/ReportController.java index 8874360b..e4253986 100644 --- a/src/main/java/de/doubleslash/keeptime/view/ReportController.java +++ b/src/main/java/de/doubleslash/keeptime/view/ReportController.java @@ -144,7 +144,7 @@ private void initHeimatIntegration() { heimatSyncButton.setMinSize(25, 25); heimatSyncButton.setGraphic(svgNodeWithScale); heimatSyncButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); - heimatSyncButton.setTooltip(new Tooltip("Synchronize to HEIMAT...")); + heimatSyncButton.setTooltip(new Tooltip("Synchronize to Heimat...")); heimatSyncButton.setOnAction(ae-> { try { showSyncStage(); diff --git a/src/main/resources/layouts/externalProjectSync.fxml b/src/main/resources/layouts/externalProjectSync.fxml index b95a6f27..ce878723 100644 --- a/src/main/resources/layouts/externalProjectSync.fxml +++ b/src/main/resources/layouts/externalProjectSync.fxml @@ -9,7 +9,7 @@ - + - +