diff --git a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml index 02e3bc194120..89cd015ccfc8 100644 --- a/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml +++ b/nixos/doc/manual/from_md/release-notes/rl-2205.section.xml @@ -150,6 +150,14 @@ services.prosody-filer. + + + timetagger, + an open source time-tracker with an intuitive user experience + and powerful reporting. + services.timetagger. + +
diff --git a/nixos/doc/manual/release-notes/rl-2205.section.md b/nixos/doc/manual/release-notes/rl-2205.section.md index d42ba989f9de..2554292b6f12 100644 --- a/nixos/doc/manual/release-notes/rl-2205.section.md +++ b/nixos/doc/manual/release-notes/rl-2205.section.md @@ -46,6 +46,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [prosody-filer](https://github.com/ThomasLeister/prosody-filer), a server for handling XMPP HTTP Upload requests. Available at [services.prosody-filer](#opt-services.prosody-filer.enable). +- [timetagger](https://timetagger.app), an open source time-tracker with an intuitive user experience and powerful reporting. [services.timetagger](options.html#opt-services.timetagger.enable). + ## Backward Incompatibilities {#sec-release-22.05-incompatibilities} - `pkgs.ghc` now refers to `pkgs.targetPackages.haskellPackages.ghc`. diff --git a/nixos/modules/services/web-apps/timetagger.nix b/nixos/modules/services/web-apps/timetagger.nix new file mode 100644 index 000000000000..373f4fcd52f8 --- /dev/null +++ b/nixos/modules/services/web-apps/timetagger.nix @@ -0,0 +1,80 @@ +{ config, lib, pkgs, ... }: + +let + inherit (lib) mkEnableOption mkIf mkOption types literalExpression; + + cfg = config.services.timetagger; +in { + + options = { + services.timetagger = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Tag your time, get the insight + + + This app does not do authentication. + You must setup authentication yourself or run it in an environment where + only allowed users have access. + + ''; + }; + + bindAddr = mkOption { + description = "Address to bind to."; + type = types.str; + default = "127.0.0.1"; + }; + + port = mkOption { + description = "Port to bind to."; + type = types.port; + default = 8080; + }; + + package = mkOption { + description = '' + Use own package for starting timetagger web application. + + The ${literalExpression ''pkgs.timetagger''} package only provides a + "run.py" script for the actual package + ${literalExpression ''pkgs.python3Packages.timetagger''}. + + If you want to provide a "run.py" script for starting timetagger + yourself, you can do so with this option. + If you do so, the 'bindAddr' and 'port' options are ignored. + ''; + + default = pkgs.timetagger.override { addr = cfg.bindAddr; port = cfg.port; }; + defaultText = literalExpression '' + pkgs.timetagger.override { + addr = ${cfg.bindAddr}; + port = ${cfg.port}; + }; + ''; + type = types.package; + }; + }; + }; + + config = mkIf cfg.enable { + systemd.services.timetagger = { + description = "Timetagger service"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + User = "timetagger"; + Group = "timetagger"; + StateDirectory = "timetagger"; + + ExecStart = "${cfg.package}/bin/timetagger"; + + Restart = "on-failure"; + RestartSec = 1; + }; + }; + }; +} + diff --git a/pkgs/development/python-modules/asgineer/default.nix b/pkgs/development/python-modules/asgineer/default.nix new file mode 100644 index 000000000000..3a1861bbd182 --- /dev/null +++ b/pkgs/development/python-modules/asgineer/default.nix @@ -0,0 +1,32 @@ +{ lib +, buildPythonPackage +, fetchFromGitHub +, pytestCheckHook +, requests +}: + +buildPythonPackage rec { + pname = "asgineer"; + version = "0.8.1"; + + # PyPI tarball doesn't include tests directory + src = fetchFromGitHub { + owner = "almarklein"; + repo = pname; + rev = "v${version}"; + sha256 = "0hd1i9pc8m7sc8bkn31q4ygkmnl5vklrcziq9zkdiqaqm8clyhcx"; + }; + + checkInputs = [ + pytestCheckHook + requests + ]; + + meta = with lib; { + description = "A really thin ASGI web framework"; + license = licenses.bsd2; + homepage = "https://asgineer.readthedocs.io"; + maintainers = [ maintainers.matthiasbeyer ]; + }; +} + diff --git a/pkgs/development/python-modules/itemdb/default.nix b/pkgs/development/python-modules/itemdb/default.nix new file mode 100644 index 000000000000..f9afc4c5cb36 --- /dev/null +++ b/pkgs/development/python-modules/itemdb/default.nix @@ -0,0 +1,26 @@ +{ lib +, buildPythonPackage +, fetchFromGitHub +}: + +buildPythonPackage rec { + pname = "itemdb"; + version = "1.1.1"; + + # PyPI tarball doesn't include tests directory + src = fetchFromGitHub { + owner = "almarklein"; + repo = pname; + rev = "v${version}"; + sha256 = "0ksad5j91nlbsn0a11clf994qz7r9ijand5hxnjhgd66i9hl3y78"; + }; + + meta = with lib; { + description = "Easy transactional database for Python dicts, backed by SQLite"; + license = licenses.bsd2; + homepage = "https://itemdb.readthedocs.io"; + maintainers = [ maintainers.matthiasbeyer ]; + }; +} + + diff --git a/pkgs/development/python-modules/pscript/default.nix b/pkgs/development/python-modules/pscript/default.nix new file mode 100644 index 000000000000..fae2c8a42818 --- /dev/null +++ b/pkgs/development/python-modules/pscript/default.nix @@ -0,0 +1,39 @@ +{ lib +, buildPythonPackage +, fetchFromGitHub +, pytestCheckHook +, nodejs +}: + +buildPythonPackage rec { + pname = "pscript"; + version = "0.7.6"; + + # PyPI tarball doesn't include tests directory + src = fetchFromGitHub { + owner = "flexxui"; + repo = pname; + rev = "v${version}"; + sha256 = "169px5n4jjnpdn9y86f28qwd95bwf1q1rz0a1h3lb5nn5c6ym8c4"; + }; + + checkInputs = [ + pytestCheckHook + nodejs + ]; + + preCheck = '' + # do not execute legacy tests + rm -rf pscript_legacy + ''; + + meta = with lib; { + description = "Python to JavaScript compiler"; + license = licenses.bsd2; + homepage = "https://pscript.readthedocs.io"; + maintainers = [ maintainers.matthiasbeyer ]; + }; +} + + + diff --git a/pkgs/development/python-modules/timetagger/default.nix b/pkgs/development/python-modules/timetagger/default.nix new file mode 100644 index 000000000000..58bf190495f4 --- /dev/null +++ b/pkgs/development/python-modules/timetagger/default.nix @@ -0,0 +1,47 @@ +{ lib +, python3Packages +, fetchFromGitHub +, pytestCheckHook +, requests +}: + +python3Packages.buildPythonPackage rec { + pname = "timetagger"; + version = "22.1.2"; + + src = fetchFromGitHub { + owner = "almarklein"; + repo = pname; + rev = "v${version}"; + sha256 = "0xrajx0iij7r70ch17m4y6ydyh368dn6nbjsv74pn1x8frd686rw"; + }; + + meta = with lib; { + homepage = "https://timetagger.app"; + license = licenses.gpl3; + description = "Tag your time, get the insight"; + maintainers = with maintainers; [ matthiasbeyer ]; + }; + + checkInputs = [ + pytestCheckHook + requests + ]; + + preCheck = '' + # https://github.com/NixOS/nixpkgs/issues/12591 + mkdir -p check-phase + export HOME=$(pwd)/check-phase + ''; + + propagatedBuildInputs = with python3Packages; [ + asgineer + itemdb + jinja2 + markdown + pscript + pyjwt + uvicorn + ]; + +} diff --git a/pkgs/servers/timetagger/default.nix b/pkgs/servers/timetagger/default.nix new file mode 100644 index 000000000000..5e4629f455b2 --- /dev/null +++ b/pkgs/servers/timetagger/default.nix @@ -0,0 +1,39 @@ +{ lib +, pkgs +, python3Packages +, fetchFromGitHub + +, addr ? "127.0.0.1" +, port ? 8082 +}: + +# +# Timetagger itself is a library that a user must write a "run.py" script for +# We provide a basic "run.py" script with this package, which simply starts +# timetagger. +# + +let + tt = python3Packages.timetagger; +in +python3Packages.buildPythonPackage rec { + pname = tt.name; + version = tt.version; + src = tt.src; + meta = tt.meta; + + propagatedBuildInputs = [ tt ] + ++ (with python3Packages; [ + setuptools + ]); + + format = "custom"; + installPhase = '' + mkdir -p $out/bin + echo "#!${pkgs.python3}/bin/python3" >> $out/bin/timetagger + cat run.py >> $out/bin/timetagger + sed -Ei 's,0\.0\.0\.0:80,${addr}:${toString port},' $out/bin/timetagger + chmod +x $out/bin/timetagger + ''; +} + diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index ccbbcfc78b30..a2f722cc9d08 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -10202,6 +10202,8 @@ with pkgs; timetrap = callPackage ../applications/office/timetrap { }; + timetagger = callPackage ../servers/timetagger { }; + timekeeper = callPackage ../applications/office/timekeeper { }; timezonemap = callPackage ../development/libraries/timezonemap { }; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 83f068845ae9..1689bfdcb399 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -634,6 +634,8 @@ in { asgi-csrf = callPackage ../development/python-modules/asgi-csrf { }; + asgineer = callPackage ../development/python-modules/asgineer { }; + asgiref = callPackage ../development/python-modules/asgiref { }; asmog = callPackage ../development/python-modules/asmog { }; @@ -4055,6 +4057,8 @@ in { itemadapter = callPackage ../development/python-modules/itemadapter { }; + itemdb = callPackage ../development/python-modules/itemdb { }; + itemloaders = callPackage ../development/python-modules/itemloaders { }; iterm2 = callPackage ../development/python-modules/iterm2 { }; @@ -6332,6 +6336,8 @@ in { psautohint = callPackage ../development/python-modules/psautohint { }; + pscript = callPackage ../development/python-modules/pscript { }; + psd-tools = callPackage ../development/python-modules/psd-tools { }; psutil = callPackage ../development/python-modules/psutil { }; @@ -9713,6 +9719,8 @@ in { timeout-decorator = callPackage ../development/python-modules/timeout-decorator { }; + timetagger = callPackage ../development/python-modules/timetagger { }; + timezonefinder = callPackage ../development/python-modules/timezonefinder { }; tinycss2 = callPackage ../development/python-modules/tinycss2 { };