From c82e766bb29c436c49e909ef6123a64b50872407 Mon Sep 17 00:00:00 2001 From: Gabor Boros Date: Mon, 11 Oct 2021 18:37:05 +0200 Subject: [PATCH] docs: add project documentation and changelog generation --- .github/workflows/docs.yml | 20 ++++++ CHANGELOG.md | 61 +++++++++++++++++ CONTRIBUTING.md | 113 ++++++++++++++++++++++++++++++++ Makefile | 8 ++- README.md | 58 ++++++++-------- cliff.toml | 50 ++++++++++++++ docs/.gitkeep | 0 www/docs/CHANGELOG.md | 1 + www/docs/CONTRIBUTING.md | 1 + www/docs/LICENSE.md | 1 + www/docs/assets/css/minutes.css | 7 ++ www/docs/configuration.md | 105 +++++++++++++++++++++++++++++ www/docs/getting-started.md | 93 ++++++++++++++++++++++++++ www/docs/index.md | 81 +++++++++++++++++++++++ www/docs/sources/clockify.md | 22 +++++-- www/docs/sources/tempo.md | 37 +++++++++++ www/docs/targets/tempo.md | 29 ++++++++ www/mkdocs.yml | 71 ++++++++++++++++++++ www/requirements.txt | 2 + 19 files changed, 726 insertions(+), 34 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 cliff.toml delete mode 100644 docs/.gitkeep create mode 120000 www/docs/CHANGELOG.md create mode 120000 www/docs/CONTRIBUTING.md create mode 120000 www/docs/LICENSE.md create mode 100644 www/docs/assets/css/minutes.css create mode 100644 www/docs/configuration.md create mode 100644 www/docs/getting-started.md create mode 100644 www/docs/index.md create mode 100644 www/docs/sources/tempo.md create mode 100644 www/docs/targets/tempo.md create mode 100644 www/mkdocs.yml create mode 100644 www/requirements.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..2a4efed --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,20 @@ +name: Docs + +'on': + push: + branches: + - main + paths: + - www/* + pull_request: { } + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.x + - run: pip install -r www/requirements.txt + - run: cd www && mkdocs gh-deploy --force diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3fd8b1f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,61 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [unreleased] + +**Bug Fixes** + +- Solve time parsing issue when start or end date is defined (3d9c7be) + +**Documentation** + +- Add readme file (6784310) +- Add code of conduct (6b29c4f) +- Update go install instructions (a91840f) +- Add project documentation and changelog generation (48b7f98) + +**Features** + +- Initial worklog implementation (b73017b) +- Add basic client implementation (2501bcc) +- Add basic tempo client implementation (202ac41) +- Add basic clockify client implementation (cb04282) +- Add initial CLI implementation (98a6759) + +**Miscellaneous Tasks** + +- Add MIT license (3c3b64c) +- Add initial .gitignore (47e5b92) +- Add dependencies (1a24535) +- Add issue templates (99fba16) +- Add virtualenv to gitignore (466aa6d) + +**Refactor** + +- Rename worklog search and create path (b3d1ede) +- Return a list of entries instead of a pointer to a list of entries (000a6b7) +- Rename every occurance of item to entry (38f37ab) +- Update command headline (e1fa381) +- Replace table printer and refactor utils (67721bf) +- Rename tasks-as-tags to tags-as-tasks and tasks-as-tags-regex to tags-as-tasks-regex (180126b) +- Rename ci.yml to build.yml (4165ea4) +- Rename codeql-analysis.yml to codeql.yml (88edae1) + +**Testing** + +- Add benchmarks for NewWorklog (87f6767) +- Remove unused mock server opts (9fba963) +- Use UTC for time zone in tests (145031e) + +**Build** + +- Add initial Makefile (d25eab8) +- Add post build hook to call upx (6391c0f) + +**Ci** + +- Add CodeQL integration (29d4b74) +- Setup PR builds (210c58f) +- Update cron frequency (05db753) + diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0c550c5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,113 @@ +# Contributing + +Contributions are welcome, and they are greatly appreciated! Every little helps, and credit will always be given. You can contribute in many ways. + +## Types of Contributions + +### Report Bugs + +Report bugs at . + +If you are reporting a bug, please use the bug report template, and include: + +- your operating system name and version +- any details about your local setup that might be helpful in troubleshooting +- detailed steps to reproduce the bug + +### Fix Bugs + +Look through the GitHub issues for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it. + +### Implement Features + +Look through the GitHub issues for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it. In case you added a new source or target, do not forget to add them to the docs as well. + +### Write Documentation + +Minutes could always use more documentation, whether as part of the docs, in docstrings, or even on the web in blog posts, articles, and such. + +### Submit Feedback + +The best way to send feedback is to file an [issue](https://github.com/gabor-boros/minutes/issues). + +If you are proposing a feature: + +- explain in detail how it would work +- keep the scope as narrow as possible, to make it easier to implement +- remember that this is a volunteer-driven project, and that contributions are welcome :) + +## Get Started! + +Ready to contribute? Here's how to set up `minutes` for local development. + +As step 0 make sure you have Go 1.17+ and Python 3 installed. + +1. Fork the repository +2. Clone your fork locally + +```shell +$ git clone git@github.com:your_name_here/minutes.git +``` + +3. Install prerequisites + +```shell +$ cd minutes +$ make prerequisites +$ make deps +$ python -m virtualenv -p python3 virtualenv +$ pip install -r www/requirements.txt +``` + +4. Create a branch for local development + +```shell +$ git checkout -b github-username/bugfix-or-feature-name +``` + +5. When you're done making changes, check that your changes are formatted, passing linters, and tests are succeeding + +```shell +$ make format +$ make lint +$ make test +``` + +6. Update documentation and check the results by running `make docs` +7. Commit your changes and push your branch to GitHub + +We use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.2/), and we require every commit to +follow this pattern. + +```shell +$ git add . +$ git commit -m "action(scope): summary" +$ git push origin github-username/bugfix-or-feature-name +``` + +8. Submit a pull request on GitHub + +## Pull Request Guidelines + +Before you submit a pull request, check that it meets these guidelines: + +1. The pull request should include tests +2. Tests should pass for the PR +3. If the pull request adds new functionality, or changes existing one, the docs should be updated + +## Releasing + +A reminder for the maintainers on how to release. + +Before doing anything, ensure you have [git-cliff](https://github.com/orhun/git-cliff) installed, and you already +executed `make prerequisites`. + +1. Make sure every required PR is merged +2. Make sure every test is passing both on GitHub and locally +3. Make sure that formatters are not complaining (`make format` returns 0) +4. Make sure that linters are not complaining (`make lint` returns 0) +5. Take a note about the next release version, keeping semantic versioning in mind +6. Update the CHANGELOG.md using `TAG="" make changelog` +7. Compare the CHANGELOG.md changes and push to master +8. Cut a new tag for the next release version +9. Run `GITHUB_TOKEN="" make release` to package the tool and create a GitHub release diff --git a/Makefile b/Makefile index c209e7e..ded0494 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help prerequisites deps format lint test build clean +.PHONY: help prerequisites deps format lint test build release changelog docs clean .DEFAULT_GOAL := build BIN_NAME := minutes @@ -34,5 +34,11 @@ build: deps ## Build binary release: ## Release a new version on GitHub goreleaser release --rm-dist --auto-snapshot +changelog: ## Generate changelog + git-cliff --unreleased --prepend CHANGELOG.md + +docs: ## Serve the documentation site locally + @cd www && mkdocs serve + clean: ## Clean up project root rm -rf bin/ diff --git a/README.md b/README.md index d0daab7..9235bba 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@

Sync worklogs between multiple time trackers, invoicing, and bookkeeping software.
- Explore the docs + Explore the docs

Bug report @@ -21,6 +21,7 @@ + ## About The Project ```plaintext @@ -42,7 +43,7 @@ You have 5 complete and 0 incomplete items. Before proceeding, please double-che Continue? [y/n]: ``` -Minutes is a CLI tool for synchronizing work logs between multiple time trackers, invoicing, and bookkeeping software to make entrepreneurs' daily work easier. Every source and destination comes with their specific flags. Before using any flags, check the related documentation. +Minutes is a CLI tool for synchronizing work logs between multiple time trackers, invoicing, and bookkeeping software to make entrepreneurs' daily work easier. Every source and destination comes with their specific flags. Before using any flags, check the related documentation. Minutes come with absolutely **NO WARRANTY**; before and after synchronizing any logs, please ensure you got the expected result. @@ -58,7 +59,7 @@ To install `minutes`, use one of the [release artifacts](https://github.com/gabo `minutes` has numerous flags and there will be more when other sources or targets are added. Therefore, `minutes` comes with a config file, that can be placed to the user's home directory or the config directory. -_To read more about the config file, please refer to the [Documentation](https://github.com/minutes/tree/master/docs/README.md)_ +_To read more about the config file, please refer to the [Documentation](https://gabor-boros.github.io/minutes/getting-started)_ ## Usage @@ -86,8 +87,8 @@ Flags: --table-sort-by strings sort table by column [task summary project client start end billable unbillable] (default [start,project,task,summary]) -t, --target string set the target of the sync [tempo] --target-user string set the source user ID - --tasks-as-tags treat tags matching the value of tasks-as-tags-regex as tasks - --tasks-as-tags-regex string regex of the task pattern + --tags-as-tasks treat tags matching the value of tags-as-tasks-regex as tasks + --tags-as-tasks-regex string regex of the task pattern --tempo-password string set the login password --tempo-url string set the base URL --tempo-username string set the login user ID @@ -95,8 +96,6 @@ Flags: --version show command version ``` - - ### Usage examples Depending on the config file, the number of flags can change. @@ -124,7 +123,7 @@ $ minutes --date-format "2006-01-02" --start "2021-10-07" --end "2021-10-08" ```shell # Specify how a tag should look like to be considered as a task -$ minutes --tasks-as-tags --tasks-as-tags-regex '[A-Z]{2,7}-\d{1,6}' +$ minutes --tags-as-tasks --tags-as-tasks-regex '[A-Z]{2,7}-\d{1,6}' ``` #### Minute based rounding @@ -155,8 +154,8 @@ tempo-username = "" tempo-password = "" # General config -tasks-as-tags = true -tasks-as-tags-regex = '[A-Z]{2,7}-\d{1,6}' +tags-as-tasks = true +tags-as-tasks-regex = '[A-Z]{2,7}-\d{1,6}' round-to-closest-minute = true force-billed-duration = true @@ -176,26 +175,26 @@ summary = 40 project = 10 client = 10 -# Column Config +# Column Config [table-column-config.summary] -widthmax = 40 +widthmax = 40 ``` ## Supported tools -| Tool | Use as source | Use as target | -| ----------- | ----------------- | ------------- | -| Clockify | **yes** | upon request | -| Everhour | upon request | upon request | -| FreshBooks | upon request | **planned** | -| Harvest | upon request | upon request | -| QuickBooks | upon request | upon request | -| Tempo | **yes** | **yes** | -| Time Doctor | upon request | upon request | -| TimeCamp | upon request | upon request | -| Timewarrior | upon request | upon request | -| Toggl Track | **planned** | upon request | -| Zoho Books | upon request | **planned** | +| Tool | Use as source | Use as target | +| ----------- | ------------- | ------------- | +| Clockify | **yes** | upon request | +| Everhour | upon request | upon request | +| FreshBooks | upon request | **planned** | +| Harvest | upon request | upon request | +| QuickBooks | upon request | upon request | +| Tempo | **yes** | **yes** | +| Time Doctor | upon request | upon request | +| TimeCamp | upon request | upon request | +| Timewarrior | upon request | upon request | +| Toggl Track | **planned** | upon request | +| Zoho Books | upon request | **planned** | See the [open issues](https://github.com/gabor-boros/minutes/issues) for a full list of proposed features, tools and known issues. @@ -203,10 +202,10 @@ See the [open issues](https://github.com/gabor-boros/minutes/issues) for a full The following list of features are not supported at the moment: -* Cost rate sync -* Hourly rate sync -* Estimate sync -* Multiple source and target user support +- Cost rate sync +- Hourly rate sync +- Estimate sync +- Multiple source and target user support ## Contributing @@ -222,6 +221,7 @@ Don't forget to give the project a star! 5. Open a Pull Request + [contributors-shield]: https://img.shields.io/github/contributors/gabor-boros/minutes.svg?style=for-the-badge [contributors-url]: https://github.com/gabor-boros/minutes/graphs/contributors [forks-shield]: https://img.shields.io/github/forks/gabor-boros/minutes.svg?style=for-the-badge diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..cbc527f --- /dev/null +++ b/cliff.toml @@ -0,0 +1,50 @@ +# configuration file for git-cliff (0.1.0) + +[changelog] +header = """ +# Changelog + +All notable changes to this project will be documented in this file.\n +""" +# template for the changelog body +# https://tera.netlify.app/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + **{{ group | upper_first }}** + {% for commit in commits %} + - {{ commit.message | upper_first }} ({{commit.id | truncate(length=7, end="")}})\ + {% endfor %} +{% endfor %}\n +""" + +trim = true +footer = "" + +[git] +# allow only conventional commits +# https://www.conventionalcommits.org +conventional_commits = true +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "Features"}, + { message = "^fix", group = "Bug Fixes"}, + { message = "^doc", group = "Documentation"}, + { message = "^perf", group = "Performance"}, + { message = "^refactor", group = "Refactor"}, + { message = "^style", group = "Styling"}, + { message = "^test", group = "Testing"}, + { message = "^chore\\(release\\): prepare for", skip = true}, + { message = "^chore", group = "Miscellaneous Tasks"}, + { body = ".*security", group = "Security"}, +] +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "v0.1.0-beta.1" diff --git a/docs/.gitkeep b/docs/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/www/docs/CHANGELOG.md b/www/docs/CHANGELOG.md new file mode 120000 index 0000000..699cc9e --- /dev/null +++ b/www/docs/CHANGELOG.md @@ -0,0 +1 @@ +../../CHANGELOG.md \ No newline at end of file diff --git a/www/docs/CONTRIBUTING.md b/www/docs/CONTRIBUTING.md new file mode 120000 index 0000000..f939e75 --- /dev/null +++ b/www/docs/CONTRIBUTING.md @@ -0,0 +1 @@ +../../CONTRIBUTING.md \ No newline at end of file diff --git a/www/docs/LICENSE.md b/www/docs/LICENSE.md new file mode 120000 index 0000000..30cff74 --- /dev/null +++ b/www/docs/LICENSE.md @@ -0,0 +1 @@ +../../LICENSE \ No newline at end of file diff --git a/www/docs/assets/css/minutes.css b/www/docs/assets/css/minutes.css new file mode 100644 index 0000000..9b9b1d6 --- /dev/null +++ b/www/docs/assets/css/minutes.css @@ -0,0 +1,7 @@ +.md-typeset__table { + min-width: 100%; +} + +.md-typeset table:not([class]) { + display: table; +} diff --git a/www/docs/configuration.md b/www/docs/configuration.md new file mode 100644 index 0000000..a07f4bb --- /dev/null +++ b/www/docs/configuration.md @@ -0,0 +1,105 @@ +This page documents the available settings for `minutes`. Please note that not all configuration options are covered by a CLI flag. + +## Configuration file + +Minutes will look for the following places for the configuration file, based on your operating system. + +The configuration file name in **every** case is `.minutes.toml`. + +### Linux/Unix + +On Linux/Unix systems, the following locations are checked for the configuration file: + +- `$HOME/.minutes.toml` +- `$XDG_CONFIG_HOME/.minutes.toml` as specified by https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + +### Darwin + +- `$HOME/.minutes.toml` +- `$HOME/Library/Application Support/.minutes.toml` + +### Windows + +- `%USERPROFILE%/.minutes.toml` +- `%AppData%/.minutes.toml` + +### On Plan 9 + +- `$home/.minutes.toml` +- `$home/lib/.minutes.toml` + +## Common configuration + +| Config option | Kind | Description | Example | Available options | +| ----------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------------------------- | +| date-format | string | Set the date format in [Go specific](https://www.geeksforgeeks.org/time-formatting-in-golang/) date format | date-format = "2006-01-02" | | +| dry-run | bool | Fetch entries from source, print the fetched entries, but do not upload them | dry-run = true | | +| end | string | Set the end date for fetching entries (must match the `date-format`) | end = "2021-10-01" | | +| force-billed-duration | bool | Treat the total spent time as billable time | force-billed-duration = true | | +| round-to-closest-minute | bool | Round time to closest minute, even if the closest minute is 0 (zero) | round-to-closest-minute = true | | +| source | string | Set the fetch source name | source = "tempo" | `clockify`, `tempo` | +| source-user | string | Set the fetch source user ID | source-user = "gabor-boros" | | +| start | string | Set the start date for fetching entries (must match the `date-format`) | start = "2021-10-01" | | +| table-column-config | [[]table.CloumnConfig][column config documentation] | Customize columns based on the underlying column config struct[^1] | table-column-config = { summary = { widthmax = 40 } } | | +| table-hide-column | []string | Hide the specified columns of the printed overview table | table-hide-column = ["start", "end"] | `summary`, `project`, `client`, `start`, `end` | +| table-sort-by | []string | Sort the specified rows of the printed table by the given column; each sort option can have a `-` (hyphen) prefix to indicate descending sort | table-sort-by = ["start", "task"] | `task`, `summary`, `project`, `client`, `start`, `end`, `billable`, `unbillable` | +| table-truncate-column | map[string]int | Truncate text in the given column to contain no more than `x` characters, where `x` is set by `int` | table-truncate-column = { summary = 30 } | | +| target | string | Set the upload target name | target = "tempo" | `tempo` | +| target-user | string | Set the upload target user ID | target = "gabor-boros" | | +| tags-as-tasks | bool | Treat tags matching the value of `tags-as-tasks-regex` as tasks | tags-as-tasks = true | | +| tags-as-tasks-regex | string | Regex of the task pattern | tags-as-tasks-regex = '[A-Z]{2,7}-\d{1,6}' | | + +## Source and target specific configuration + +Source and target specific configuration is **not** covered by this guide. For more information, please refer to the source or target documentation. + +## Example configuration + +```toml +# Source config +source = "clockify" +source-user = "" + +clockify-url = "https://api.clockify.me" +clockify-api-key = "" +clockify-workspace = "" + +# Target config +target = "tempo" +target-user = "" + +tempo-url = "https://tasks.opencraft.com" +tempo-username = "" +tempo-password = "" + +# General config +tags-as-tasks = true +tags-as-tasks-regex = '[A-Z]{2,7}-\d{1,6}' +round-to-closest-minute = true +force-billed-duration = true + +table-sort-by = [ + "start", + "project", + "task", + "summary", +] + +table-hide-column = [ + "end" +] + +[table-column-truncates] +summary = 40 +project = 10 +client = 10 + +# Column Config +[table-column-config.summary] +widthmax = 40 +widthmin = 20 +``` + +[^1]: The column configuration cannot be mapped directly as-is. Therefore, the configuration option names are lower-cased. Also, some settings cannot be used that would require Go code, like transformers. + +[column config documentation]: https://github.com/jedib0t/go-pretty/blob/b2f15441a4e4addd806df446c65f0ce5e327003c/table/config.go#L7-L71 diff --git a/www/docs/getting-started.md b/www/docs/getting-started.md new file mode 100644 index 0000000..e3b69aa --- /dev/null +++ b/www/docs/getting-started.md @@ -0,0 +1,93 @@ +Minutes is a CLI tool, primarily made for entrepreneurs and finance people, to help their daily work by synchronizing worklogs from a `source` to a `target` software. The `source` can be your own time tracking tool you use, while the `target` is a bookkeeping software. + +This guide show you the basics `minutes`, walks through the available flags, and gives some examples for basic configuration. For the full list of available configuration options, visit the related [documentation](https://gabor-boros.github.io/minutes/configuration). + +## Installation + +To install `minutes`, use one of the [release artifacts](https://github.com/gabor-boros/minutes/releases). If you have `go` installed, you can simply run `go install github.com/gabor-boros/minutes@latest` as well. + +`minutes` has numerous flags and there will be more when other sources or targets are added. Therefore, `minutes` comes with a config file, that can be placed to the user's home directory or the config directory. + +## Usage + +```plaintext +Usage: + minutes [flags] + +Flags: + --clockify-api-key string set the API key + --clockify-url string set the base URL + --clockify-workspace string set the workspace ID + --config string config file (default is $HOME/.minutes.yaml) + --date-format string set start and end date format (in Go style) (default "2006-01-02 15:04:05") + --dry-run fetch entries, but do not sync them + --end string set the end date (defaults to now) + --force-billed-duration treat every second spent as billed + -h, --help help for minutes + --round-to-closest-minute round time to closest minute + -s, --source string set the source of the sync [clockify tempo] + --source-user string set the source user ID + --start string set the start date (defaults to 00:00:00) + --table-hide-column strings hide table column [summary project client start end] + --table-sort-by strings sort table by column [task summary project client start end billable unbillable] (default [start,project,task,summary]) + -t, --target string set the target of the sync [tempo] + --target-user string set the source user ID + --tags-as-tasks treat tags matching the value of tags-as-tasks-regex as tasks + --tags-as-tasks-regex string regex of the task pattern + --tempo-password string set the login password + --tempo-url string set the base URL + --tempo-username string set the login user ID + --verbose print verbose messages + --version show command version +``` + +## Usage examples + +Depending on the config file, the number of flags can change. + +### Simplest command + +```shell +# No arguments, no flags, just running the command +$ minutes +``` + +### Set specific date and time + +```shell +# Set the date and time to fetch entries in the given time frame +$ minutes --start "2021-10-07 00:00:00" --end "2021-10-07 23:59:59" +``` + +```shell +# Specify the start and end date format +$ minutes --date-format "2006-01-02" --start "2021-10-07" --end "2021-10-08" +``` + +### Use tags for tasks + +```shell +# Specify how a tag should look like to be considered as a task +$ minutes --tags-as-tasks --tags-as-tasks-regex '[A-Z]{2,7}-\d{1,6}' +``` + +### Minute based rounding + +```shell +# Set the billed and unbilled time separately +# to round to the closest minute (even if it is zero) +$ minutes --round-to-closest-minute +``` + +### Format the table output + +```shell +# Skip some columns and sort table by -start date +$ minutes --table-sort-by "-start" --table-hide-column "client" --table-hide-column "project" +``` + +## Config file vs flags + +Be aware that not all configuration option is covered by flags, especially not more advanced options, like table column width or truncate settings. + +When using the configuration file and flags in conjunction, please note that flags take precedence, hence it can override settings from the configuration file. diff --git a/www/docs/index.md b/www/docs/index.md new file mode 100644 index 0000000..9dba073 --- /dev/null +++ b/www/docs/index.md @@ -0,0 +1,81 @@ +

+

Minutes

+ +

+ Sync worklogs between multiple time trackers, invoicing, and bookkeeping software. +
+ Bug report + · + Feature request +

+ +

+ + + + + + + + + + + + + + + +

+
+ +--- + +Charging by the hour is one of the most common ways to invoice a client. Some companies or clients specify the time tracking tool to use, though it usually won't fit your own workflows. This even gets more complicated and cumbersome, when the invoices should contain the tasks you spent time on. + +Minutes is a CLI tool, primarily made for entrepreneurs and finance people, to help their daily work by synchronizing worklogs from a `source` to a `target` software. The `source` can be your own time tracking tool you use, let's say [Tempo](https://tempo.io/), while the `target` is a bookkeeping software, like [Zoho Books](https://books.zoho.com). + +## Key features + +_Some features may vary depending on the `source` and `target`. For more information, please refer to their documentation._ + +- Customize the date time format used for fetching entries +- Set a specific start and end date to query entries +- Force every second spent to be billable[^1] +- Treat tags attached to an entry as tasks you spent time on[^2] +- Round billable and unbillable seconds to the closest minute per entry[^3] +- Customizable table output before uploading + +[^1]: It can be useful if the `source` does not support billable time, while the `target` does. +[^2]: When you need to split time across entries or your `source` tool does not support tasks, it comes handy to tag entries. +[^3]: Rounding rules are the following: if you spent >=30 seconds on a task, it will be treated as 1 minute, otherwise 0 (zero). + +For usage examples and configuration options, please check the [Getting Started](https://gabor-boros.github.io/minutes/getting-started) and [Configuration](https://gabor-boros.github.io/minutes/configuration) documentation. + +## Supported platforms + +The following platforms and tools are supported. If you miss your favorite tool, please send a pull request with the implementation, or file a new [feature request](https://github.com/gabor-boros/minutes/issues). + +| Tool | Use as source | Use as target | +| ----------- | ------------- | ------------- | +| Clockify | **yes** | upon request | +| Everhour | upon request | upon request | +| FreshBooks | upon request | **planned** | +| Harvest | upon request | upon request | +| QuickBooks | upon request | upon request | +| Tempo | **yes** | **yes** | +| Time Doctor | upon request | upon request | +| TimeCamp | upon request | upon request | +| Timewarrior | upon request | upon request | +| Toggl Track | **planned** | upon request | +| Zoho Books | upon request | **planned** | + +## Versioning + +Minutes adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Disclaimer + +!!! warning + + Minutes comes with absolutely **no warranty**. + When money comes into the picture, everyone should be more careful what they are doing. Before and after synchronizing any logs to the `target`, **make sure the entries displayed on the screen matching the `source` entries**. diff --git a/www/docs/sources/clockify.md b/www/docs/sources/clockify.md index 0a41e6b..83650b1 100644 --- a/www/docs/sources/clockify.md +++ b/www/docs/sources/clockify.md @@ -1,7 +1,19 @@ Source documentation for [Clockify](https://clockify.me/). +## Field mappings + +The source makes the following special mappings. + +| From | To | Description | +| ----------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| Tags | Task | Turns tags into tasks and split the entry into as many pieces as the item has matching tags when `tags-as-tasks` is enabled | +| Task | Summary or Description | Tasks will be used for defining the summary of an entry; in case the `tags-as-tasks` is enabled, Summary will be set to the Description of the item | +| Description | Notes | | + ## CLI flags +The source provides to following extra CLI flags. + ```plaintext Flags: --clockify-api-key string set the API key @@ -11,15 +23,17 @@ Flags: ## Configuration options +The source provides the following extra configuration options. + | Config option | Kind | Description | Example | -|--------------------|--------|------------------------------------------------------------|---------------------------------------| +| ------------------ | ------ | ---------------------------------------------------------- | ------------------------------------- | | clockify-url | string | URL for the Clockify installation without a trailing slash | clockify-url = "https://clockify.me" | | clockify-api-key | string | API key gathered from Clockify[^1] | clockify-api-key = "" | -| clockify-workspace | string | Clockify workspace ID[^2] | clockify-workspace = "" | +| clockify-workspace | string | Clockify workspace ID[^2] | clockify-workspace = "" | ## Limitations -* It is not possible to filter for projects when fetching, though it is a [planned](https://github.com/gabor-boros/minutes/issues/1) feature. +- It is not possible to filter for projects when fetching, though it is a [planned](https://github.com/gabor-boros/minutes/issues/1) feature. [^1]: As described in the [API documentation](https://clockify.me/developers-api), visit the [settings](https://clockify.me/user/settings) page to get your API token. -[^2]: To get your workspace ID, navigate to workspace settings and copy the ID from the URL. \ No newline at end of file +[^2]: To get your workspace ID, navigate to workspace settings and copy the ID from the URL. diff --git a/www/docs/sources/tempo.md b/www/docs/sources/tempo.md new file mode 100644 index 0000000..4e70a38 --- /dev/null +++ b/www/docs/sources/tempo.md @@ -0,0 +1,37 @@ +Source documentation for [Tempo](https://tempo.io/). + +## Field mappings + +The source makes the following special mappings. + +| From | To | Description | +| ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| AccountKey | Client | | +| ProjectKey | Project | Tasks will be used for defining the summary of an entry; in case the `tags-as-tasks` is enabled, Summary will be set to the Description of the item | +| IssueKey | Task | | +| Comment | Notes | | + +## CLI flags + +The source provides to following extra CLI flags. + +```plaintext +Flags: + --tempo-password string set the login password + --tempo-url string set the base URL + --tempo-username string set the login user ID +``` + +## Configuration options + +The source provides the following extra configuration options. + +| Config option | Kind | Description | Example | +| -------------- | ------ | ------------------------------------------------------ | ------------------------------------------- | +| tempo-password | string | Jira password | tempo-password = "" | +| tempo-url | string | URL for the Jira installation without a trailing slash | tempo-url = "https://example.atlassian.net" | +| tempo-username | string | Jira username | tempo-username = "gabor-boros" | + +## Limitations + +- It is not possible to filter for projects when fetching, though it is a [planned](https://github.com/gabor-boros/minutes/issues/1) feature. diff --git a/www/docs/targets/tempo.md b/www/docs/targets/tempo.md new file mode 100644 index 0000000..eff6fd8 --- /dev/null +++ b/www/docs/targets/tempo.md @@ -0,0 +1,29 @@ +Target documentation for [Tempo](https://tempo.io/). + +!!! warning + + Tempo can go crazy when not a whole minute is uploaded. It is highly recommended using the `round-to-closest-minute` option. + +## Field mappings + +The target makes the following special mappings. + +| From | To | Description | +| ---------- | ------------ | --------------------------------------------------------------------------------------------- | +| Summary | Comment | The entry summary will be used as the comment | +| Task | OriginTaskID | Since OriginTaskID must be an Issue Key, the Issue Key defined by Task must represent in Jira | +| tempo-user | Worker | | + +## CLI flags + +The target does not provide additional CLI flags. + +## Configuration options + +The target does not provide additional configuration options. + +## Limitations + +- It is not possible to filter for projects when fetching, though it is a [planned](https://github.com/gabor-boros/minutes/issues/1) feature. +- Tempo entries cannot have Summary and Notes at the same time, therefore we use Summary for the comment field during upload. +- At the moment, it is not possible to upload an entry in the name of someone else. diff --git a/www/mkdocs.yml b/www/mkdocs.yml new file mode 100644 index 0000000..b4a5a6e --- /dev/null +++ b/www/mkdocs.yml @@ -0,0 +1,71 @@ +site_name: Minutes +site_url: https://github.com/gabor-boros/minutes +site_description: Sync worklogs between multiple time trackers, invoicing, and bookkeeping software. +copyright: Made with ❤️ by Minutes contributors. +repo_name: gabor-boros/minutes +repo_url: https://github.com/gabor-boros/minutes +edit_uri: edit/master/www/docs/ + +theme: + name: material + language: en + include_search_page: false + search_index_only: true + features: + - navigation.tracking + - navigation.top + palette: + - media: "(prefers-color-scheme: light)" # Light mode + scheme: default + primary: light blue + accent: blue + toggle: + icon: material/toggle-switch-off-outline + name: Switch to light mode + - media: "(prefers-color-scheme: dark)" # Dark mode + scheme: slate + primary: light blue + accent: blue + toggle: + icon: material/toggle-switch-outline + name: Switch to dark mode + +plugins: + - minify: + minify_html: true + - search: + lang: + - en + +extra: + social: + - icon: fontawesome/brands/github-alt + link: https://github.com/gabor-boros/minutes + +markdown_extensions: + - admonition + - codehilite + - footnotes + - meta + - pymdownx.highlight + - pymdownx.superfences + - toc: + permalink: true + - pymdownx.tasklist: + custom_checkbox: true + +extra_css: + - assets/css/minutes.css + +nav: +- Introduction: index.md +- getting-started.md +- configuration.md +- Sources: + - Clockify: sources/clockify.md + - Tempo: sources/tempo.md +- Targets: + - targets/tempo.md +- Contributing: CONTRIBUTING.md +- Changelog: CHANGELOG.md +- License: LICENSE.md diff --git a/www/requirements.txt b/www/requirements.txt new file mode 100644 index 0000000..8a923b9 --- /dev/null +++ b/www/requirements.txt @@ -0,0 +1,2 @@ +mkdocs-material==7.3.2 +mkdocs-minify-plugin==0.4.1