From 5caff109bf444087ec83f8f6e3257d5ffddefaa1 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Tue, 7 Mar 2023 16:52:44 +0100 Subject: [PATCH 01/55] feat: Support for new reminder array (read) --- vja/model.py | 22 ++++++++++++++++++++++ vja/service_command.py | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/vja/model.py b/vja/model.py index 31d51e9..407f08a 100755 --- a/vja/model.py +++ b/vja/model.py @@ -131,6 +131,26 @@ class Label: return [Label.from_json(x) for x in json_array or []] +@dataclass +@custom_output +@data_dict +# pylint: disable=too-many-instance-attributes +class TaskReminder: + json: dict = field(repr=False) + reminder: datetime + relative_period: int + relative_to: str + + @classmethod + def from_json(cls, json): + return cls(json, parse_json_date(json['reminder']), json['relative_period'], json['relative_to']) + + @classmethod + def from_json_array(cls, json_array): + return [TaskReminder.from_json(x) for x in json_array or []] + + + @dataclass @custom_output @data_dict @@ -144,6 +164,7 @@ class Task: is_favorite: bool due_date: datetime reminder_dates: typing.List[datetime] + reminders: typing.List[TaskReminder] repeat_mode: int repeat_after: timedelta start_date: datetime @@ -171,6 +192,7 @@ class Task: json['is_favorite'], parse_json_date(json['due_date']), [parse_json_date(reminder) for reminder in json['reminder_dates'] or []], + TaskReminder.from_json_array(json["reminders"]), json['repeat_mode'], timedelta(seconds=json['repeat_after']), parse_json_date(json['start_date']), diff --git a/vja/service_command.py b/vja/service_command.py index 45fbada..192d7d0 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -111,8 +111,9 @@ class CommandService: }) payload = self._args_to_payload(args) - logger.debug('post task: %s', payload) + logger.debug('update fields: %s', payload) task_remote.update(payload) + logger.debug('post task: %s', task_remote) task_json = self._api_client.post_task(task_id, task_remote) task_new = self._task_service.task_from_json(task_json) -- GitLab From fe2c33281206fcf4e121875164ab36ea78369987 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Wed, 8 Mar 2023 07:54:56 +0100 Subject: [PATCH 02/55] feat!: Preliminary support for new reminder array Reminders will only work with new Vikunja server instances --- tests/test_command.py | 57 +++++++++++------------------------------- vja/service_command.py | 54 ++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 66 deletions(-) diff --git a/tests/test_command.py b/tests/test_command.py index 50b3a5a..2d0e361 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -35,13 +35,13 @@ class TestAddTask: def test_default_reminder_uses_due(self, runner): res = invoke(runner, 'add title of new task --force --list=test-list --due=today --reminder') after = json_for_created_task(runner, res.output) - assert after['due_date'] == after['reminder_dates'][0] + assert after['reminders'][0]['relative_period'] == 0 + assert after['reminders'][0]['relative_to'] == 'due_date' - def test_default_reminder_with_missing_due_uses_tomorrow(self, runner): - res = invoke(runner, 'add title of new task --force --list=test-list --reminder') + def test_default_reminder_with_absolute_time(self, runner): + res = invoke(runner, 'add title of new task --force --list=test-list --reminder=tomorrow') after = json_for_created_task(runner, res.output) - assert after['due_date'] is None - assert TOMORROW_ISO[0:10] in after['reminder_dates'][0] + assert TOMORROW_ISO[0:10] in after['reminders'][0]['reminder'] class TestCloneTask: @@ -129,43 +129,14 @@ class TestEditGeneral: class TestEditReminder: - def test_set_default_reminder_to_remote_due(self, runner): - invoke(runner, f'edit 2 --due-date={TODAY_ISO}') - invoke(runner, f'edit 2 --reminder={TOMORROW_ISO}') - before = json_for_task_id(runner, 2) - - invoke(runner, 'edit 2 --reminder') - after = json_for_task_id(runner, 2) - assert before['reminder_dates'][0][:10] == TOMORROW.date().isoformat() - assert after['reminder_dates'][0][:10] == TODAY.date().isoformat() - - def test_set_default_reminder_to_tomorrow(self, runner): - invoke(runner, 'edit 2 --due-date=') - invoke(runner, f'edit 2 --reminder={TODAY_ISO}') - before = json_for_task_id(runner, 2) - - invoke(runner, 'edit 2 --reminder') - after = json_for_task_id(runner, 2) - assert before['reminder_dates'][0][:10] == TODAY.date().isoformat() - assert after['reminder_dates'][0][:10] == TOMORROW.date().isoformat() - - def test_unset_reminder(self, runner): - invoke(runner, f'edit 2 --reminder={TODAY_ISO}') - before = json_for_task_id(runner, 2) - - invoke(runner, 'edit 2 --reminder=') - after = json_for_task_id(runner, 2) - assert before['reminder_dates'][0][:10] == TODAY.date().isoformat() - assert not after['reminder_dates'] - def test_set_reminder_to_due(self, runner): invoke(runner, f'edit 2 --reminder={TODAY_ISO}') before = json_for_task_id(runner, 2) invoke(runner, f'edit 2 --due={TOMORROW_ISO} --reminder=due') after = json_for_task_id(runner, 2) - assert before['reminder_dates'][0][:10] == TODAY.date().isoformat() - assert after['reminder_dates'][0][:10] == TOMORROW.date().isoformat() + assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() + assert after['reminders'][0]['reminder'][:10] == TOMORROW.date().isoformat() def test_set_reminder_to_value(self, runner): invoke(runner, f'edit 2 --reminder={TODAY_ISO}') @@ -173,17 +144,17 @@ class TestEditReminder: invoke(runner, f'edit 2 --due={TODAY_ISO} --reminder={TOMORROW_ISO}') after = json_for_task_id(runner, 2) - assert before['reminder_dates'][0][:10] == TODAY.date().isoformat() - assert after['reminder_dates'][0][:10] == TOMORROW.date().isoformat() + assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() + assert after['reminders'][0]['reminder'][:10] == TOMORROW.date().isoformat() - def test_set_reminder_to_value_new_reminder(self, runner): - invoke(runner, 'edit 2 --reminder=') + def test_unset_reminder(self, runner): + invoke(runner, f'edit 2 --reminder={TODAY_ISO}') before = json_for_task_id(runner, 2) - invoke(runner, f'edit 2 --reminder={TOMORROW_ISO}') + invoke(runner, 'edit 2 --reminder=') after = json_for_task_id(runner, 2) - assert not before['reminder_dates'] - assert after['reminder_dates'][0][:10] == TOMORROW.date().isoformat() + assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() + assert not after['reminders'] class TestToggleDoneTask: diff --git a/vja/service_command.py b/vja/service_command.py index 192d7d0..11635e5 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -47,7 +47,7 @@ class CommandService: 'list_id': {'field': 'list_id', 'mapping': int}, 'bucket_id': {'field': 'bucket_id', 'mapping': int}, 'kanban_position': {'field': 'kanban_position', 'mapping': int}, - 'reminder': {'field': 'reminder_dates', 'mapping': (lambda x: x)} + 'reminder': {'field': 'reminders', 'mapping': (lambda x: x)} } def _args_to_payload(self, args: dict): @@ -69,10 +69,11 @@ class CommandService: list_id = self._list_service.get_default_list().id tag_name = args.pop('tag') if args.get('tag') else None is_force = args.pop('force_create') if args.get('force_create') is not None else False - if args.get('reminder') == 'due': - args.update({'reminder': args.get('due') or 'tomorrow'}) if args.get('reminder'): - args.update({'reminder': [parse_date_arg_to_iso(args.get('reminder'))]}) + if args.get('reminder') == 'due': + args.update({'reminder': [{'relative_to': 'due_date', 'relative_period': 0}]}) + else: + args.update({'reminder': [{'reminder': parse_date_arg_to_iso(args.get('reminder'))}]}) payload = self._args_to_payload(args) @@ -113,6 +114,8 @@ class CommandService: payload = self._args_to_payload(args) logger.debug('update fields: %s', payload) task_remote.update(payload) + # make sure we do not send back the old reminder_dates + task_remote.pop("reminder_dates", None) logger.debug('post task: %s', task_remote) task_json = self._api_client.post_task(task_id, task_remote) task_new = self._task_service.task_from_json(task_json) @@ -127,27 +130,32 @@ class CommandService: @staticmethod def _update_reminder(args, task_remote): + if args.get('reminder') is None: + return + + # create reminder entry if args.get('reminder') == 'due': - if args.get('due'): - args.update({'reminder': args.get('due')}) # reminder = cli argument --due - else: - if parse_json_date(task_remote['due_date']): - args.update({'reminder': task_remote['due_date']}) # reminder = due_date - else: - args.update({'reminder': 'tomorrow'}) # reminder default - if args.get('reminder') is not None: - # replace the first existing reminder - new_reminder = parse_date_arg_to_iso(args.pop('reminder')) - old_reminders = task_remote['reminder_dates'] - if old_reminders and len(old_reminders) > 0: - if new_reminder: - old_reminders[0] = new_reminder # overwrite first remote reminder_date - else: - old_reminders.pop(0) # remove first remote reminder_date + args.update( + {'reminder': [{'relative_to': 'due_date', 'relative_period': 0}]}) # --reminder=due or --reminder + elif args.get('reminder') == '': + args.update( + {'reminder': None}) # --reminder="" + else: + args.update( + {'reminder': [{'reminder': parse_date_arg_to_iso(args.get('reminder'))}]}) + + # replace the first existing reminder with our entry + new_reminder = args.pop('reminder')[0] if args.get('reminder') else None + old_reminders = task_remote['reminders'] + if old_reminders and len(old_reminders) > 0: + if new_reminder: + old_reminders[0] = new_reminder # overwrite first remote reminder else: - if new_reminder: - old_reminders = [new_reminder] # create single reminder_date - args.update({'reminder': old_reminders}) + old_reminders.pop(0) # remove first remote reminder + else: + if new_reminder: + old_reminders = [new_reminder] # create single reminder_date + args.update({'reminder': old_reminders}) def toggle_task_done(self, task_id): task_remote = self._api_client.get_task(task_id) -- GitLab From c5dbf43d582b244f8b17787ed12a06d160a20856 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Tue, 14 Mar 2023 14:52:10 +0100 Subject: [PATCH 03/55] fix: sharpen test --- tests/test_command.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_command.py b/tests/test_command.py index 2d0e361..981b4e3 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -137,6 +137,8 @@ class TestEditReminder: after = json_for_task_id(runner, 2) assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() assert after['reminders'][0]['reminder'][:10] == TOMORROW.date().isoformat() + assert after['reminders'][0]['relative_period'] == 0 + assert after['reminders'][0]['relative_to'] == 'due_date' def test_set_reminder_to_value(self, runner): invoke(runner, f'edit 2 --reminder={TODAY_ISO}') @@ -146,6 +148,7 @@ class TestEditReminder: after = json_for_task_id(runner, 2) assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() assert after['reminders'][0]['reminder'][:10] == TOMORROW.date().isoformat() + assert not after['reminders'][0]['relative_to'] def test_unset_reminder(self, runner): invoke(runner, f'edit 2 --reminder={TODAY_ISO}') -- GitLab From b1df70496a070b827c7431c68181d4ec18aa5190 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Tue, 28 Mar 2023 12:29:10 +0200 Subject: [PATCH 04/55] feat(api)!: New projects api (only backend side) --- tests/docker-compose.yml | 14 +++++++------- vja/apiclient.py | 16 ++++++++-------- vja/model.py | 2 +- vja/service_command.py | 4 ++-- vja/task_service.py | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index d8bf998..74ab6b5 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: api: - image: vikunja/api:0.20.4 + image: vikunja/api:unstable ports: - "3456:3456" environment: @@ -13,10 +13,10 @@ services: /app/vikunja/vikunja user create -u test -p test -e test@test.test exec /app/vikunja/vikunja " - frontend: - image: vikunja/frontend:0.20.5 - ports: - - "8080:80" - environment: - VIKUNJA_API_URL: http://localhost:3456/api/v1 +# frontend: +# image: vikunja/frontend:0.20.5 +# ports: +# - "8080:80" +# environment: +# VIKUNJA_API_URL: http://localhost:3456/api/v1 diff --git a/vja/apiclient.py b/vja/apiclient.py index c40e4e8..132ff82 100755 --- a/vja/apiclient.py +++ b/vja/apiclient.py @@ -41,7 +41,7 @@ class ApiClient: def __init__(self, api_url, token_file): logger.debug('Connecting to api_url %s', api_url) self._api_url = api_url - self._cache = {'lists': None, 'labels': None, 'namespaces': None, 'tasks': None} + self._cache = {'projects': None, 'labels': None, 'namespaces': None, 'tasks': None} self._login = Login(api_url, token_file) def _create_url(self, path): @@ -117,19 +117,19 @@ class ApiClient: return self._cache['namespaces'] def get_lists(self): - if self._cache['lists'] is None: - self._cache['lists'] = self._get_json(self._create_url('/lists')) or [] - return self._cache['lists'] + if self._cache['projects'] is None: + self._cache['projects'] = self._get_json(self._create_url('/projects')) or [] + return self._cache['projects'] def get_list(self, list_id): - return self._get_json(self._create_url(f'/lists/{str(list_id)}')) + return self._get_json(self._create_url(f'/projects/{str(list_id)}')) def put_list(self, namespace_id, title): payload = {'title': title} - return self._put_json(self._create_url(f'/namespaces/{str(namespace_id)}/lists'), payload=payload) + return self._put_json(self._create_url(f'/namespaces/{str(namespace_id)}/projects'), payload=payload) def get_buckets(self, list_id): - return self._get_json(self._create_url(f'/lists/{str(list_id)}/buckets')) + return self._get_json(self._create_url(f'/projects/{str(list_id)}/buckets')) def get_labels(self): if self._cache['labels'] is None: @@ -152,7 +152,7 @@ class ApiClient: return self._get_json(url) def put_task(self, list_id, payload): - return self._put_json(self._create_url(f'/lists/{str(list_id)}'), payload=payload) + return self._put_json(self._create_url(f'/projects/{str(list_id)}'), payload=payload) def post_task(self, task_id, payload): return self._post_json(self._create_url(f'/tasks/{str(task_id)}'), payload=payload) diff --git a/vja/model.py b/vja/model.py index 407f08a..b138e32 100755 --- a/vja/model.py +++ b/vja/model.py @@ -49,7 +49,7 @@ class User: @classmethod def from_json(cls, json): - return cls(json, json['id'], json['username'], json['name'], json['settings']['default_list_id']) + return cls(json, json['id'], json['username'], json['name'], json['settings']['default_project_id']) @dataclass(frozen=True) diff --git a/vja/service_command.py b/vja/service_command.py index 11635e5..e0d9bb2 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -44,7 +44,7 @@ class CommandService: 'favorite': {'field': 'is_favorite', 'mapping': bool}, 'completed': {'field': 'done', 'mapping': bool}, 'position': {'field': 'position', 'mapping': int}, - 'list_id': {'field': 'list_id', 'mapping': int}, + 'list_id': {'field': 'project_id', 'mapping': int}, 'bucket_id': {'field': 'bucket_id', 'mapping': int}, 'kanban_position': {'field': 'kanban_position', 'mapping': int}, 'reminder': {'field': 'reminders', 'mapping': (lambda x: x)} @@ -94,7 +94,7 @@ class CommandService: task_remote.update({'title': title}) logger.debug('put task: %s', task_remote) - task_json = self._api_client.put_task(task_remote['list_id'], task_remote) + task_json = self._api_client.put_task(task_remote['project_id'], task_remote) task = self._task_service.task_from_json(task_json) return task diff --git a/vja/task_service.py b/vja/task_service.py index a006abd..6e127ba 100644 --- a/vja/task_service.py +++ b/vja/task_service.py @@ -13,7 +13,7 @@ class TaskService: self._urgency = urgency def task_from_json(self, task_json: dict) -> Task: - list_object = self._list_service.find_list_by_id(task_json['list_id']) + list_object = self._list_service.find_list_by_id(task_json['project_id']) labels = Label.from_json_array(task_json['labels']) task = Task.from_json(task_json, list_object, labels) task.urgency = self._urgency.compute_for(task) -- GitLab From 6f18cff9ffae2e95dafd9c936400b5e216b44008 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Tue, 28 Mar 2023 15:22:21 +0200 Subject: [PATCH 05/55] feat(api)!: remove reminder_dates --- .vjacli/vja.rc | 2 +- Features.md | 51 +++++++++++++++++++++++++++++++++++--- tests/.vjatest/vja.rc | 2 +- tests/.vjatest_dind/vja.rc | 2 +- tests/test_command.py | 2 +- vja/model.py | 2 -- vja/output.py | 2 +- vja/service_command.py | 2 +- 8 files changed, 54 insertions(+), 11 deletions(-) diff --git a/.vjacli/vja.rc b/.vjacli/vja.rc index 579cff5..ce3994a 100755 --- a/.vjacli/vja.rc +++ b/.vjacli/vja.rc @@ -8,7 +8,7 @@ api_url=https://try.vikunja.io/api/v1 # Be careful: Any code which is entered here gets executed at runtime (python eval()). # Do not use --custom-format if you feel uncomfortable with that. -tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminder_dates else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} +tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} tasklist_short={x.id:5} {x.title:50.50} ids_only={x.id} diff --git a/Features.md b/Features.md index 18e56d5..2914505 100644 --- a/Features.md +++ b/Features.md @@ -22,18 +22,21 @@ vja add --help ``` for more. + ### Clone + Another option to create a new task is cloning an existing task + ```shell -vja clone 1 Clone a new task +vja clone 1 Clone a new task ``` See + ```shell vja clone --help ``` - ## List tasks List all active tasks @@ -44,7 +47,12 @@ vja ls --json ``` ### Urgency -By default tasks are sorted (amongst others) by their urgency, which is displayed in the last column. Urgency is calculated by regarding due_date, priority and is_favorite of the task, as well as the occurence of keywords in the list title or the label titles. The weights of each factor and the keywords can be specified in the configuration file ~/.vjacli/vja.rc. See Configuration section in [Readme.md](Readme.md). See [.vjacli/vja.rc](.vjacli/vja.rc) for an example. + +By default, tasks are sorted (amongst others) by their urgency, which is displayed in the last column. Urgency is +calculated by regarding due_date, priority and is_favorite of the task, as well as the occurence of keywords in the list +title or the label titles. The weights of each factor and the keywords can be specified in the configuration file ~ +/.vjacli/vja.rc. See Configuration section in [Readme.md](Readme.md). See [.vjacli/vja.rc](.vjacli/vja.rc) for an +example. ### Filter @@ -123,7 +131,9 @@ Toggle tag (=label). Use with --force to create new label: ```shell vja edit 1 -t @work ``` + Mark as done + ```shell vja edit 1 --done="true" vja check 1 # Shortcut to toggle the done flag of task 1 @@ -137,6 +147,41 @@ vja defer --help ``` This command moves the due_date (and later the reminder) ahead in time. +### Reminders + +vja manages only the first reminder of the task. That is the earliest reminder on the server. + +Set reminder to an absolute time + +```shell +vja edit 1 -r "next sunday at 11:00" +vja edit 1 --reminder="in 3 days at 11:00" +``` + +Set reminder equal to due date + +```shell +vja edit 1 -r +vja edit 1 --reminder +``` + +Set reminder relative to due date + +```shell +Not yet implemented! +``` + +Remove the earliest reminder + +```shell +vja edit 1 -r "" +vja edit 1 --reminder="" +``` + +The same goes for `vja add`. + +### Batch editing + Multiple edits are possible by giving more task ids ```shell diff --git a/tests/.vjatest/vja.rc b/tests/.vjatest/vja.rc index 4e35eae..5aa2fc1 100644 --- a/tests/.vjatest/vja.rc +++ b/tests/.vjatest/vja.rc @@ -8,7 +8,7 @@ api_url=http://localhost:3456/api/v1 # Be careful: Any code which is entered here gets executed at runtime (python eval()). # Do not use --custom-format if you feel uncomfortable with that. -tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminder_dates else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} +tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} tasklist_short={x.id:5} {x.title:50.50} ids_only={x.id} diff --git a/tests/.vjatest_dind/vja.rc b/tests/.vjatest_dind/vja.rc index 61a36fd..428f7dc 100644 --- a/tests/.vjatest_dind/vja.rc +++ b/tests/.vjatest_dind/vja.rc @@ -8,7 +8,7 @@ api_url=http://docker:3456/api/v1 # Be careful: Any code which is entered here gets executed at runtime (python eval()). # Do not use --custom-format if you feel uncomfortable with that. -tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminder_dates else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} +tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} tasklist_short={x.id:5} {x.title:50.50} ids_only={x.id} diff --git a/tests/test_command.py b/tests/test_command.py index 981b4e3..8606446 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -68,7 +68,7 @@ class TestEditGeneral: assert after['updated'] > before['updated'] # other attributes remain in place assert after['due_date'] == before['due_date'] - assert after['reminder_dates'] == before['reminder_dates'] + assert after['reminders'] == before['reminders'] assert after['position'] == before['position'] assert after['tasklist']['id'] == before['tasklist']['id'] assert after['created'] == before['created'] diff --git a/vja/model.py b/vja/model.py index b138e32..308d175 100755 --- a/vja/model.py +++ b/vja/model.py @@ -163,7 +163,6 @@ class Task: priority: int is_favorite: bool due_date: datetime - reminder_dates: typing.List[datetime] reminders: typing.List[TaskReminder] repeat_mode: int repeat_after: timedelta @@ -191,7 +190,6 @@ class Task: json['priority'], json['is_favorite'], parse_json_date(json['due_date']), - [parse_json_date(reminder) for reminder in json['reminder_dates'] or []], TaskReminder.from_json_array(json["reminders"]), json['repeat_mode'], timedelta(seconds=json['repeat_after']), diff --git a/vja/output.py b/vja/output.py index 754cfd8..485abad 100644 --- a/vja/output.py +++ b/vja/output.py @@ -16,7 +16,7 @@ LABEL_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20}' TASK_LIST_FORMAT_DEFAULT = '{x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} ' \ '{x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} ' \ - '{"R" if x.reminder_dates else " "} {x.tasklist.title:20.20} ' \ + '{"R" if x.reminders else " "} {x.tasklist.title:20.20} ' \ '{x.label_titles:20.20} {x.urgency:3.1f}' logger = logging.getLogger(__name__) diff --git a/vja/service_command.py b/vja/service_command.py index e0d9bb2..0122c61 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -154,7 +154,7 @@ class CommandService: old_reminders.pop(0) # remove first remote reminder else: if new_reminder: - old_reminders = [new_reminder] # create single reminder_date + old_reminders = [new_reminder] # create single reminder args.update({'reminder': old_reminders}) def toggle_task_done(self, task_id): -- GitLab From 18534b4921a04e603ad4003a4a3f3ad9196de10c Mon Sep 17 00:00:00 2001 From: cernst72 Date: Thu, 30 Mar 2023 23:23:04 +0200 Subject: [PATCH 06/55] feat(reminders): Set relative reminders like "1h before due" --- Features.md | 5 ++-- tests/test_command.py | 60 +++++++++++++++++++++++++++++------------- vja/cli.py | 10 ++++--- vja/model.py | 8 +++++- vja/service_command.py | 45 ++++++++++++++++++------------- 5 files changed, 85 insertions(+), 43 deletions(-) diff --git a/Features.md b/Features.md index 2914505..75570cd 100644 --- a/Features.md +++ b/Features.md @@ -165,10 +165,11 @@ vja edit 1 -r vja edit 1 --reminder ``` -Set reminder relative to due date +Set reminder relative to due date (only due date is supported by vja for relative reminders) ```shell -Not yet implemented! +vja edit --reminder="1h before due_date" +vja edit -r "10m before due" ``` Remove the earliest reminder diff --git a/tests/test_command.py b/tests/test_command.py index 8606446..0558d4a 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -6,10 +6,12 @@ from tests.conftest import invoke from vja.cli import cli ADD_SUCCESS_PATTERN = re.compile(r'.*Created task (\d+) in list .*') +DATE_1 = datetime.datetime(2023, 3, 30, 15, 0, 0, 0) +DATE_2 = DATE_1 + datetime.timedelta(days=1) +DATE_1_ISO = DATE_1.isoformat() +DATE_2_ISO = DATE_2.isoformat() TODAY = datetime.datetime.now() -TOMORROW = (datetime.datetime.now() + datetime.timedelta(days=1)) TODAY_ISO = TODAY.isoformat() -TOMORROW_ISO = TOMORROW.isoformat() class TestAddTask: @@ -39,9 +41,9 @@ class TestAddTask: assert after['reminders'][0]['relative_to'] == 'due_date' def test_default_reminder_with_absolute_time(self, runner): - res = invoke(runner, 'add title of new task --force --list=test-list --reminder=tomorrow') + res = invoke(runner, f'add title of new task --force --list=test-list --reminder={DATE_2_ISO}') after = json_for_created_task(runner, res.output) - assert TOMORROW_ISO[0:10] in after['reminders'][0]['reminder'] + assert after['reminders'][0]['reminder'] == DATE_2_ISO class TestCloneTask: @@ -79,7 +81,7 @@ class TestEditGeneral: invoke(runner, 'edit 1 --due=today') after = json_for_task_id(runner, 1) - assert datetime.date.today().isoformat()[0:10] in after['due_date'] + assert after['due_date'][:10] == TODAY_ISO[:10] assert after['updated'] >= before['updated'] def test_unset_due_date(self, runner): @@ -129,34 +131,56 @@ class TestEditGeneral: class TestEditReminder: + def test_set_reminder_to_absolute_value(self, runner): + invoke(runner, f'edit 2 --reminder={DATE_1_ISO}') + before = json_for_task_id(runner, 2) + + invoke(runner, f'edit 2 --due={DATE_1_ISO} --reminder={DATE_2_ISO}') + + after = json_for_task_id(runner, 2) + assert before['reminders'][0]['reminder'] == DATE_1_ISO + assert after['reminders'][0]['reminder'] == DATE_2_ISO + assert not after['reminders'][0]['relative_to'] + def test_set_reminder_to_due(self, runner): - invoke(runner, f'edit 2 --reminder={TODAY_ISO}') + invoke(runner, f'edit 2 --reminder={DATE_1_ISO}') before = json_for_task_id(runner, 2) - invoke(runner, f'edit 2 --due={TOMORROW_ISO} --reminder=due') + invoke(runner, f'edit 2 --due={DATE_2_ISO} --reminder=due') + after = json_for_task_id(runner, 2) - assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() - assert after['reminders'][0]['reminder'][:10] == TOMORROW.date().isoformat() + assert before['reminders'][0]['reminder'] == DATE_1_ISO + assert after['reminders'][0]['reminder'] == DATE_2_ISO assert after['reminders'][0]['relative_period'] == 0 assert after['reminders'][0]['relative_to'] == 'due_date' - def test_set_reminder_to_value(self, runner): - invoke(runner, f'edit 2 --reminder={TODAY_ISO}') - before = json_for_task_id(runner, 2) + def test_set_reminder_to_due_empty_option(self, runner): + invoke(runner, f'edit 2 --reminder={DATE_1_ISO}') + + invoke(runner, f'edit 2 --due={DATE_2_ISO} --reminder') - invoke(runner, f'edit 2 --due={TODAY_ISO} --reminder={TOMORROW_ISO}') after = json_for_task_id(runner, 2) - assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() - assert after['reminders'][0]['reminder'][:10] == TOMORROW.date().isoformat() - assert not after['reminders'][0]['relative_to'] + assert after['reminders'][0]['reminder'] == DATE_2_ISO + assert after['reminders'][0]['relative_period'] == 0 + assert after['reminders'][0]['relative_to'] == 'due_date' + + def test_set_reminder_to_relative_value(self, runner): + invoke(runner, f'edit 2 --reminder={DATE_1_ISO}') + + invoke(runner, ['edit', '2', '--due={DATE_2_ISO}', '--reminder=1h1m before due_date']) + + after = json_for_task_id(runner, 2) + assert after['reminders'][0]['relative_period'] == -3660 + assert after['reminders'][0]['relative_to'] == 'due_date' def test_unset_reminder(self, runner): - invoke(runner, f'edit 2 --reminder={TODAY_ISO}') + invoke(runner, f'edit 2 --reminder={DATE_1_ISO}') before = json_for_task_id(runner, 2) invoke(runner, 'edit 2 --reminder=') + after = json_for_task_id(runner, 2) - assert before['reminders'][0]['reminder'][:10] == TODAY.date().isoformat() + assert before['reminders'][0]['reminder'] == DATE_1_ISO assert not after['reminders'] diff --git a/vja/cli.py b/vja/cli.py index cd23c2b..6b122bd 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -225,7 +225,9 @@ def label_add(application, title): @click.option('tag', '-t', '--tag', '--label', help='Set label (label must exist on server)') @click.option('reminder', '-r', '--alarm', '--remind', '--reminder', is_flag=False, flag_value='due', - help='Set reminder (supports parsedatetime expressions). Leave empty to set to due date.') + help='Set reminder (supports parsedatetime and timedelta expressions). ' + 'Absolute: "in 3 days at 18:00" or relative: "1h before due_date" or just -r to set equal to ' + 'due date.') @click.option('force_create', '--force-create', '--force', is_flag=True, help='Force creation of non existing label') @with_application @@ -257,7 +259,7 @@ def task_clone(ctx, application, task_id, title): @click.option('note', '-n', '--note', '--description', help='Set description (note)') @click.option('note_append', '-a', '--note-append', '--append-note', '--description-append', '--append-description', - help='Append description to existing note separated by new line') + help='Append note to existing description separated by new line') @click.option('prio', '-p', '--prio', '--priority', type=click.INT, help='Set priority') @click.option('list_id', '-l', '--folder-id', '--project-id', '--list-id', '--list_id', type=click.INT, @@ -277,7 +279,9 @@ def task_clone(ctx, application, task_id, title): @click.option('tag', '-t', '--tag', '--label', help='Set label (label must exist on server unless called with --force-create)') @click.option('reminder', '-r', '--alarm', '--remind', '--reminder', is_flag=False, flag_value='due', - help='Set reminder (supports parsedatetime expressions). Leave empty to set to due date.') + help='Set reminder (supports parsedatetime and timedelta expressions). ' + 'Absolute: "in 3 days at 18:00" or relative: "1h30m before due_date" or just -r to set equal to ' + 'due date.') @click.option('force_create', '--force-create', '--force', is_flag=True, default=None, help='Force creation of non existing label') @with_application diff --git a/vja/model.py b/vja/model.py index 308d175..5839a8b 100755 --- a/vja/model.py +++ b/vja/model.py @@ -14,7 +14,11 @@ def custom_output(cls): if attribute.name != 'json' and getattr(self, attribute.name)) def _str_value(attribute_value): - return [_str_value(x) for x in attribute_value] if isinstance(attribute_value, list) else str(attribute_value) + if isinstance(attribute_value, datetime): + return attribute_value.isoformat() + if isinstance(attribute_value, list): + return [_str_value(x) for x in attribute_value] + return str(attribute_value) setattr(cls, '__str__', str_function) return cls @@ -25,6 +29,8 @@ def data_dict(cls): return {k: _transform_value(v) for k, v in self.__dict__.items() if k != 'json'} def _transform_value(v): + if isinstance(v, datetime): + return v.isoformat() if _is_data_dict(v): return v.data_dict() if isinstance(v, list): diff --git a/vja/service_command.py b/vja/service_command.py index 0122c61..8345433 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -69,11 +69,8 @@ class CommandService: list_id = self._list_service.get_default_list().id tag_name = args.pop('tag') if args.get('tag') else None is_force = args.pop('force_create') if args.get('force_create') is not None else False - if args.get('reminder'): - if args.get('reminder') == 'due': - args.update({'reminder': [{'relative_to': 'due_date', 'relative_period': 0}]}) - else: - args.update({'reminder': [{'reminder': parse_date_arg_to_iso(args.get('reminder'))}]}) + + self._parse_reminder_arg(args.get('reminder'), args) payload = self._args_to_payload(args) @@ -130,22 +127,11 @@ class CommandService: @staticmethod def _update_reminder(args, task_remote): - if args.get('reminder') is None: - return - - # create reminder entry - if args.get('reminder') == 'due': - args.update( - {'reminder': [{'relative_to': 'due_date', 'relative_period': 0}]}) # --reminder=due or --reminder - elif args.get('reminder') == '': - args.update( - {'reminder': None}) # --reminder="" - else: - args.update( - {'reminder': [{'reminder': parse_date_arg_to_iso(args.get('reminder'))}]}) + reminder_arg = args.get('reminder') + CommandService._parse_reminder_arg(reminder_arg, args) # replace the first existing reminder with our entry - new_reminder = args.pop('reminder')[0] if args.get('reminder') else None + new_reminder = args.pop('reminder')[0] if reminder_arg else None old_reminders = task_remote['reminders'] if old_reminders and len(old_reminders) > 0: if new_reminder: @@ -157,6 +143,27 @@ class CommandService: old_reminders = [new_reminder] # create single reminder args.update({'reminder': old_reminders}) + @staticmethod + def _parse_reminder_arg(reminder_arg, args): + if reminder_arg is None: + return + if reminder_arg == 'due': + args.update( + {'reminder': [{'relative_to': 'due_date', 'relative_period': 0}]}) # --reminder=due or --reminder + elif 'due' in reminder_arg: + reminder_due_args = reminder_arg.split(" ", 2) + duration = int(parse_date_arg_to_timedelta(reminder_due_args[0]).total_seconds()) + sign = -1 if reminder_due_args[1] == 'before' else 1 + args.update( + {'reminder': [{'relative_to': 'due_date', + 'relative_period': sign * duration}]}) # --reminder="1h before due_date" + elif reminder_arg == '': + args.update( + {'reminder': None}) # --reminder="" + else: + args.update( + {'reminder': [{'reminder': parse_date_arg_to_iso(reminder_arg)}]}) + def toggle_task_done(self, task_id): task_remote = self._api_client.get_task(task_id) task_remote.update({'done': not task_remote['done']}) -- GitLab From 719943a9d1b77a7663d87abac602f8d869c246b1 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 10:41:17 +0200 Subject: [PATCH 07/55] chore: Remove redundant test --- tests/test_command.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_command.py b/tests/test_command.py index 0558d4a..4937375 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -28,12 +28,6 @@ class TestAddTask: def test_duplicate_task_title_rejected(self, runner): invoke(runner, 'add title of new task', 1) - def test_positions_not_null(self, runner): - res = invoke(runner, 'add any other new task --force') - after = json_for_created_task(runner, res.output) - assert after['kanban_position'] > 0 - assert after['position'] > 0 - def test_default_reminder_uses_due(self, runner): res = invoke(runner, 'add title of new task --force --list=test-list --due=today --reminder') after = json_for_created_task(runner, res.output) -- GitLab From e394ca5e3959a77e1a8bb39285f4dc348d997cbd Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 10:42:05 +0200 Subject: [PATCH 08/55] doc: Add table of contents to Features.md --- Features.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Features.md b/Features.md index 75570cd..42f4d20 100644 --- a/Features.md +++ b/Features.md @@ -1,4 +1,26 @@ # Features + +* [Features](#features) + * [Create Task](#create-task) + * [Clone](#clone) + * [List tasks](#list-tasks) + * [Urgency](#urgency) + * [Filter](#filter) + * [Sort](#sort) + * [Select](#select) + * [Show single task by id](#show-single-task-by-id) + * [Modify tasks](#modify-tasks) + * [Reminders](#reminders) + * [Batch editing](#batch-editing) + * [Open Vikunja in browser](#open-vikunja-in-browser) + * [Manage lists, namespaces, labels, buckets](#manage-lists-namespaces-labels-buckets) + * [Manage namespaces](#manage-namespaces) + * [Manage lists (projects)](#manage-lists-projects) + * [Manage kanban buckets](#manage-kanban-buckets) + * [Manage labels](#manage-labels) + * [Output format](#output-format) + * [Terminate session](#terminate-session) + ## Create Task @@ -6,7 +28,7 @@ context: ```shell -vja add Make things work --note="find out how" -priority=3 --favorite=True --due="tomorrow at 11:00" --reminder --tag=@work +vja add Getting things done --note="find out how" -priority=3 --favorite=True --due="tomorrow at 11:00" --reminder --tag=@work ``` or more concise -- GitLab From de4df867ec80fbead7e8831edbc8d38fd46e0a76 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 10:54:14 +0200 Subject: [PATCH 09/55] ci: update semantic-release configuration --- .releaserc.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.releaserc.yml b/.releaserc.yml index 9f59c41..6d05e0a 100644 --- a/.releaserc.yml +++ b/.releaserc.yml @@ -1,6 +1,6 @@ # spec: https://semantic-release.gitbook.io/semantic-release/usage/configuration tagFormat: "${version}" -branches: [main, next] +branches: [ main, next ] plugins: # Determine the type of release by analyzing commits. # ie: Major, Minor or Patch @@ -14,11 +14,13 @@ plugins: - { type: perf, release: patch } - { type: docs, release: patch } - { type: refactor, release: patch } - - { type: style, release: patch } - { type: build, release: patch } - - { type: ci, release: patch } - { type: test, release: patch } + - { type: tests, release: patch } - { type: update, release: patch } + - { type: chore, release: false } + - { type: ci, release: false } + - { scope: no-release, release: false } - - "@semantic-release/release-notes-generator" - preset: conventionalcommits presetConfig: @@ -26,12 +28,11 @@ plugins: - { type: feat, section: "Features" } - { type: new, section: "Features" } - { type: fix, section: "Bug Fixes" } - - { type: chore, section: "Misc" } - { type: doc, section: "Documentation" } - { type: docs, section: "Documentation" } - - { type: style, section: "Improvements" } - - { type: refactor, section: "Improvements" } - - { type: perf, section: "Improvements" } + - { type: chore, section: "Misc" } + - { type: refactor, section: "Misc" } + - { type: perf, section: "Misc" } - { type: test, section: "Automation" } - { type: tests, section: "Automation" } - { type: ci, section: "Automation" } -- GitLab From aec5f53ed530a3e1a486b7cad56a9c1613ae100a Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 15:30:38 +0200 Subject: [PATCH 10/55] feat: defer reminder --- Features.md | 9 +++++++-- tests/test_command.py | 18 ++++++++++++++---- vja/cli.py | 2 +- vja/parse.py | 4 ++-- vja/service_command.py | 27 ++++++++++++++++++++++----- 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/Features.md b/Features.md index 42f4d20..6e559c4 100644 --- a/Features.md +++ b/Features.md @@ -1,4 +1,5 @@ # Features + * [Features](#features) * [Create Task](#create-task) @@ -10,6 +11,7 @@ * [Select](#select) * [Show single task by id](#show-single-task-by-id) * [Modify tasks](#modify-tasks) + * [Defer task](#defer-task) * [Reminders](#reminders) * [Batch editing](#batch-editing) * [Open Vikunja in browser](#open-vikunja-in-browser) @@ -162,12 +164,15 @@ vja check 1 # Shortcut to toggle the done flag of task 1 ``` ### Defer task + There is a shortcut for setting a delay on a task by giving a timedelta expression. + ```shell vja defer 1 1d vja defer --help ``` -This command moves the due_date (and later the reminder) ahead in time. + +This command moves the due_date and the first reminder ahead in time. ### Reminders @@ -205,7 +210,7 @@ The same goes for `vja add`. ### Batch editing -Multiple edits are possible by giving more task ids +Multiple edits and defers are possible by giving more task ids ```shell vja edit 1 5 8 --due="next monday 14:00" diff --git a/tests/test_command.py b/tests/test_command.py index 4937375..be39f0c 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -199,14 +199,24 @@ class TestToggleDoneTask: class TestDeferTask: - def test_defer_task(self, runner): - invoke(runner, f'edit 2 --due-date={TODAY_ISO}') + def test_defer_due_date_and_reminder(self, runner): + invoke(runner, f'edit 2 --due-date={DATE_1_ISO} --reminder={DATE_1_ISO}') invoke(runner, 'defer 2 1d') after = json_for_task_id(runner, 2) - assert after['due_date'][:10] == TOMORROW.date().isoformat() - assert after['reminder_dates'][0][:10] == TOMORROW.date().isoformat() + assert after['due_date'] == DATE_2_ISO + assert after['reminders'][0]['reminder'] == DATE_2_ISO + + def test_dont_modify_relative_reminder(self, runner): + invoke(runner, f'edit 2 --due-date={DATE_1_ISO} -r') + + invoke(runner, 'defer 2 1d') + + after = json_for_task_id(runner, 2) + assert after['due_date'] == DATE_2_ISO + assert after['reminders'][0]['relative_period'] == 0 + assert after['reminders'][0]['relative_to'] == 'due_date' class TestMultipleTasks: diff --git a/vja/cli.py b/vja/cli.py index 6b122bd..0f1789a 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -308,7 +308,7 @@ def task_toggle(ctx, application, task_id): @cli.command('defer', aliases=['delay'], help='Shortcut for moving the due_date and the reminders of the task. ' - 'Valid delay values are 2d, 1h30m.') + 'Examples for valid delay values are 2d, 1h30m.') @click.argument('task_ids', required=True, type=click.INT, nargs=-1) @click.argument('delay_by', required=True) @with_application diff --git a/vja/parse.py b/vja/parse.py index 288156a..5694767 100644 --- a/vja/parse.py +++ b/vja/parse.py @@ -29,10 +29,10 @@ def parse_date_arg_to_datetime(text: str) -> Optional[datetime]: def parse_date_arg_to_iso(text: str) -> str: - return format_datetime_to_json(parse_date_arg_to_datetime(text)) + return datetime_to_isoformat(parse_date_arg_to_datetime(text)) -def format_datetime_to_json(date: datetime) -> str: +def datetime_to_isoformat(date: datetime) -> str: return date.astimezone(tz.tzlocal()).isoformat() if date else None diff --git a/vja/service_command.py b/vja/service_command.py index 8345433..4229517 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -4,7 +4,7 @@ from vja import VjaError from vja.apiclient import ApiClient from vja.list_service import ListService from vja.model import Label -from vja.parse import parse_date_arg_to_iso, parse_json_date, parse_date_arg_to_timedelta, format_datetime_to_json +from vja.parse import parse_date_arg_to_iso, parse_json_date, parse_date_arg_to_timedelta, datetime_to_isoformat from vja.task_service import TaskService logger = logging.getLogger(__name__) @@ -90,6 +90,8 @@ class CommandService: task_remote.update({'id': None}) task_remote.update({'title': title}) + # make sure we do not send back the old reminder_dates + task_remote.pop("reminder_dates", None) logger.debug('put task: %s', task_remote) task_json = self._api_client.put_task(task_remote['project_id'], task_remote) task = self._task_service.task_from_json(task_json) @@ -166,18 +168,33 @@ class CommandService: def toggle_task_done(self, task_id): task_remote = self._api_client.get_task(task_id) + # make sure we do not send back the old reminder_dates + task_remote.pop("reminder_dates", None) task_remote.update({'done': not task_remote['done']}) task_json = self._api_client.post_task(task_id, task_remote) return self._task_service.task_from_json(task_json) def defer_task(self, task_id, delay_by): - task_remote = self._api_client.get_task(task_id) timedelta = parse_date_arg_to_timedelta(delay_by) + args = {} + + task_remote = self._api_client.get_task(task_id) due_date = parse_json_date(task_remote['due_date']) if due_date: - due_date = format_datetime_to_json(due_date + timedelta) - task_remote.update({'due_date': due_date}) - # TODO update absolute reminders + args.update({'due': datetime_to_isoformat(due_date + timedelta)}) + old_reminders = task_remote['reminders'] + if old_reminders and len(old_reminders) > 0: + reminder_date = parse_json_date(old_reminders[0]['reminder']) + is_absolute_reminder = not old_reminders[0]['relative_to'] + if reminder_date and is_absolute_reminder: + args.update({'reminder': datetime_to_isoformat(reminder_date + timedelta)}) + self._update_reminder(args, task_remote) + + payload = self._args_to_payload(args) + logger.debug('update fields: %s', payload) + task_remote.update(payload) + # make sure we do not send back the old reminder_dates + task_remote.pop("reminder_dates", None) task_json = self._api_client.post_task(task_id, task_remote) return self._task_service.task_from_json(task_json) -- GitLab From 3a936d9a0425ca3c6c87c61b526e87b7474398c3 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 22:29:52 +0200 Subject: [PATCH 11/55] ci: pipeline on branches only manual --- .gitlab-ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1993e07..918cf04 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,6 +25,8 @@ build: paths: - dist/*.whl rules: + - if: CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ + when: manual - when: always pylint: @@ -35,6 +37,8 @@ pylint: - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: + - if: CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ + when: manual - when: on_success integration-test: @@ -75,6 +79,8 @@ integration-test: coverage_format: cobertura path: coverage.xml rules: + - if: CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ + when: manual - when: on_success release: -- GitLab From 9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 22:33:47 +0200 Subject: [PATCH 12/55] ci: pipeline on branches only manual --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 918cf04..2873137 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,7 +25,7 @@ build: paths: - dist/*.whl rules: - - if: CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ + - if: $CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ when: manual - when: always @@ -37,7 +37,7 @@ pylint: - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: - - if: CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ + - if: $CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ when: manual - when: on_success @@ -79,7 +79,7 @@ integration-test: coverage_format: cobertura path: coverage.xml rules: - - if: CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ + - if: $CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ when: manual - when: on_success -- GitLab From 166172141e63f3ef22c576196aacaf7de5bea227 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 22:38:17 +0200 Subject: [PATCH 13/55] ci: remove build stage --- .gitlab-ci.yml | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2873137..98e9306 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,30 +9,14 @@ cache: - venv/ stages: - - build - test - release -build: - stage: build - script: - - ci/virtual-env.sh - - source venv/bin/activate - - ci/build-install.sh - - pip -V - - pip show -f vja - artifacts: - paths: - - dist/*.whl - rules: - - if: $CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ - when: manual - - when: always - pylint: stage: test allow_failure: true script: + - ci/virtual-env.sh - source venv/bin/activate - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py @@ -58,7 +42,7 @@ integration-test: - pip3 install coverage - python3 --version - - pip install dist/*.whl + - ci/build-install.sh - pip show vja - which vja -- GitLab From 49d2fe2d4261fa993aa06365fd004876d8fff055 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 22:49:24 +0200 Subject: [PATCH 14/55] ci: remove build stage --- .gitlab-ci.yml | 7 ++++--- ci/build-install.sh | 7 ------- ci/virtual-env.sh | 7 ------- 3 files changed, 4 insertions(+), 17 deletions(-) delete mode 100755 ci/build-install.sh delete mode 100755 ci/virtual-env.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 98e9306..d905e9a 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,8 +16,6 @@ pylint: stage: test allow_failure: true script: - - ci/virtual-env.sh - - source venv/bin/activate - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: @@ -42,7 +40,10 @@ integration-test: - pip3 install coverage - python3 --version - - ci/build-install.sh + - pip install -r requirements_dev.txt + - python3 setup.py sdist bdist_wheel + - pip install dist/*.whl; + - pip show vja - which vja diff --git a/ci/build-install.sh b/ci/build-install.sh deleted file mode 100755 index ddb6dbe..0000000 --- a/ci/build-install.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -set -euo pipefail - -pip install -r requirements_dev.txt -pip uninstall -y vja -python setup.py sdist bdist_wheel -pip install dist/*.whl diff --git a/ci/virtual-env.sh b/ci/virtual-env.sh deleted file mode 100755 index 27d4934..0000000 --- a/ci/virtual-env.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -set -euo pipefail - -python --version -pip install virtualenv -virtualenv venv - -- GitLab From e27df75b220380148aab79e75af0e5194041d381 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 22:53:07 +0200 Subject: [PATCH 15/55] ci: remove build stage --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d905e9a..0bac455 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,7 +6,6 @@ variables: cache: paths: - .cache/pip - - venv/ stages: - test @@ -16,6 +15,7 @@ pylint: stage: test allow_failure: true script: + - pip install -r requirements_dev.txt - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: @@ -57,7 +57,6 @@ integration-test: - coverage xml --omit='*test*' - docker-compose -f tests/docker-compose.yml down coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' - cache: {} artifacts: reports: coverage_report: -- GitLab From e4858e363aed6369ef29ef0fe3ed56115083a11b Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 22:58:31 +0200 Subject: [PATCH 16/55] ci: remove build stage --- .gitlab-ci.yml | 4 ++-- vja/model.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0bac455..0555f68 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,6 +16,7 @@ pylint: allow_failure: true script: - pip install -r requirements_dev.txt + - python setup.py sdist bdist_wheel - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: @@ -41,7 +42,7 @@ integration-test: - python3 --version - pip install -r requirements_dev.txt - - python3 setup.py sdist bdist_wheel + - pip uninstall -y vja; python3 setup.py sdist bdist_wheel - pip install dist/*.whl; - pip show vja @@ -80,7 +81,6 @@ release: script: - python --version - semantic-release - cache: {} rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: on_success diff --git a/vja/model.py b/vja/model.py index 5839a8b..0a8dcc3 100755 --- a/vja/model.py +++ b/vja/model.py @@ -156,7 +156,6 @@ class TaskReminder: return [TaskReminder.from_json(x) for x in json_array or []] - @dataclass @custom_output @data_dict -- GitLab From 8e4f36cee4ebaff4fcf3c703e6e1b265d955d302 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:01:24 +0200 Subject: [PATCH 17/55] ci: remove build stage --- .gitlab-ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0555f68..96b8a5c 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ pylint: allow_failure: true script: - pip install -r requirements_dev.txt - - python setup.py sdist bdist_wheel + - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl; - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: @@ -42,9 +42,7 @@ integration-test: - python3 --version - pip install -r requirements_dev.txt - - pip uninstall -y vja; python3 setup.py sdist bdist_wheel - - pip install dist/*.whl; - + - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl; - pip show vja - which vja -- GitLab From 9b03ba180ceb1a9d8125a4713a5e2799777e4e36 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:15:41 +0200 Subject: [PATCH 18/55] ci: install coverage from requirements_dev.txt --- .gitlab-ci.yml | 3 --- requirements_dev.txt | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 96b8a5c..ed7a6a6 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -36,9 +36,6 @@ integration-test: script: - docker --version - apk add --no-cache bash curl python3-dev py3-pip docker-compose - - pip3 install wheel - - pip3 install pytest - - pip3 install coverage - python3 --version - pip install -r requirements_dev.txt diff --git a/requirements_dev.txt b/requirements_dev.txt index 07d7643..c45e594 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -4,3 +4,4 @@ twine==4.0.2 pylint==2.17.2 flake8==6.0.0 pytest==7.3.1 +coverage==7.2.2 -- GitLab From a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:22:37 +0200 Subject: [PATCH 19/55] ci: remove redundant apk packages --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ed7a6a6..321eb45 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ pylint: allow_failure: true script: - pip install -r requirements_dev.txt - - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl; + - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: @@ -35,11 +35,11 @@ integration-test: DOCKER_TLS_CERTDIR: "" script: - docker --version - - apk add --no-cache bash curl python3-dev py3-pip docker-compose + - apk add --no-cache python3 py3-pip docker-compose - python3 --version - pip install -r requirements_dev.txt - - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl; + - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl - pip show vja - which vja -- GitLab From bf6c0eae179929555ecba1315d19683f052a046e Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:31:53 +0200 Subject: [PATCH 20/55] ci: remove redundant apk packages --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 321eb45..86b2218 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,7 +27,7 @@ pylint: integration-test: stage: test image: - name: docker:stable + name: docker:20.10.23 services: - name: docker:dind variables: @@ -35,7 +35,7 @@ integration-test: DOCKER_TLS_CERTDIR: "" script: - docker --version - - apk add --no-cache python3 py3-pip docker-compose + - apk add --no-cache bash python3 py3-pip docker-compose - python3 --version - pip install -r requirements_dev.txt -- GitLab From 017cf444633a7f800c6f8d1960ea84e093a79c65 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:52:48 +0200 Subject: [PATCH 21/55] ci: cleanup gitlab-ci --- .gitlab-ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86b2218..8b1a8f7 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,8 +1,5 @@ -image: python:3.11-slim - variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip" - cache: paths: - .cache/pip @@ -13,6 +10,7 @@ stages: pylint: stage: test + image: python:3.11-slim allow_failure: true script: - pip install -r requirements_dev.txt @@ -27,7 +25,7 @@ pylint: integration-test: stage: test image: - name: docker:20.10.23 + name: docker:23.0-cli services: - name: docker:dind variables: -- GitLab From 0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:56:53 +0200 Subject: [PATCH 22/55] ci: cleanup gitlab-ci --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8b1a8f7..1164373 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,7 +33,7 @@ integration-test: DOCKER_TLS_CERTDIR: "" script: - docker --version - - apk add --no-cache bash python3 py3-pip docker-compose + - apk add --no-cache bash python3 py3-pip - python3 --version - pip install -r requirements_dev.txt @@ -41,7 +41,7 @@ integration-test: - pip show vja - which vja - - docker-compose -f tests/docker-compose.yml up -d api + - docker compose -f tests/docker-compose.yml up -d api - curl --retry 5 --retry-all-errors --retry-delay 1 "http://docker:3456/api/v1/info" - export VJA_CONFIGDIR=tests/.vjatest_dind -- GitLab From cab2530d7bdfe9261acf9ae4f30d304e8279b6aa Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 31 Mar 2023 23:57:11 +0200 Subject: [PATCH 23/55] ci: cleanup gitlab-ci --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1164373..6b0f530 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,7 +49,7 @@ integration-test: - coverage run --omit='*test*' -m pytest - coverage report --omit='*test*' - coverage xml --omit='*test*' - - docker-compose -f tests/docker-compose.yml down + - docker compose -f tests/docker-compose.yml down coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/' artifacts: reports: -- GitLab From cb6f743f14ab85afd8059c8c9f4baa68e492b215 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 00:02:29 +0200 Subject: [PATCH 24/55] ci: cleanup gitlab-ci --- tests/docker-compose.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 74ab6b5..73621d9 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -13,10 +13,10 @@ services: /app/vikunja/vikunja user create -u test -p test -e test@test.test exec /app/vikunja/vikunja " -# frontend: -# image: vikunja/frontend:0.20.5 -# ports: -# - "8080:80" -# environment: -# VIKUNJA_API_URL: http://localhost:3456/api/v1 + frontend: + image: vikunja/frontend:0.20.5 + ports: + - "8080:80" + environment: + VIKUNJA_API_URL: http://localhost:3456/api/v1 -- GitLab From 727c2823f2adab62e4e91835ed39219f2b274fe2 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 10:13:36 +0200 Subject: [PATCH 25/55] test: capture click output --- tests/conftest.py | 10 +++++++++- tests/test_command.py | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 12f5b7b..e30cddf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,4 @@ +import logging import os import subprocess import sys @@ -7,16 +8,23 @@ from click.testing import CliRunner from vja.cli import cli +logging.basicConfig(stream=sys.stdout, level=logging.DEBUG) + @pytest.fixture(name='runner', scope='session') def setup_runner(): return CliRunner() -def invoke(runner, command, return_code=0, user_input=None, catch_exceptions=True): +def invoke(runner, command, return_code=0, user_input=None, catch_exceptions=False): if isinstance(command, str): command = command.split() res = runner.invoke(cli, command, input=user_input, catch_exceptions=catch_exceptions) + sys.stdout.write(res.output) + if res.stderr_bytes: + sys.stdout.write(res.stderr_bytes) + if res.exception: + logging.warning(res.exception) assert res.exit_code == return_code, res return res diff --git a/tests/test_command.py b/tests/test_command.py index be39f0c..0065b11 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -26,7 +26,7 @@ class TestAddTask: assert after['tasklist']['title'] == 'test-list' def test_duplicate_task_title_rejected(self, runner): - invoke(runner, 'add title of new task', 1) + invoke(runner, 'add title of new task', 1, catch_exceptions=True) def test_default_reminder_uses_due(self, runner): res = invoke(runner, 'add title of new task --force --list=test-list --due=today --reminder') -- GitLab From c8a387244ee86728241970d86e8b59d259a90c40 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 10:43:58 +0200 Subject: [PATCH 26/55] test: cleanup test setup --- tests/conftest.py | 47 +++++++++++++++-------------------------------- 1 file changed, 15 insertions(+), 32 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index e30cddf..1794a1f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -30,36 +30,23 @@ def invoke(runner, command, return_code=0, user_input=None, catch_exceptions=Fal def _login_as_test_user(): - result = subprocess.run('vja logout'.split(), check=False) - if result.returncode: - print(result.stdout) - print(result.stderr) - return result.returncode - - result = subprocess.run('vja --username=test --password=test user show'.split(), check=False) - if result.returncode: - print(result.stdout) - print(result.stderr) - return result.returncode + run_vja('vja logout') + run_vja('vja --username=test --password=test user show') def _create_list_and_task(): - result = subprocess.run('vja list add test-list'.split(), check=False) - if result.returncode: - print(result.stdout) - print(result.stderr) - return result.returncode - result = subprocess.run('vja add At least one task --force-create ' - '--priority=5 --due-date=today --tag=my_tag --favorite=True'.split(), check=False) - if result.returncode: - print(result.stdout) - print(result.stderr) - return result.returncode - result = subprocess.run('vja add A task without a label --force-create'.split(), check=False) + run_vja('vja list add test-list') + run_vja('vja add At least one task --force-create --priority=5 --due-date=today --tag=my_tag --favorite=True') + run_vja('vja add A task without a label --force-create') + + +def run_vja(command): + result = subprocess.run(command.split(), capture_output=True, check=False) if result.returncode: - print(result.stdout) - print(result.stderr) - return result.returncode + print('!!! Non-zero result from command: ' + command) + sys.stdout.write(result.stdout.decode('utf-8')) + sys.stdout.write(result.stderr.decode('utf-8')) + sys.exit(1) def pytest_configure(): @@ -67,10 +54,6 @@ def pytest_configure(): print('!!! Precondition not met. You must set VJA_CONFIGDIR in environment variables !!!') sys.exit(1) - if _login_as_test_user() > 0: - print('!!! Precondition not met. Cannot connect to Vikunja with user test/test') - sys.exit(1) + _login_as_test_user() - if _create_list_and_task() > 0: - print('!!! Unable to create default list') - sys.exit(1) + _create_list_and_task() -- GitLab From 7b8c922acaf726060c9de5ad574da585bc8e2e9a Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 14:47:31 +0200 Subject: [PATCH 27/55] fix: do not unset reminder if missing in vja edit --- tests/conftest.py | 2 +- tests/docker-compose.yml | 2 +- vja/service_command.py | 19 ++++++++++--------- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1794a1f..e424399 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -43,7 +43,7 @@ def _create_list_and_task(): def run_vja(command): result = subprocess.run(command.split(), capture_output=True, check=False) if result.returncode: - print('!!! Non-zero result from command: ' + command) + print(f'!!! Non-zero result ({result.returncode}) from command {command}') sys.stdout.write(result.stdout.decode('utf-8')) sys.stdout.write(result.stderr.decode('utf-8')) sys.exit(1) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 73621d9..544e009 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -14,7 +14,7 @@ services: exec /app/vikunja/vikunja " frontend: - image: vikunja/frontend:0.20.5 + image: vikunja/frontend:unstable ports: - "8080:80" environment: diff --git a/vja/service_command.py b/vja/service_command.py index 4229517..5514933 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -134,16 +134,17 @@ class CommandService: # replace the first existing reminder with our entry new_reminder = args.pop('reminder')[0] if reminder_arg else None - old_reminders = task_remote['reminders'] - if old_reminders and len(old_reminders) > 0: - if new_reminder: - old_reminders[0] = new_reminder # overwrite first remote reminder + if new_reminder is not None: + old_reminders = task_remote['reminders'] + if old_reminders and len(old_reminders) > 0: + if new_reminder: + old_reminders[0] = new_reminder # overwrite first remote reminder + else: + old_reminders.pop(0) # remove first remote reminder else: - old_reminders.pop(0) # remove first remote reminder - else: - if new_reminder: - old_reminders = [new_reminder] # create single reminder - args.update({'reminder': old_reminders}) + if new_reminder: + old_reminders = [new_reminder] # create single reminder + args.update({'reminder': old_reminders}) @staticmethod def _parse_reminder_arg(reminder_arg, args): -- GitLab From c57f4bcd40fcbad44b1d364884864bf764b012e9 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 19:13:38 +0200 Subject: [PATCH 28/55] ci: automate beta releases --- .gitlab-ci.yml | 3 +++ .releaserc.yml | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b0f530..b9c088e 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,3 +77,6 @@ release: rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: on_success + - if: $CI_COMMIT_BRANCH == "beta" + when: manual + diff --git a/.releaserc.yml b/.releaserc.yml index 6d05e0a..d72169d 100644 --- a/.releaserc.yml +++ b/.releaserc.yml @@ -1,9 +1,9 @@ -# spec: https://semantic-release.gitbook.io/semantic-release/usage/configuration tagFormat: "${version}" -branches: [ main, next ] +branches: + - main + - { name: beta, prerelease: true } + plugins: - # Determine the type of release by analyzing commits. - # ie: Major, Minor or Patch - - "@semantic-release/commit-analyzer" - preset: conventionalcommits releaseRules: -- GitLab From f2dc40ae6d731b96946c999f3f9d639b38f2b601 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 19:21:45 +0200 Subject: [PATCH 29/55] ci: automate beta releases --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b9c088e..4fd5147 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,6 +13,7 @@ pylint: image: python:3.11-slim allow_failure: true script: + - echo $CI_COMMIT_BRANCH - pip install -r requirements_dev.txt - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl - flake8 --max-line-length=120 vja/*.py || true -- GitLab From a3fed80753d817a8026d1ac8eb65291576c5a10f Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 19:23:49 +0200 Subject: [PATCH 30/55] ci: automate beta releases --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4fd5147..20adf77 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -13,7 +13,6 @@ pylint: image: python:3.11-slim allow_failure: true script: - - echo $CI_COMMIT_BRANCH - pip install -r requirements_dev.txt - pip uninstall -y vja && python3 setup.py sdist bdist_wheel && pip install dist/*.whl - flake8 --max-line-length=120 vja/*.py || true @@ -78,6 +77,6 @@ release: rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: on_success - - if: $CI_COMMIT_BRANCH == "beta" + - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: manual -- GitLab From a32525446577421f95b51cb578390d2c72d114c3 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 1 Apr 2023 19:44:31 +0200 Subject: [PATCH 31/55] ci: automate beta releases --- .gitlab-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 20adf77..3b7c502 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,6 +18,8 @@ pylint: - flake8 --max-line-length=120 vja/*.py || true - pylint -d C0103,C0114,C0115,C0116,C0301 --fail-under=9 vja/*.py rules: + - if: $CI_COMMIT_BRANCH == "beta" + when: on_success - if: $CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ when: manual - when: on_success @@ -57,6 +59,8 @@ integration-test: coverage_format: cobertura path: coverage.xml rules: + - if: $CI_COMMIT_BRANCH == "beta" + when: on_success - if: $CI_COMMIT_BRANCH && $CI_COMMIT_REF_SLUG !~ /renovate.*/ when: manual - when: on_success @@ -77,6 +81,6 @@ release: rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: on_success - - if: $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH == "beta" when: manual -- GitLab From 9d27ea2639c0ffec7582199f004508006479385e Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 1 Apr 2023 18:55:56 +0000 Subject: [PATCH 32/55] chore(release): Release 2.0.0-beta.1 update changelog [skip ci] * **api:** remove reminder_dates * **api:** New projects api (only backend side) * Preliminary support for new reminder array * **api:** New projects api (only backend side) ([157aeb4](https://gitlab.com/ce72/vja/commit/157aeb483fa2b5d3b1d733f7682c97c8e449aebc)) * **api:** remove reminder_dates ([76ffb20](https://gitlab.com/ce72/vja/commit/76ffb2007cf77d87e41b8cdb8bf16a0f9d4edf26)) * defer reminder ([c493b07](https://gitlab.com/ce72/vja/commit/c493b07266affc2f6976a5682b1b33170c90e51b)) * Preliminary support for new reminder array ([eb7e819](https://gitlab.com/ce72/vja/commit/eb7e819b08b897eeb55e0a18320a03a11442ce91)) * **reminders:** Set relative reminders like "1h before due" ([f05438d](https://gitlab.com/ce72/vja/commit/f05438d9f8c61ee04cb5432b2e1e0d0a56ff2175)) * Support for new reminder array (read) ([c323c76](https://gitlab.com/ce72/vja/commit/c323c76fcb52541a00e35d1e5c31a668eb061405)) * do not unset reminder if missing in vja edit ([a3b81b0](https://gitlab.com/ce72/vja/commit/a3b81b0bae08841fd92e204d5557cc1ad46a59b3)) * sharpen test ([4c59738](https://gitlab.com/ce72/vja/commit/4c59738a19bb4dabd1b871d54ba40f8833b2fe10)) * Remove redundant test ([2901848](https://gitlab.com/ce72/vja/commit/29018480b6a11c2ec3495ce6e44c4955fe6b13ec)) * Add table of contents to Features.md ([3a87061](https://gitlab.com/ce72/vja/commit/3a87061f39b2bf4d2a1194197f5cfef3c8d7d46e)) * automate beta releases ([8f19e48](https://gitlab.com/ce72/vja/commit/8f19e48db1312db3e6d27716a692b95805ef82d1)) * automate beta releases ([1c74fda](https://gitlab.com/ce72/vja/commit/1c74fdab9e9b02fc116a1532b081b562e9dbf832)) * automate beta releases ([8f7bb4f](https://gitlab.com/ce72/vja/commit/8f7bb4f9802ec6e199d5f7dd60790341550a1785)) * automate beta releases ([68bd7d8](https://gitlab.com/ce72/vja/commit/68bd7d8ee3b3579c3f48b3b8d13d2780f5194641)) * capture click output ([9aafa2c](https://gitlab.com/ce72/vja/commit/9aafa2c426757b2068a1199410db58899356eacd)) * cleanup gitlab-ci ([450d13f](https://gitlab.com/ce72/vja/commit/450d13fe43987c3cf33c72bfa2303e452ee7be8b)) * cleanup gitlab-ci ([543a479](https://gitlab.com/ce72/vja/commit/543a47928a9539982a91507ece4e9d3605bb2dbb)) * cleanup gitlab-ci ([7145451](https://gitlab.com/ce72/vja/commit/714545181a76b15c4341df3a4ff6830416ddf897)) * cleanup gitlab-ci ([9584cac](https://gitlab.com/ce72/vja/commit/9584cac6e18e81480231b34fabd46990249a2760)) * cleanup test setup ([5e5040a](https://gitlab.com/ce72/vja/commit/5e5040a3254b8cc5dc75f0391352e0e1358fdeaa)) * install coverage from requirements_dev.txt ([eab4b0f](https://gitlab.com/ce72/vja/commit/eab4b0f4ef879c64859c9796f2562b09eaa53320)) * pipeline on branches only manual ([43fa7df](https://gitlab.com/ce72/vja/commit/43fa7df6ec8fe69eb8d9d27589b65b9541b0b71a)) * pipeline on branches only manual ([8689f5e](https://gitlab.com/ce72/vja/commit/8689f5e0a36a536187a9df97dd38a2a0ece9ed01)) * remove build stage ([3294b83](https://gitlab.com/ce72/vja/commit/3294b83e1b75b2b6826333104d91e71ee1b8d478)) * remove build stage ([8bca866](https://gitlab.com/ce72/vja/commit/8bca866c60f3ed2cf62eeb87cd10dad06f9563e6)) * remove build stage ([4638743](https://gitlab.com/ce72/vja/commit/46387430fe4c92a02b818e200672c86ed4190e1a)) * remove build stage ([5b32e53](https://gitlab.com/ce72/vja/commit/5b32e53277c3ee95464eb1d60f2c270dccb5bf4b)) * remove build stage ([7dd6dcb](https://gitlab.com/ce72/vja/commit/7dd6dcbf9f8c373a9d8b33b8c17d29c559cc1075)) * remove redundant apk packages ([22a3f48](https://gitlab.com/ce72/vja/commit/22a3f48391bc8434fcb208d31e4db50f701b8c68)) * remove redundant apk packages ([efb7016](https://gitlab.com/ce72/vja/commit/efb701685d11bad90eb844ac8636117225ab2f7c)) * sleep 1s after starting api ([649a806](https://gitlab.com/ce72/vja/commit/649a8063a39f76f91196c0f6f8261f5033f95d52)) * update semantic-release configuration ([572f519](https://gitlab.com/ce72/vja/commit/572f519a10bc97e9badb017f90b5e723eecc8e42)) --- CHANGELOG.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++++--- setup.cfg | 2 +- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c625d8..3066b93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,62 @@ -## [1.5.1](https://gitlab.com/ce72/vja/compare/1.5.0...1.5.1) (2023-04-27) +## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.0...2.0.0-beta.1) (2023-04-01) + + +### ⚠ BREAKING CHANGES + +* **api:** remove reminder_dates +* **api:** New projects api (only backend side) +* Preliminary support for new reminder array + +### Features + +* **api:** New projects api (only backend side) ([157aeb4](https://gitlab.com/ce72/vja/commit/157aeb483fa2b5d3b1d733f7682c97c8e449aebc)) +* **api:** remove reminder_dates ([76ffb20](https://gitlab.com/ce72/vja/commit/76ffb2007cf77d87e41b8cdb8bf16a0f9d4edf26)) +* defer reminder ([c493b07](https://gitlab.com/ce72/vja/commit/c493b07266affc2f6976a5682b1b33170c90e51b)) +* Preliminary support for new reminder array ([eb7e819](https://gitlab.com/ce72/vja/commit/eb7e819b08b897eeb55e0a18320a03a11442ce91)) +* **reminders:** Set relative reminders like "1h before due" ([f05438d](https://gitlab.com/ce72/vja/commit/f05438d9f8c61ee04cb5432b2e1e0d0a56ff2175)) +* Support for new reminder array (read) ([c323c76](https://gitlab.com/ce72/vja/commit/c323c76fcb52541a00e35d1e5c31a668eb061405)) + + +### Bug Fixes + +* do not unset reminder if missing in vja edit ([a3b81b0](https://gitlab.com/ce72/vja/commit/a3b81b0bae08841fd92e204d5557cc1ad46a59b3)) +* sharpen test ([4c59738](https://gitlab.com/ce72/vja/commit/4c59738a19bb4dabd1b871d54ba40f8833b2fe10)) ### Misc -* **deps:** update all dependencies ([546d995](https://gitlab.com/ce72/vja/commit/546d9953f3fba1289760b9d5b6bcd6f6ac4e2c99)) +* Remove redundant test ([2901848](https://gitlab.com/ce72/vja/commit/29018480b6a11c2ec3495ce6e44c4955fe6b13ec)) + + +### Documentation + +* Add table of contents to Features.md ([3a87061](https://gitlab.com/ce72/vja/commit/3a87061f39b2bf4d2a1194197f5cfef3c8d7d46e)) ### Automation -* wait for running api container ([fca176d](https://gitlab.com/ce72/vja/commit/fca176dfb72c8b3e7ef07a048093691c5c74f8c3)) +* automate beta releases ([8f19e48](https://gitlab.com/ce72/vja/commit/8f19e48db1312db3e6d27716a692b95805ef82d1)) +* automate beta releases ([1c74fda](https://gitlab.com/ce72/vja/commit/1c74fdab9e9b02fc116a1532b081b562e9dbf832)) +* automate beta releases ([8f7bb4f](https://gitlab.com/ce72/vja/commit/8f7bb4f9802ec6e199d5f7dd60790341550a1785)) +* automate beta releases ([68bd7d8](https://gitlab.com/ce72/vja/commit/68bd7d8ee3b3579c3f48b3b8d13d2780f5194641)) +* capture click output ([9aafa2c](https://gitlab.com/ce72/vja/commit/9aafa2c426757b2068a1199410db58899356eacd)) +* cleanup gitlab-ci ([450d13f](https://gitlab.com/ce72/vja/commit/450d13fe43987c3cf33c72bfa2303e452ee7be8b)) +* cleanup gitlab-ci ([543a479](https://gitlab.com/ce72/vja/commit/543a47928a9539982a91507ece4e9d3605bb2dbb)) +* cleanup gitlab-ci ([7145451](https://gitlab.com/ce72/vja/commit/714545181a76b15c4341df3a4ff6830416ddf897)) +* cleanup gitlab-ci ([9584cac](https://gitlab.com/ce72/vja/commit/9584cac6e18e81480231b34fabd46990249a2760)) +* cleanup test setup ([5e5040a](https://gitlab.com/ce72/vja/commit/5e5040a3254b8cc5dc75f0391352e0e1358fdeaa)) +* install coverage from requirements_dev.txt ([eab4b0f](https://gitlab.com/ce72/vja/commit/eab4b0f4ef879c64859c9796f2562b09eaa53320)) +* pipeline on branches only manual ([43fa7df](https://gitlab.com/ce72/vja/commit/43fa7df6ec8fe69eb8d9d27589b65b9541b0b71a)) +* pipeline on branches only manual ([8689f5e](https://gitlab.com/ce72/vja/commit/8689f5e0a36a536187a9df97dd38a2a0ece9ed01)) +* remove build stage ([3294b83](https://gitlab.com/ce72/vja/commit/3294b83e1b75b2b6826333104d91e71ee1b8d478)) +* remove build stage ([8bca866](https://gitlab.com/ce72/vja/commit/8bca866c60f3ed2cf62eeb87cd10dad06f9563e6)) +* remove build stage ([4638743](https://gitlab.com/ce72/vja/commit/46387430fe4c92a02b818e200672c86ed4190e1a)) +* remove build stage ([5b32e53](https://gitlab.com/ce72/vja/commit/5b32e53277c3ee95464eb1d60f2c270dccb5bf4b)) +* remove build stage ([7dd6dcb](https://gitlab.com/ce72/vja/commit/7dd6dcbf9f8c373a9d8b33b8c17d29c559cc1075)) +* remove redundant apk packages ([22a3f48](https://gitlab.com/ce72/vja/commit/22a3f48391bc8434fcb208d31e4db50f701b8c68)) +* remove redundant apk packages ([efb7016](https://gitlab.com/ce72/vja/commit/efb701685d11bad90eb844ac8636117225ab2f7c)) +* sleep 1s after starting api ([649a806](https://gitlab.com/ce72/vja/commit/649a8063a39f76f91196c0f6f8261f5033f95d52)) +* update semantic-release configuration ([572f519](https://gitlab.com/ce72/vja/commit/572f519a10bc97e9badb017f90b5e723eecc8e42)) ## [1.5.0](https://gitlab.com/ce72/vja/compare/1.4.1...1.5.0) (2023-03-31) diff --git a/setup.cfg b/setup.cfg index 5643264..c8a9fe3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 1.5.1 +version = 2.0.0b1 -- GitLab From 54b0b0a46cfaaa20236fe79580a9a28909056d7c Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sun, 2 Apr 2023 21:49:06 +0200 Subject: [PATCH 33/55] feat: rename lists to project within vja --- .vjacli/vja.rc | 6 +-- Features.md | 39 +++++++--------- Readme.md | 22 ++++----- tests/.vjatest/vja.rc | 6 +-- tests/.vjatest_dind/vja.rc | 6 +-- tests/conftest.py | 6 +-- tests/run.sh | 17 ++++--- tests/test_command.py | 36 +++++++-------- tests/test_query.py | 64 ++++++++------------------ vja/apiclient.py | 16 +++---- vja/cli.py | 93 +++++++++++++++----------------------- vja/config.py | 4 +- vja/filter.py | 12 ++--- vja/list_service.py | 62 ++++++++++++------------- vja/model.py | 12 ++--- vja/output.py | 14 +++--- vja/service_command.py | 24 +++++----- vja/service_query.py | 16 +++---- vja/task_service.py | 4 +- vja/urgency.py | 22 ++++----- 20 files changed, 213 insertions(+), 268 deletions(-) diff --git a/.vjacli/vja.rc b/.vjacli/vja.rc index ce3994a..3e8e3d5 100755 --- a/.vjacli/vja.rc +++ b/.vjacli/vja.rc @@ -8,7 +8,7 @@ api_url=https://try.vikunja.io/api/v1 # Be careful: Any code which is entered here gets executed at runtime (python eval()). # Do not use --custom-format if you feel uncomfortable with that. -tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} +tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.project.title:20.20} {x.label_titles:20.20} {x.urgency:3} tasklist_short={x.id:5} {x.title:50.50} ids_only={x.id} @@ -16,9 +16,9 @@ ids_only={x.id} due_date_weight=1.0 priority_weight=2.0 favorite_weight=1.0 -list_weight=1.0 +project_weight=1.0 label_weight=1.0 [urgency_keywords] -list_keywords=next, test-list +project_keywords=next, test-project label_keywords=next,my_tag diff --git a/Features.md b/Features.md index 6e559c4..5caef68 100644 --- a/Features.md +++ b/Features.md @@ -1,6 +1,7 @@ # Features + * [Features](#features) * [Create Task](#create-task) * [Clone](#clone) @@ -15,18 +16,18 @@ * [Reminders](#reminders) * [Batch editing](#batch-editing) * [Open Vikunja in browser](#open-vikunja-in-browser) - * [Manage lists, namespaces, labels, buckets](#manage-lists-namespaces-labels-buckets) - * [Manage namespaces](#manage-namespaces) - * [Manage lists (projects)](#manage-lists-projects) + * [Manage projects, labels, buckets](#manage-projects-labels-buckets) + * [Manage project)](#manage-projects) * [Manage kanban buckets](#manage-kanban-buckets) * [Manage labels](#manage-labels) * [Output format](#output-format) * [Terminate session](#terminate-session) + ## Create Task -`vja add ` allows to quickly add a new task to the default list. Several options exist to provide more +`vja add ` allows to quickly add a new task to the default project. Several options exist to provide more context: ```shell @@ -73,14 +74,14 @@ vja ls --json ### Urgency By default, tasks are sorted (amongst others) by their urgency, which is displayed in the last column. Urgency is -calculated by regarding due_date, priority and is_favorite of the task, as well as the occurence of keywords in the list -title or the label titles. The weights of each factor and the keywords can be specified in the configuration file ~ -/.vjacli/vja.rc. See Configuration section in [Readme.md](Readme.md). See [.vjacli/vja.rc](.vjacli/vja.rc) for an +calculated by regarding due_date, priority and is_favorite of the task, as well as the occurence of keywords in the +project title or the label titles. The weights of each factor and the keywords can be specified in the configuration +file ~/.vjacli/vja.rc. See Configuration section in [Readme.md](Readme.md). See [.vjacli/vja.rc](.vjacli/vja.rc) for an example. ### Filter -The displayed tasks may be filtered by several arguments like list id or title, namespace and label +The displayed tasks may be filtered by several arguments like project or title, namespace and label ```shell vja ls --label=@work @@ -117,7 +118,7 @@ vja ls --sort=-id # reverse Sort criteria can be combined. The default sort order of vja is the same as ```shell -vja ls --sort='done, -urgency, due_date, -priority, tasklist.title, title' +vja ls --sort='done, -urgency, due_date, -priority, project.title, title' ``` See `vja ls --help` for more. @@ -239,36 +240,30 @@ Open task 42 in browser vja open 42 ``` -## Manage lists, namespaces, labels, buckets - -### Manage namespaces - -```shell -vja namespace ls -``` +## Manage projects, labels, buckets -### Manage lists (projects) +### Manage projects ```shell -vja list add New List +vja project add New Project ``` ```shell -vja list add -n 2 Create list in namespace with index 2 +vja project add -n 2 Create project in namespace with index 2 ``` ```shell -vja list ls +vja project ls ``` ```shell -vja list show 1 +vja project show 1 ``` ### Manage kanban buckets ```shell -vja bucket ls --list-id=1 +vja bucket ls --project-id=1 ``` ### Manage labels diff --git a/Readme.md b/Readme.md index f9c08b2..eae61a9 100755 --- a/Readme.md +++ b/Readme.md @@ -49,17 +49,17 @@ Before using vja you must provide a configuration. #### Optional options -| Section | Option | Description | -|------------------------|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [output] | arbitrary_name | Python format strings which may be referenced on the command line by `--custom-format=`. May contain any valid python f-Format string.
Take care: The format string may provide code which will be executed at runtime! Do not use `--custom-format` if you are unsure.
Default: missing | -| [output] | another_format | Multiple formats can be defined for reference. (see above) | -| [urgency_coefficients] | due_date_weight | Weight of dueness in urgency score. Default: 1.0 | -| [urgency_coefficients] | priority_weight | Weight of priority in urgency score. Default: 1.0 | -| [urgency_coefficients] | favorite_weight | Weight of is_favorite in urgency score. Default: 1.0 | -| [urgency_coefficients] | list_weight | Weight of keyword occurrence in list title in urgency score. Default: 1.0 | -| [urgency_coefficients] | label_weight | Weight of keyword occurrence in label title in urgency score. Default: 1.0 | -| [urgency_keywords] | list_keywords | Tasks in lists with a title containing these keywords are considered more urgent. Default: None | -| [urgency_keywords] | label_keywords | Tasks labeled with one of these keywords are considered more urgent. Default: None | +| Section | Option | Description | +|------------------------|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [output] | arbitrary_name | Python format strings which may be referenced on the command line by `--custom-format=`. May contain any valid python f-Format string.
Take care: The format string may provide code which will be executed at runtime! Do not use `--custom-format` if you are unsure.
Default: missing | +| [output] | another_format | Multiple formats can be defined for reference. (see above) | +| [urgency_coefficients] | due_date_weight | Weight of dueness in urgency score. Default: 1.0 | +| [urgency_coefficients] | priority_weight | Weight of priority in urgency score. Default: 1.0 | +| [urgency_coefficients] | favorite_weight | Weight of is_favorite in urgency score. Default: 1.0 | +| [urgency_coefficients] | project_weight | Weight of keyword occurrence in project title in urgency score. Default: 1.0 | +| [urgency_coefficients] | label_weight | Weight of keyword occurrence in label title in urgency score. Default: 1.0 | +| [urgency_keywords] | lisproject_keywords | Tasks in projects with a title containing these keywords are considered more urgent. Default: None | +| [urgency_keywords] | label_keywords | Tasks labeled with one of these keywords are considered more urgent. Default: None | ## Usage diff --git a/tests/.vjatest/vja.rc b/tests/.vjatest/vja.rc index 5aa2fc1..ebcaf22 100644 --- a/tests/.vjatest/vja.rc +++ b/tests/.vjatest/vja.rc @@ -8,7 +8,7 @@ api_url=http://localhost:3456/api/v1 # Be careful: Any code which is entered here gets executed at runtime (python eval()). # Do not use --custom-format if you feel uncomfortable with that. -tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} +tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.project.title:20.20} {x.label_titles:20.20} {x.urgency:3} tasklist_short={x.id:5} {x.title:50.50} ids_only={x.id} @@ -16,9 +16,9 @@ ids_only={x.id} due_date_weight=1.0 priority_weight=2.0 favorite_weight=1.0 -list_weight=1.0 +project_weight=1.0 label_weight=1.0 [urgency_keywords] -list_keywords=next, test-list +project_keywords=next, test-project label_keywords=next,my_tag diff --git a/tests/.vjatest_dind/vja.rc b/tests/.vjatest_dind/vja.rc index 428f7dc..f8b7788 100644 --- a/tests/.vjatest_dind/vja.rc +++ b/tests/.vjatest_dind/vja.rc @@ -8,7 +8,7 @@ api_url=http://docker:3456/api/v1 # Be careful: Any code which is entered here gets executed at runtime (python eval()). # Do not use --custom-format if you feel uncomfortable with that. -tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.tasklist.title:20.20} {x.label_titles:20.20} {x.urgency:3} +tasklist_long={x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} {x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} {"R" if x.reminders else " "} {x.project.title:20.20} {x.label_titles:20.20} {x.urgency:3} tasklist_short={x.id:5} {x.title:50.50} ids_only={x.id} @@ -16,9 +16,9 @@ ids_only={x.id} due_date_weight=1.0 priority_weight=2.0 favorite_weight=1.0 -list_weight=1.0 +project_weight=1.0 label_weight=1.0 [urgency_keywords] -list_keywords=next, test-list +project_keywords=next, test-project label_keywords=next,my_tag diff --git a/tests/conftest.py b/tests/conftest.py index e424399..5474214 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -34,8 +34,8 @@ def _login_as_test_user(): run_vja('vja --username=test --password=test user show') -def _create_list_and_task(): - run_vja('vja list add test-list') +def _create_project_and_task(): + run_vja('vja project add test-project') run_vja('vja add At least one task --force-create --priority=5 --due-date=today --tag=my_tag --favorite=True') run_vja('vja add A task without a label --force-create') @@ -56,4 +56,4 @@ def pytest_configure(): _login_as_test_user() - _create_list_and_task() + _create_project_and_task() diff --git a/tests/run.sh b/tests/run.sh index eb3fb8e..65073b7 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -7,18 +7,18 @@ run-test () { vja --help vja -u test -p test ls vja user show - vja list add Work - vja list add Home - vja list ls - vja list show 1 + vja project add Work + vja project add Home + vja project ls + vja project show 1 vja label add Next Action vja label ls vja add "Look around" --prio=2 --tag="Next Action" --note="my note" --due="next monday at 15:00" --favorite=True --reminder="friday 12:00" vja add "Stay at home" -p 4 -t "Next Action" -n "my note" -d "23:00" -f True --list=2 vja add Go home vja ls - vja ls --list=1 - vja ls --list=Work + vja ls --project=1 + vja ls --project=Work vja ls --label="Next Action" vja ls --title="home" vja ls --bucket=2 @@ -31,13 +31,12 @@ run-test () { vja show 1 --json vja show 1 --jsonvja vja toggle 1 - vja list show 1 --json + vja project show 1 --json vja bucket ls -l 1 vja label ls - vja namespace ls vja -v logout vja -v -u test -p test ls - vja -v list ls + vja -v project ls vja -v edit 1 --prio=5 --favorite=True vja -v show 1 vja -v ls diff --git a/tests/test_command.py b/tests/test_command.py index 0065b11..a9dc58d 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -5,7 +5,7 @@ import re from tests.conftest import invoke from vja.cli import cli -ADD_SUCCESS_PATTERN = re.compile(r'.*Created task (\d+) in list .*') +ADD_SUCCESS_PATTERN = re.compile(r'.*Created task (\d+) in project .*') DATE_1 = datetime.datetime(2023, 3, 30, 15, 0, 0, 0) DATE_2 = DATE_1 + datetime.timedelta(days=1) DATE_1_ISO = DATE_1.isoformat() @@ -15,27 +15,27 @@ TODAY_ISO = TODAY.isoformat() class TestAddTask: - def test_list_id(self, runner): - res = invoke(runner, 'add title of new task --force --list=1') + def test_project_id(self, runner): + res = invoke(runner, 'add title of new task --force --project=1') after = json_for_created_task(runner, res.output) - assert after['tasklist']['id'] == 1 + assert after['project']['id'] == 1 - def test_list_title(self, runner): - res = invoke(runner, 'add title of new task --force --list=test-list') + def test_project_title(self, runner): + res = invoke(runner, 'add title of new task --force --project=test-project') after = json_for_created_task(runner, res.output) - assert after['tasklist']['title'] == 'test-list' + assert after['project']['title'] == 'test-project' def test_duplicate_task_title_rejected(self, runner): invoke(runner, 'add title of new task', 1, catch_exceptions=True) def test_default_reminder_uses_due(self, runner): - res = invoke(runner, 'add title of new task --force --list=test-list --due=today --reminder') + res = invoke(runner, 'add title of new task --force --project=test-project --due=today --reminder') after = json_for_created_task(runner, res.output) assert after['reminders'][0]['relative_period'] == 0 assert after['reminders'][0]['relative_to'] == 'due_date' def test_default_reminder_with_absolute_time(self, runner): - res = invoke(runner, f'add title of new task --force --list=test-list --reminder={DATE_2_ISO}') + res = invoke(runner, f'add title of new task --force --project=test-project --reminder={DATE_2_ISO}') after = json_for_created_task(runner, res.output) assert after['reminders'][0]['reminder'] == DATE_2_ISO @@ -45,7 +45,7 @@ class TestCloneTask: before = json_for_task_id(runner, 1) res = invoke(runner, 'clone 1 title of new task cloned from 1') after = json_for_created_task(runner, res.output) - assert after['tasklist'] == before['tasklist'] + assert after['project'] == before['project'] assert after['due_date'] == before['due_date'] assert after['title'] != before['title'] assert after['id'] != before['id'] @@ -66,7 +66,7 @@ class TestEditGeneral: assert after['due_date'] == before['due_date'] assert after['reminders'] == before['reminders'] assert after['position'] == before['position'] - assert after['tasklist']['id'] == before['tasklist']['id'] + assert after['project']['id'] == before['project']['id'] assert after['created'] == before['created'] def test_edit_due_date(self, runner): @@ -108,15 +108,15 @@ class TestEditGeneral: assert note_1 == 'line1' assert note_2 == 'line1\nline2' - def test_edit_list(self, runner): - invoke(runner, 'list add another list') - invoke(runner, 'edit 1 --list-id=1') - list_1 = json_for_task_id(runner, 1)['tasklist']['id'] + def test_edit_project(self, runner): + invoke(runner, 'project add another project') + invoke(runner, 'edit 1 --project-id=1') + project_1 = json_for_task_id(runner, 1)['project']['id'] invoke(runner, 'edit 1 -l 2') - list_2 = json_for_task_id(runner, 1)['tasklist']['id'] + project_2 = json_for_task_id(runner, 1)['project']['id'] - assert list_1 == 1 - assert list_2 == 2 + assert project_1 == 1 + assert project_2 == 2 @staticmethod def _has_label_with_title(labels, title): diff --git a/tests/test_query.py b/tests/test_query.py index df2b1c9..7ad2362 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -18,47 +18,28 @@ class TestUser: assert json.loads(res.output)['username'] == 'test' -class TestNamespace: - def test_namespace_ls(self, runner): - res = invoke(runner, 'namespace ls') - assert re.search(r'test\'s namespace', res.output) +class TestProject: + def test_project_ls(self, runner): + res = invoke(runner, 'project ls') + assert re.search(r'test-project', res.output) - def test_namespace_ls_json(self, runner): - res = invoke(runner, 'namespace ls --json') - assert json.loads(res.output)[1]['title'] == 'test' - - def test_namespace_ls_jsonvja(self, runner): - res = invoke(runner, 'namespace ls --jsonvja') - assert json.loads(res.output)[1]['title'] == 'test' - - def test_namespace_ls_custom_format(self, runner): - res = invoke(runner, 'namespace ls --custom-format=ids_only') - for line in res.output: - assert re.match(r'^-?\d*$', line) - - -class TestList: - def test_list_ls(self, runner): - res = invoke(runner, 'list ls') - assert re.search(r'test-list', res.output) - - def test_list_show(self, runner): - res = invoke(runner, 'list show 1') + def test_project_show(self, runner): + res = invoke(runner, 'project show 1') assert len(res.output) > 0 - def test_list_ls_custom_format(self, runner): - res = invoke(runner, 'list ls --custom-format=ids_only') + def test_project_ls_custom_format(self, runner): + res = invoke(runner, 'project ls --custom-format=ids_only') for line in res.output: assert re.match(r'^\d*$', line) class TestBucket: def test_bucket_ls(self, runner): - res = invoke(runner, 'bucket ls --list-id=1') + res = invoke(runner, 'bucket ls --project-id=1') assert re.search(r'Backlog', res.output) def test_bucket_ls_custom_format(self, runner): - res = invoke(runner, 'bucket ls --list-id=1 --custom-format=ids_only') + res = invoke(runner, 'bucket ls --project-id=1 --custom-format=ids_only') for line in res.output: assert re.match(r'^\d*$', line) @@ -91,12 +72,12 @@ class TestSingleTask: assert data['position'] is not None assert data['kanban_position'] is not None assert data['bucket_id'] is not None - assert data['tasklist']['id'] is not None + assert data['project']['id'] is not None assert data['created'] is not None assert data['updated'] is not None -class TestTaskList: +class TestTaskLs: def test_task_ls(self, runner): res = invoke(runner, 'ls') assert re.search(r'At least one task', res.output) @@ -119,7 +100,7 @@ class TestTaskList: assert data[0]['id'] > 1 def test_sort_combined(self, runner): - res = invoke(runner, ['ls', '--jsonvja', '--sort=due_date, is_favorite, -priority, tasklist.title']) + res = invoke(runner, ['ls', '--jsonvja', '--sort=due_date, is_favorite, -priority, project.title']) data = json.loads(res.output) assert data[0]['due_date'] is not None assert data[-1]['due_date'] is None @@ -130,7 +111,7 @@ class TestTaskList: assert re.match(r'^\d*$', line) -class TestTaskListFilter: +class TestTaskLsFilter: def test_task_filter_bucket(self, runner): res = invoke(runner, ['ls', '--jsonvja', '--bucket=1']) data = json.loads(res.output) @@ -176,21 +157,12 @@ class TestTaskListFilter: assert len(data) > 0 assert all(len(i['labels']) == 0 for i in data) - def test_task_filter_list(self, runner): - res = invoke(runner, ['ls', '--jsonvja', '--list=test-list']) - data = json.loads(res.output) - assert len(data) > 0 - assert all(i['tasklist']['title'] == 'test-list' for i in data) - res = invoke(runner, ['ls', '--jsonvja', '--list=Not created']) - data = json.loads(res.output) - assert len(data) == 0 - - def test_task_filter_namespace(self, runner): - res = invoke(runner, ['ls', '--jsonvja', '--namespace=test']) + def test_task_filter_project(self, runner): + res = invoke(runner, ['ls', '--jsonvja', '--project=test-project']) data = json.loads(res.output) assert len(data) > 0 - assert all(i['tasklist']['namespace']['title'] == 'test' for i in data) - res = invoke(runner, ['ls', '--jsonvja', '--namespace=Not created']) + assert all(i['project']['title'] == 'test-project' for i in data) + res = invoke(runner, ['ls', '--jsonvja', '--project=Not created']) data = json.loads(res.output) assert len(data) == 0 diff --git a/vja/apiclient.py b/vja/apiclient.py index 132ff82..0af8bce 100755 --- a/vja/apiclient.py +++ b/vja/apiclient.py @@ -116,20 +116,20 @@ class ApiClient: self._cache['namespaces'] = self._get_json(self._create_url('/namespaces')) or [] return self._cache['namespaces'] - def get_lists(self): + def get_projects(self): if self._cache['projects'] is None: self._cache['projects'] = self._get_json(self._create_url('/projects')) or [] return self._cache['projects'] - def get_list(self, list_id): - return self._get_json(self._create_url(f'/projects/{str(list_id)}')) + def get_project(self, project_id): + return self._get_json(self._create_url(f'/projects/{str(project_id)}')) - def put_list(self, namespace_id, title): + def put_project(self, namespace_id, title): payload = {'title': title} return self._put_json(self._create_url(f'/namespaces/{str(namespace_id)}/projects'), payload=payload) - def get_buckets(self, list_id): - return self._get_json(self._create_url(f'/projects/{str(list_id)}/buckets')) + def get_buckets(self, project_id): + return self._get_json(self._create_url(f'/projects/{str(project_id)}/buckets')) def get_labels(self): if self._cache['labels'] is None: @@ -151,8 +151,8 @@ class ApiClient: url = self._create_url(f'/tasks/{str(task_id)}') return self._get_json(url) - def put_task(self, list_id, payload): - return self._put_json(self._create_url(f'/projects/{str(list_id)}'), payload=payload) + def put_task(self, project_id, payload): + return self._put_json(self._create_url(f'/projects/{str(project_id)}'), payload=payload) def post_task(self, task_id, payload): return self._post_json(self._create_url(f'/tasks/{str(task_id)}'), payload=payload) diff --git a/vja/cli.py b/vja/cli.py index 0f1789a..f19287b 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -93,43 +93,22 @@ def user_show(application, is_json=False, is_jsonvja=False): application.query_service.find_current_user(), is_json, is_jsonvja) -# namespaces -@cli.group('namespace', help='Subcommand: namespace (see help)') -def namespace_group(): +# projects +@cli.group('project', help='Subcommand: project (see help)') +def project_group(): pass -@namespace_group.command('ls', help='Print namespaces ... (id; title; description)') -@click.option('is_json', '--json', default=False, is_flag=True, - help='Print as Vikunja json') -@click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, - help='Print as vja application json') -@click.option('custom_format', '--custom-format', - help='Format with template from .vjacli/vja.rc') -@with_application -def namespace_ls(application, is_json, is_jsonvja, custom_format): - if custom_format: - custom_format = application.configuration.get_custom_format_string(custom_format) - application.output.namespace_array( - application.query_service.find_all_namespaces(), is_json, is_jsonvja, custom_format) - - -# lists -@cli.group('list', help='Subcommand: list (see help)') -def list_group(): - pass - - -@list_group.command('add', help='Add list with title') -@click.option('namespace_id', '-n', '--namespace-id', help='Create list in namespace, default: first list found') +@project_group.command('add', help='Add project with title') +@click.option('namespace_id', '-n', '--namespace-id', help='Create project in namespace, default: first namespace found') @click.argument('title', nargs=-1, required=True) @with_application -def list_add(application, title, namespace_id=None): - tasklist = application.command_service.add_list(namespace_id, " ".join(title)) - click.echo(f'Created list {tasklist.id}') +def project_add(application, title, namespace_id=None): + project = application.command_service.add_project(namespace_id, " ".join(title)) + click.echo(f'Created project {project.id}') -@list_group.command('ls', help='Print lists ... (id; title; description; namespace; namespace_id)') +@project_group.command('ls', help='Print projects ... (id; title; description; namespace; namespace_id)') @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, @@ -137,23 +116,23 @@ def list_add(application, title, namespace_id=None): @click.option('custom_format', '--custom-format', help='Format with template from .vjacli/vja.rc') @with_application -def list_ls(application, is_json, is_jsonvja, custom_format): +def project_ls(application, is_json, is_jsonvja, custom_format): if custom_format: custom_format = application.configuration.get_custom_format_string(custom_format) - application.output.list_array( - application.query_service.find_all_lists(), is_json, is_jsonvja, custom_format) + application.output.project_array( + application.query_service.find_all_projects(), is_json, is_jsonvja, custom_format) -@list_group.command('show', help='Show list details') -@click.argument('list_id', required=True, type=click.INT) +@project_group.command('show', help='Show project details') +@click.argument('project_id', required=True, type=click.INT) @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, help='Print as vja application json') @with_application -def list_show(application, list_id, is_json, is_jsonvja): - application.output.list( - application.query_service.find_list_by_id(list_id), is_json, is_jsonvja) +def project_show(application, project_id, is_json, is_jsonvja): + application.output.project( + application.query_service.find_project_by_id(project_id), is_json, is_jsonvja) # buckets @@ -162,9 +141,9 @@ def bucket_group(): pass -@bucket_group.command('ls', help='Print kanban buckets of given list ... (id; title; is_done; limit; count tasks)') -@click.option('list_id', '-l', '--list', '--list-id', '--list_id', required=True, type=click.INT, - help='Show buckets of list with id') +@bucket_group.command('ls', help='Print kanban buckets of given project ... (id; title; is_done; limit; count tasks)') +@click.option('project_id', '-l', '--list', '--project-id', '--project_id', required=True, type=click.INT, + help='Show buckets of project with id') @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, @@ -172,11 +151,11 @@ def bucket_group(): @click.option('custom_format', '--custom-format', help='Format with template from .vjacli/vja.rc') @with_application -def bucket_ls(application, list_id, is_json, is_jsonvja, custom_format): +def bucket_ls(application, project_id, is_json, is_jsonvja, custom_format): if custom_format: custom_format = application.configuration.get_custom_format_string(custom_format) application.output.bucket_array( - application.query_service.find_all_buckets_in_list(list_id), is_json, is_jsonvja, custom_format) + application.query_service.find_all_buckets_in_project(project_id), is_json, is_jsonvja, custom_format) # labels @@ -212,8 +191,8 @@ def label_add(application, title): @cli.command('add', aliases=['create'], help='Add new task') @click.argument('title', required=True, nargs=-1) -@click.option('list_id', '-l', '--folder', '--project', '--list', - help='List (id or name), defaults to list from user settings, than to first favorite list') +@click.option('project_id', '-l', '--folder', '--project', '--list', + help='Project (id or name), defaults to project from user settings, than to first favorite project') @click.option('note', '-n', '--note', '--description', help='Set description (note)') @click.option('prio', '-p', '--prio', '--priority', @@ -235,7 +214,7 @@ def label_add(application, title): def task_add(ctx, application, title, **args): args_present = {k: v for k, v in args.items() if v is not None} task = application.command_service.add_task(" ".join(title), args_present.copy()) - click.echo(f'Created task {task.id} in list {task.tasklist.id}') + click.echo(f'Created task {task.id} in project {task.project.id}') ctx.invoke(task_show, tasks=[task.id]) @@ -247,7 +226,7 @@ def task_add(ctx, application, title, **args): @click.pass_context def task_clone(ctx, application, task_id, title): task = application.command_service.clone_task(task_id, " ".join(title)) - click.echo(f'Created task {task.id} in list {task.tasklist.id} as clone from {task_id}') + click.echo(f'Created task {task.id} in project {task.project.id} as clone from {task_id}') ctx.invoke(task_show, tasks=[task.id]) @@ -262,10 +241,10 @@ def task_clone(ctx, application, task_id, title): help='Append note to existing description separated by new line') @click.option('prio', '-p', '--prio', '--priority', type=click.INT, help='Set priority') -@click.option('list_id', '-l', '--folder-id', '--project-id', '--list-id', '--list_id', type=click.INT, - help='Move to list with id') -@click.option('position', '--list-position', '--list_position', '--position', type=click.INT, - help='Set list position') +@click.option('project_id', '-l', '--folder-id', '--project-id', '--list-id', '--project_id', type=click.INT, + help='Move to project with id') +@click.option('position', '--project-position', '--project_position', '--position', type=click.INT, + help='Set project position') @click.option('bucket_id', '--bucket-id', '--bucket_id', type=click.INT, help='Set bucket id') @click.option('kanban_position', '--kanban-position', '--kanban_position', type=click.INT, @@ -291,7 +270,7 @@ def task_edit(ctx, application, task_ids, **args): for task_id in task_ids: if args_present: task = application.command_service.edit_task(task_id, args_present.copy()) - click.echo(f'Modified task {task.id} in list {task.tasklist.id}') + click.echo(f'Modified task {task.id} in project {task.project.id}') ctx.invoke(task_show, tasks=[task.id]) else: application.open_browser(task_id) @@ -303,7 +282,7 @@ def task_edit(ctx, application, task_ids, **args): @click.pass_context def task_toggle(ctx, application, task_id): task = application.command_service.toggle_task_done(task_id) - click.echo(f'Modified task {task.id} in list {task.tasklist.id}') + click.echo(f'Modified task {task.id} in project {task.project.id}') ctx.invoke(task_show, tasks=[task_id]) @@ -316,12 +295,12 @@ def task_toggle(ctx, application, task_id): def task_defer(ctx, application, task_ids, delay_by): for task_id in task_ids: task = application.command_service.defer_task(task_id, delay_by) - click.echo(f'Modified task {task.id} in list {task.tasklist.id}') + click.echo(f'Modified task {task.id} in project {task.project.id}') ctx.invoke(task_show, tasks=[task_id]) @cli.command('ls', help='List tasks ... (task-id; priority; is_favorite; title; due_date; ' - 'has reminder; namespace; list; labels; urgency)') + 'has reminder; namespace; project; labels; urgency)') @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, @@ -346,8 +325,8 @@ def task_defer(ctx, application, task_ids, delay_by): 'Multiple occurrences of --filter are allowed and will be combined with logical AND.') @click.option('label_filter', '-t', '--tag', '--label', help='Filter by label (name or id)') -@click.option('list_filter', '-l', '--list', - help='Filter by list (name or id)') +@click.option('project_filter', '-l', '--project', + help='Filter by project (name or id)') @click.option('namespace_filter', '-n', '--namespace', help='Filter by namespace (name or id)') @click.option('priority_filter', '-p', '--prio', '--priority', diff --git a/vja/config.py b/vja/config.py index 1feecfe..05898a2 100755 --- a/vja/config.py +++ b/vja/config.py @@ -34,8 +34,8 @@ class VjaConfiguration: def get_custom_format_string(self, template_key): return self._parser.get('output', template_key, fallback=None) - def get_urgency_list_keywords(self): - return self._parser.get('urgency_keywords', 'list_keywords', fallback=None) + def get_urgency_project_keywords(self): + return self._parser.get('urgency_keywords', 'project_keywords', fallback=None) def get_urgency_label_keywords(self): return self._parser.get('urgency_keywords', 'label_keywords', fallback=None) diff --git a/vja/filter.py b/vja/filter.py index a65f924..e801802 100644 --- a/vja/filter.py +++ b/vja/filter.py @@ -63,16 +63,16 @@ def _create_label_filter(value): return lambda x: any(label.title == value for label in x.labels) -def _create_list_filter(value): +def _create_project_filter(value): if str(value).isdigit(): - return _create_general_filter([f'tasklist.id eq {value}']) - return _create_general_filter([f'tasklist.title eq {value}']) + return _create_general_filter([f'project.id eq {value}']) + return _create_general_filter([f'project.title eq {value}']) def _create_namespace_filter(value): if str(value).isdigit(): - return _create_general_filter([f'tasklist.namespace.id eq {value}']) - return _create_general_filter([f'tasklist.namespace.title eq {value}']) + return _create_general_filter([f'project.namespace.id eq {value}']) + return _create_general_filter([f'project.namespace.title eq {value}']) def _create_title_filter(value): @@ -105,7 +105,7 @@ _filter_mapping = { 'favorite_filter': _create_favorite_filter, 'general_filter': _create_general_filter, 'label_filter': _create_label_filter, - 'list_filter': _create_list_filter, + 'project_filter': _create_project_filter, 'namespace_filter': _create_namespace_filter, 'title_filter': _create_title_filter, 'priority_filter': _create_priority_filter, diff --git a/vja/list_service.py b/vja/list_service.py index 8ff6cac..33f23c5 100644 --- a/vja/list_service.py +++ b/vja/list_service.py @@ -3,7 +3,7 @@ from typing import Optional from vja import VjaError from vja.apiclient import ApiClient -from vja.model import Namespace, List, User +from vja.model import Namespace, Project, User logger = logging.getLogger(__name__) @@ -12,7 +12,7 @@ class ListService: def __init__(self, api_client: ApiClient): self._api_client = api_client self._namespace_by_id: Optional[dict] = None - self._list_by_id: Optional[dict] = None + self._project_by_id: Optional[dict] = None def find_namespace_by_id(self, namespace_id: int) -> Namespace: if not self._namespace_by_id: @@ -23,35 +23,35 @@ class ListService: 'Inconsistent data: namespace_id %s is referring to non existing cached Namespace.', str(namespace_id)) return namespace_object - def find_list_by_id(self, list_id: int) -> List: - if not self._list_by_id: - self._list_by_id = {x['id']: self.convert_list_json(x) for x in self._api_client.get_lists()} - return self._list_by_id.get(list_id) - - def find_list_by_title(self, title): - list_objects = [self.convert_list_json(x) for x in self._api_client.get_lists()] - if not list_objects: - raise VjaError('No lists exist. Go and create at least one.') - list_found = [x for x in list_objects if x.title == title] - if not list_found: - raise VjaError(f'List with title {title} does not exist.') - return list_found[0] - - def get_default_list(self) -> List: + def find_project_by_id(self, project_id: int) -> Project: + if not self._project_by_id: + self._project_by_id = {x['id']: self.convert_project_json(x) for x in self._api_client.get_projects()} + return self._project_by_id.get(project_id) + + def find_project_by_title(self, title): + project_objects = [self.convert_project_json(x) for x in self._api_client.get_projects()] + if not project_objects: + raise VjaError('No projects exist. Go and create at least one.') + project_found = [x for x in project_objects if x.title == title] + if not project_found: + raise VjaError(f'Project with title {title} does not exist.') + return project_found[0] + + def get_default_project(self) -> Project: user = User.from_json(self._api_client.get_user()) - list_found = self.find_list_by_id(user.default_list_id) - if not list_found: - list_objects = [self.convert_list_json(x) for x in self._api_client.get_lists()] - if not list_objects: - raise VjaError('No lists exist. Go and create at least one.') - list_objects.sort(key=lambda x: x.id) - favorite_lists = [x for x in list_objects if x.is_favorite] - if favorite_lists: - list_found = favorite_lists[0] + project_found = self.find_project_by_id(user.default_project_id) + if not project_found: + project_objects = [self.convert_project_json(x) for x in self._api_client.get_projects()] + if not project_objects: + raise VjaError('No projects exist. Go and create at least one.') + project_objects.sort(key=lambda x: x.id) + favorite_projects = [x for x in project_objects if x.is_favorite] + if favorite_projects: + project_found = favorite_projects[0] else: - list_found = list_objects[0] - return list_found + project_found = project_objects[0] + return project_found - def convert_list_json(self, list_json: dict) -> List: - namespace = self.find_namespace_by_id(list_json['namespace_id']) - return List.from_json(list_json, namespace) + def convert_project_json(self, project_json: dict) -> Project: + namespace = self.find_namespace_by_id(project_json['namespace_id']) + return Project.from_json(project_json, namespace) diff --git a/vja/model.py b/vja/model.py index 0a8dcc3..f301692 100755 --- a/vja/model.py +++ b/vja/model.py @@ -51,7 +51,7 @@ class User: id: int username: str name: str - default_list_id: int + default_project_id: int @classmethod def from_json(cls, json): @@ -78,7 +78,7 @@ class Namespace: @dataclass(frozen=True) @data_dict -class List: +class Project: json: dict = field(repr=False) id: int title: str @@ -94,7 +94,7 @@ class List: @classmethod def from_json_array(cls, json_array, namespace): - return [List.from_json(x, namespace) for x in json_array or []] + return [Project.from_json(x, namespace) for x in json_array or []] @dataclass(frozen=True) @@ -177,7 +177,7 @@ class Task: done: bool done_at: datetime labels: typing.List[Label] - tasklist: List + project: Project position: int bucket_id: int kanban_position: int @@ -190,7 +190,7 @@ class Task: return ",".join(map(lambda label: label.title, self.labels or [])) @classmethod - def from_json(cls, json, list_object, labels): + def from_json(cls, json, project_object, labels): return cls(json, json['id'], json['title'], json['description'], json['priority'], json['is_favorite'], @@ -204,7 +204,7 @@ class Task: json['done'], parse_json_date(json['done_at']), labels, - list_object, + project_object, json['position'], json['bucket_id'], json['kanban_position'], diff --git a/vja/output.py b/vja/output.py index 485abad..59c8e6a 100644 --- a/vja/output.py +++ b/vja/output.py @@ -3,11 +3,11 @@ import logging import click -from vja.model import User, List, Task +from vja.model import User, Task, Project NAMESPACE_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.description:20.20}' -LIST_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.description:20.20} ' \ +PROJECT_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.description:20.20} ' \ '{x.namespace.title:20.20} {x.namespace.id:5}' BUCKET_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.is_done_bucket:2} {x.limit:3} {x.count_tasks:5}' @@ -16,7 +16,7 @@ LABEL_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20}' TASK_LIST_FORMAT_DEFAULT = '{x.id:5} ({x.priority}) {"*" if x.is_favorite else " "} {x.title:50.50} ' \ '{x.due_date.strftime("%a %d.%m %H:%M") if x.due_date else "":15.15} ' \ - '{"R" if x.reminders else " "} {x.tasklist.title:20.20} ' \ + '{"R" if x.reminders else " "} {x.project.title:20.20} ' \ '{x.label_titles:20.20} {x.urgency:3.1f}' logger = logging.getLogger(__name__) @@ -27,8 +27,8 @@ class Output: def user(self, user: User, is_json, is_jsonvja): self._dump(user, is_json, is_jsonvja) - def list(self, task_list: List, is_json, is_jsonvja): - self._dump(task_list, is_json, is_jsonvja) + def project(self, project: Project, is_json, is_jsonvja): + self._dump(project, is_json, is_jsonvja) def task(self, task: Task, is_json, is_jsonvja): self._dump(task, is_json, is_jsonvja) @@ -37,8 +37,8 @@ class Output: line_format = custom_format or NAMESPACE_LIST_FORMAT_DEFAULT self._dump_array(object_array, line_format, is_json, is_jsonvja) - def list_array(self, object_array, is_json, is_jsonvja, custom_format=None): - line_format = custom_format or LIST_LIST_FORMAT_DEFAULT + def project_array(self, object_array, is_json, is_jsonvja, custom_format=None): + line_format = custom_format or PROJECT_LIST_FORMAT_DEFAULT self._dump_array(object_array, line_format, is_json, is_jsonvja) def bucket_array(self, object_array, is_json, is_jsonvja, custom_format=None): diff --git a/vja/service_command.py b/vja/service_command.py index 5514933..aeb87ec 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -23,13 +23,13 @@ class CommandService: self._api_client.logout() logger.info('Logged out') - # list - def add_list(self, namespace_id, title): + # project + def add_project(self, namespace_id, title): if not namespace_id: namespaces = self._api_client.get_namespaces() namespace_id = min(namespace['id'] if namespace['id'] > 0 else 99999 for namespace in namespaces) - list_json = self._api_client.put_list(namespace_id, title) - return self._list_service.convert_list_json(list_json) + project_json = self._api_client.put_project(namespace_id, title) + return self._list_service.convert_project_json(project_json) # label def add_label(self, title): @@ -44,7 +44,7 @@ class CommandService: 'favorite': {'field': 'is_favorite', 'mapping': bool}, 'completed': {'field': 'done', 'mapping': bool}, 'position': {'field': 'position', 'mapping': int}, - 'list_id': {'field': 'project_id', 'mapping': int}, + 'project_id': {'field': 'project_id', 'mapping': int}, 'bucket_id': {'field': 'bucket_id', 'mapping': int}, 'kanban_position': {'field': 'kanban_position', 'mapping': int}, 'reminder': {'field': 'reminders', 'mapping': (lambda x: x)} @@ -59,14 +59,14 @@ class CommandService: def add_task(self, title, args: dict): args.update({'title': title}) - if args.get('list_id'): - list_arg = args.pop('list_id') - if str(list_arg).isdigit(): - list_id = list_arg + if args.get('project_id'): + project_arg = args.pop('project_id') + if str(project_arg).isdigit(): + project_id = project_arg else: - list_id = self._list_service.find_list_by_title(list_arg).id + project_id = self._list_service.find_project_by_title(project_arg).id else: - list_id = self._list_service.get_default_list().id + project_id = self._list_service.get_default_project().id tag_name = args.pop('tag') if args.get('tag') else None is_force = args.pop('force_create') if args.get('force_create') is not None else False @@ -77,7 +77,7 @@ class CommandService: if not is_force: self._validate_add_task(title, tag_name) logger.debug('put task: %s', payload) - task_json = self._api_client.put_task(list_id, payload) + task_json = self._api_client.put_task(project_id, payload) task = self._task_service.task_from_json(task_json) label = self._label_from_name(tag_name, is_force) if tag_name else None diff --git a/vja/service_query.py b/vja/service_query.py index 1a26b36..c0a5e4a 100644 --- a/vja/service_query.py +++ b/vja/service_query.py @@ -8,7 +8,7 @@ from vja.parse import rgetattr from vja.task_service import TaskService logger = logging.getLogger(__name__) -DEFAULT_SORT_STRING = 'done, -urgency, due_date, -priority, tasklist.title, title' +DEFAULT_SORT_STRING = 'done, -urgency, due_date, -priority, project.title, title' class QueryService: @@ -25,16 +25,16 @@ class QueryService: def find_all_namespaces(self): return Namespace.from_json_array(self._api_client.get_namespaces()) - # list - def find_all_lists(self): - return [self._list_service.convert_list_json(list_json) for list_json in (self._api_client.get_lists())] + # project + def find_all_projects(self): + return [self._list_service.convert_project_json(project_json) for project_json in (self._api_client.get_projects())] - def find_list_by_id(self, list_id): - return self._list_service.convert_list_json(self._api_client.get_list(list_id)) + def find_project_by_id(self, project_id): + return self._list_service.convert_project_json(self._api_client.get_project(project_id)) # bucket - def find_all_buckets_in_list(self, list_id): - return Bucket.from_json_array(self._api_client.get_buckets(list_id)) + def find_all_buckets_in_project(self, project_id): + return Bucket.from_json_array(self._api_client.get_buckets(project_id)) # label def find_all_labels(self): diff --git a/vja/task_service.py b/vja/task_service.py index 6e127ba..83024fa 100644 --- a/vja/task_service.py +++ b/vja/task_service.py @@ -13,8 +13,8 @@ class TaskService: self._urgency = urgency def task_from_json(self, task_json: dict) -> Task: - list_object = self._list_service.find_list_by_id(task_json['project_id']) + project_object = self._list_service.find_project_by_id(task_json['project_id']) labels = Label.from_json_array(task_json['labels']) - task = Task.from_json(task_json, list_object, labels) + task = Task.from_json(task_json, project_object, labels) task.urgency = self._urgency.compute_for(task) return task diff --git a/vja/urgency.py b/vja/urgency.py index a568fd6..897ea7e 100644 --- a/vja/urgency.py +++ b/vja/urgency.py @@ -6,9 +6,9 @@ from vja.model import Task class Urgency: - def __init__(self, urgency_coefficients: dict, list_keywords, label_keywords): + def __init__(self, urgency_coefficients: dict, project_keywords, label_keywords): self._urgency_coefficients = urgency_coefficients - self._list_keywords = list_keywords + self._project_keywords = project_keywords self._label_keywords = label_keywords def compute_for(self, task: Task): @@ -17,20 +17,20 @@ class Urgency: due_date_score = self._get_due_date_score(task) * self._urgency_coefficients.get('due_date_weight', 1.0) priority_score = task.priority * self._urgency_coefficients.get('priority_weight', 1.0) favorite_score = int(task.is_favorite) * self._urgency_coefficients.get('favorite_weight', 1.0) - list_name_score = self._get_list_score(task) * self._urgency_coefficients.get('list_keyword', 1.0) + project_name_score = self._get_project_score(task) * self._urgency_coefficients.get('project_keyword', 1.0) lable_name_score = self._get_label_score(task) * self._urgency_coefficients.get('label_keyword', 1.0) - return 1 + due_date_score + priority_score + favorite_score + list_name_score + lable_name_score + return 1 + due_date_score + priority_score + favorite_score + project_name_score + lable_name_score def _get_label_score(self, task): task_label_title = task.label_titles.lower() return int(any(label_name.lower() in task_label_title for label_name in self._label_keywords)) if self._label_keywords else 0 - def _get_list_score(self, task): - task_list_title = task.tasklist.title.lower() - return int(any(list_name.lower() in task_list_title for list_name in - self._list_keywords)) if self._list_keywords else 0 + def _get_project_score(self, task): + task_project_title = task.project.title.lower() + return int(any(project_name.lower() in task_project_title for project_name in + self._project_keywords)) if self._project_keywords else 0 @staticmethod def _get_due_date_score(task: Task): @@ -58,10 +58,10 @@ class Urgency: @classmethod def from_config(cls, config: VjaConfiguration): - config_list_keywords = config.get_urgency_list_keywords() - list_keywords = [x.strip() for x in config_list_keywords.split(',')] if config_list_keywords else [] + config_project_keywords = config.get_urgency_project_keywords() + project_keywords = [x.strip() for x in config_project_keywords.split(',')] if config_project_keywords else [] config_label_keywords = config.get_urgency_label_keywords() label_keywords = [x.strip() for x in config_label_keywords.split(',')] if config_label_keywords else [] urgency_coefficients = {k: float(v) for k, v in config.get_urgency_coefficients().items()} - return cls(urgency_coefficients, list_keywords, label_keywords) + return cls(urgency_coefficients, project_keywords, label_keywords) -- GitLab From ed78554db8f5adaec000fca4358d709755ee20a5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 2 Apr 2023 20:49:46 +0000 Subject: [PATCH 34/55] chore(release): Release 2.0.0-beta.2 update changelog [skip ci] ## [2.0.0-beta.2](https://gitlab.com/ce72/vja/compare/2.0.0-beta.1...2.0.0-beta.2) (2023-04-02) ### Features * rename lists to project within vja ([f757117](https://gitlab.com/ce72/vja/commit/f75711797d887ffee8cd5b3ab7ec7edb8044494e)) --- CHANGELOG.md | 7 +++++++ setup.cfg | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3066b93..f492b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2.0.0-beta.2](https://gitlab.com/ce72/vja/compare/2.0.0-beta.1...2.0.0-beta.2) (2023-04-02) + + +### Features + +* rename lists to project within vja ([f757117](https://gitlab.com/ce72/vja/commit/f75711797d887ffee8cd5b3ab7ec7edb8044494e)) + ## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.0...2.0.0-beta.1) (2023-04-01) diff --git a/setup.cfg b/setup.cfg index c8a9fe3..e1aa5d2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b1 +version = 2.0.0b2 -- GitLab From 1e8a7b86ae4781b812909132d1574380965e99d3 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Mon, 10 Apr 2023 09:40:38 +0200 Subject: [PATCH 35/55] feat: fetch long_token when logging in (with a ttl of 30 days) --- tests/docker-compose.yml | 3 ++- vja/authenticate.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 544e009..351f109 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -8,6 +8,8 @@ services: environment: VIKUNJA_SERVICE_FRONTENDURL: http://localhost:8080/ VIKUNJA_RATELIMIT_LIMIT: 10000 + #VIKUNJA_LOG_LEVEL: DEBUG + #VIKUNJA_LOG_DATABASELEVEL: DEBUG entrypoint: > /bin/sh -c " /app/vikunja/vikunja user create -u test -p test -e test@test.test @@ -19,4 +21,3 @@ services: - "8080:80" environment: VIKUNJA_API_URL: http://localhost:3456/api/v1 - diff --git a/vja/authenticate.py b/vja/authenticate.py index dd42a91..d7f3b14 100644 --- a/vja/authenticate.py +++ b/vja/authenticate.py @@ -64,7 +64,8 @@ class Login: def _post_login_request(self, username, password, totp_passcode): login_url = self._create_url('/login') - payload = {'username': username, + payload = {'long_token': True, + 'username': username, 'password': password, 'totp_passcode': totp_passcode} return requests.post(login_url, json=payload, timeout=30) -- GitLab From 1d10ce675ab4dd4305196e7048261b018c4dd9f7 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 10 Apr 2023 07:45:02 +0000 Subject: [PATCH 36/55] chore(release): Release 2.0.0-beta.3 update changelog [skip ci] ## [2.0.0-beta.3](https://gitlab.com/ce72/vja/compare/2.0.0-beta.2...2.0.0-beta.3) (2023-04-10) ### Features * fetch long_token when logging in (with a ttl of 30 days) ([04b8932](https://gitlab.com/ce72/vja/commit/04b8932288b8072ad85a6614147e3b835a4f8bff)) --- CHANGELOG.md | 7 +++++++ setup.cfg | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f492b91..dac47c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2.0.0-beta.3](https://gitlab.com/ce72/vja/compare/2.0.0-beta.2...2.0.0-beta.3) (2023-04-10) + + +### Features + +* fetch long_token when logging in (with a ttl of 30 days) ([04b8932](https://gitlab.com/ce72/vja/commit/04b8932288b8072ad85a6614147e3b835a4f8bff)) + ## [2.0.0-beta.2](https://gitlab.com/ce72/vja/compare/2.0.0-beta.1...2.0.0-beta.2) (2023-04-02) diff --git a/setup.cfg b/setup.cfg index e1aa5d2..351f656 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b2 +version = 2.0.0b3 -- GitLab From ef0c2bd9b6b38414a091787c3d641cc9e9799f9a Mon Sep 17 00:00:00 2001 From: cernst72 Date: Sat, 15 Apr 2023 07:04:38 +0200 Subject: [PATCH 37/55] doc: describe env variable VJA_CONFIGDIR --- Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Readme.md b/Readme.md index eae61a9..3866829 100755 --- a/Readme.md +++ b/Readme.md @@ -38,6 +38,9 @@ Before using vja you must provide a configuration. Especially, the api_url must be reachable from your client. This can be verified, for example by `curl https://mydomain.com/api/v1/info` +You may change the location of the configuration directory with an environment variable +like `VJA_CONFIGDIR=/not/my/home` + ### Description of configuration #### Required options -- GitLab From 9e0a9aa8ce9e8d6b845063888c22ece7f40b1028 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Thu, 20 Apr 2023 08:25:04 +0200 Subject: [PATCH 38/55] fix(clone): do not clone positions and have --bucket --- Features.md | 45 +++++++++++++++++++++--------------------- tests/test_command.py | 11 +++++++++++ vja/cli.py | 6 ++++-- vja/service_command.py | 6 +++++- 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/Features.md b/Features.md index 5caef68..d81c820 100644 --- a/Features.md +++ b/Features.md @@ -2,26 +2,26 @@ -* [Features](#features) - * [Create Task](#create-task) - * [Clone](#clone) - * [List tasks](#list-tasks) - * [Urgency](#urgency) - * [Filter](#filter) - * [Sort](#sort) - * [Select](#select) - * [Show single task by id](#show-single-task-by-id) - * [Modify tasks](#modify-tasks) - * [Defer task](#defer-task) - * [Reminders](#reminders) - * [Batch editing](#batch-editing) - * [Open Vikunja in browser](#open-vikunja-in-browser) - * [Manage projects, labels, buckets](#manage-projects-labels-buckets) - * [Manage project)](#manage-projects) - * [Manage kanban buckets](#manage-kanban-buckets) - * [Manage labels](#manage-labels) - * [Output format](#output-format) - * [Terminate session](#terminate-session) +- [Features](#features) + - [Create Task](#create-task) + - [Clone](#clone) + - [List tasks](#list-tasks) + - [Urgency](#urgency) + - [Filter](#filter) + - [Sort](#sort) + - [Select](#select) + - [Show single task by id](#show-single-task-by-id) + - [Modify tasks](#modify-tasks) + - [Defer task](#defer-task) + - [Reminders](#reminders) + - [Batch editing](#batch-editing) + - [Open Vikunja in browser](#open-vikunja-in-browser) + - [Manage projects, labels, buckets](#manage-projects-labels-buckets) + - [Manage projects](#manage-projects) + - [Manage kanban buckets](#manage-kanban-buckets) + - [Manage labels](#manage-labels) + - [Output format](#output-format) + - [Terminate session](#terminate-session) @@ -55,6 +55,7 @@ Another option to create a new task is cloning an existing task ```shell vja clone 1 Clone a new task ``` +By default, the kanban bucket is not cloned so that cloned tasks should appear in the leftmost Kanban lane of the project. Call `vja clone 1 New task --bucket` to clone the Kanban bucket too. See @@ -196,8 +197,8 @@ vja edit 1 --reminder Set reminder relative to due date (only due date is supported by vja for relative reminders) ```shell -vja edit --reminder="1h before due_date" -vja edit -r "10m before due" +vja edit --reminder="1h before due_date" +vja edit -r "10m before due" ``` Remove the earliest reminder diff --git a/tests/test_command.py b/tests/test_command.py index a9dc58d..b5c9467 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -47,9 +47,20 @@ class TestCloneTask: after = json_for_created_task(runner, res.output) assert after['project'] == before['project'] assert after['due_date'] == before['due_date'] +# assert after['labels'] == before['labels'] assert after['title'] != before['title'] assert after['id'] != before['id'] assert after['created'] != before['created'] + assert after['position'] != before['position'] + assert after['kanban_position'] != before['kanban_position'] +# assert after['bucket_id'] != before['bucket_id'] # TODO: Need to create a second bucket to test this + + + def test_clone_task_keeping_bucket(self, runner): + before = json_for_task_id(runner, 1) + res = invoke(runner, 'clone 1 --bucket title of new task with labels cloned from 1') + after = json_for_created_task(runner, res.output) + assert after['bucket_id'] == before['bucket_id'] class TestEditGeneral: diff --git a/vja/cli.py b/vja/cli.py index f19287b..f4c2a44 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -222,10 +222,12 @@ def task_add(ctx, application, title, **args): help='Clone task with given task_id. Set the new title') @click.argument('task_id', required=True, type=click.INT) @click.argument('title', required=True, nargs=-1) +@click.option('is_clone_bucket', '--bucket', is_flag=True, + help='Clone kanban bucket too. Default: False') @with_application @click.pass_context -def task_clone(ctx, application, task_id, title): - task = application.command_service.clone_task(task_id, " ".join(title)) +def task_clone(ctx, application, task_id, title, is_clone_bucket=False): + task = application.command_service.clone_task(task_id, " ".join(title), is_clone_bucket) click.echo(f'Created task {task.id} in project {task.project.id} as clone from {task_id}') ctx.invoke(task_show, tasks=[task.id]) diff --git a/vja/service_command.py b/vja/service_command.py index aeb87ec..bc288d3 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -85,10 +85,14 @@ class CommandService: self._api_client.add_label_to_task(task.id, label.id) return task - def clone_task(self, task_id: int, title): + def clone_task(self, task_id: int, title, is_clone_bucket): task_remote = self._api_client.get_task(task_id) task_remote.update({'id': None}) task_remote.update({'title': title}) + task_remote.update({'position': 0}) + task_remote.update({'kanban_position': 0}) + if is_clone_bucket: + task_remote.update({'bucket_id': 0}) # make sure we do not send back the old reminder_dates task_remote.pop("reminder_dates", None) -- GitLab From 15fac96ec4f34fbde4906eef925646fef8ba0d6e Mon Sep 17 00:00:00 2001 From: cernst72 Date: Thu, 20 Apr 2023 08:25:04 +0200 Subject: [PATCH 39/55] fix(clone): do not clone positions and have --bucket --- Features.md | 44 +++++++++++++++++++++----------------------- vja/cli.py | 2 +- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/Features.md b/Features.md index d81c820..597080e 100644 --- a/Features.md +++ b/Features.md @@ -1,28 +1,26 @@ # Features - -- [Features](#features) - - [Create Task](#create-task) - - [Clone](#clone) - - [List tasks](#list-tasks) - - [Urgency](#urgency) - - [Filter](#filter) - - [Sort](#sort) - - [Select](#select) - - [Show single task by id](#show-single-task-by-id) - - [Modify tasks](#modify-tasks) - - [Defer task](#defer-task) - - [Reminders](#reminders) - - [Batch editing](#batch-editing) - - [Open Vikunja in browser](#open-vikunja-in-browser) - - [Manage projects, labels, buckets](#manage-projects-labels-buckets) - - [Manage projects](#manage-projects) - - [Manage kanban buckets](#manage-kanban-buckets) - - [Manage labels](#manage-labels) - - [Output format](#output-format) - - [Terminate session](#terminate-session) - +* [Features](#features) + * [Create Task](#create-task) + * [Clone](#clone) + * [List tasks](#list-tasks) + * [Urgency](#urgency) + * [Filter](#filter) + * [Sort](#sort) + * [Select](#select) + * [Show single task by id](#show-single-task-by-id) + * [Modify tasks](#modify-tasks) + * [Defer task](#defer-task) + * [Reminders](#reminders) + * [Batch editing](#batch-editing) + * [Open Vikunja in browser](#open-vikunja-in-browser) + * [Manage projects, labels, buckets](#manage-projects-labels-buckets) + * [Manage projects](#manage-projects) + * [Manage kanban buckets](#manage-kanban-buckets) + * [Manage labels](#manage-labels) + * [Output format](#output-format) + * [Terminate session](#terminate-session) ## Create Task @@ -55,7 +53,7 @@ Another option to create a new task is cloning an existing task ```shell vja clone 1 Clone a new task ``` -By default, the kanban bucket is not cloned so that cloned tasks should appear in the leftmost Kanban lane of the project. Call `vja clone 1 New task --bucket` to clone the Kanban bucket too. +By default, the kanban bucket is not cloned so that cloned tasks should appear in the leftmost Kanban column of the project. Call `vja clone 1 New task --bucket` to clone the Kanban bucket too. See diff --git a/vja/cli.py b/vja/cli.py index f4c2a44..e8f2e70 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -222,7 +222,7 @@ def task_add(ctx, application, title, **args): help='Clone task with given task_id. Set the new title') @click.argument('task_id', required=True, type=click.INT) @click.argument('title', required=True, nargs=-1) -@click.option('is_clone_bucket', '--bucket', is_flag=True, +@click.option('is_clone_bucket', '-b', '--bucket', is_flag=True, help='Clone kanban bucket too. Default: False') @with_application @click.pass_context -- GitLab From 05169086c09ff4b77d597799defff00b01f4b591 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Mon, 24 Apr 2023 10:19:07 +0200 Subject: [PATCH 40/55] fix(clone): clone labels too --- tests/test_command.py | 2 +- vja/service_command.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_command.py b/tests/test_command.py index b5c9467..bfd23db 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -47,7 +47,7 @@ class TestCloneTask: after = json_for_created_task(runner, res.output) assert after['project'] == before['project'] assert after['due_date'] == before['due_date'] -# assert after['labels'] == before['labels'] + assert after['labels'] == before['labels'] assert after['title'] != before['title'] assert after['id'] != before['id'] assert after['created'] != before['created'] diff --git a/vja/service_command.py b/vja/service_command.py index bc288d3..bee4536 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -100,6 +100,8 @@ class CommandService: task_json = self._api_client.put_task(task_remote['project_id'], task_remote) task = self._task_service.task_from_json(task_json) + for label in task_remote['labels']: + self._api_client.add_label_to_task(task.id, label['id']) return task def edit_task(self, task_id: int, args: dict): -- GitLab From 65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 24 Apr 2023 08:34:51 +0000 Subject: [PATCH 41/55] chore(release): Release 2.0.0-beta.4 update changelog [skip ci] ## [2.0.0-beta.4](https://gitlab.com/ce72/vja/compare/2.0.0-beta.3...2.0.0-beta.4) (2023-04-24) ### Bug Fixes * **clone:** clone labels too ([22bf1c0](https://gitlab.com/ce72/vja/commit/22bf1c075888d931ceefc989d50eb49282adccf5)) * **clone:** do not clone positions and have --bucket ([bc382c2](https://gitlab.com/ce72/vja/commit/bc382c2aa9ca4b8109e62b8fce6f792b49c18fce)) * **clone:** do not clone positions and have --bucket ([5edeaba](https://gitlab.com/ce72/vja/commit/5edeaba7cad2695fdf5470f6568bd4048d23c568)) ### Documentation * describe env variable VJA_CONFIGDIR ([11e1a97](https://gitlab.com/ce72/vja/commit/11e1a979dbfb169b5559145adc735df65ef09838)) --- CHANGELOG.md | 14 ++++++++++++++ setup.cfg | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dac47c9..869a51f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [2.0.0-beta.4](https://gitlab.com/ce72/vja/compare/2.0.0-beta.3...2.0.0-beta.4) (2023-04-24) + + +### Bug Fixes + +* **clone:** clone labels too ([22bf1c0](https://gitlab.com/ce72/vja/commit/22bf1c075888d931ceefc989d50eb49282adccf5)) +* **clone:** do not clone positions and have --bucket ([bc382c2](https://gitlab.com/ce72/vja/commit/bc382c2aa9ca4b8109e62b8fce6f792b49c18fce)) +* **clone:** do not clone positions and have --bucket ([5edeaba](https://gitlab.com/ce72/vja/commit/5edeaba7cad2695fdf5470f6568bd4048d23c568)) + + +### Documentation + +* describe env variable VJA_CONFIGDIR ([11e1a97](https://gitlab.com/ce72/vja/commit/11e1a979dbfb169b5559145adc735df65ef09838)) + ## [2.0.0-beta.3](https://gitlab.com/ce72/vja/compare/2.0.0-beta.2...2.0.0-beta.3) (2023-04-10) diff --git a/setup.cfg b/setup.cfg index 351f656..418868a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b3 +version = 2.0.0b4 -- GitLab From 3701ab25ddeebc7f07959c0ac2bdca9833b5d15f Mon Sep 17 00:00:00 2001 From: cernst72 Date: Mon, 24 Apr 2023 21:22:59 +0200 Subject: [PATCH 42/55] feat(cli): alias --urgent for --urgency --- vja/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vja/cli.py b/vja/cli.py index e8f2e70..6bb3750 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -336,7 +336,7 @@ def task_defer(ctx, application, task_ids, delay_by): 'Shortcut for --filter="priority "') @click.option('title_filter', '-i', '--title', help='Filter title (regex)') -@click.option('urgency_filter', '-u', '--urgency', is_flag=False, flag_value=3, type=click.INT, +@click.option('urgency_filter', '-u', '--urgent', '--urgency', is_flag=False, flag_value=3, type=click.INT, help='Filter by minimum urgency. Shortcut for --filter="urgency ge "') @with_application def task_ls(application, is_json, is_jsonvja, custom_format, include_completed, sort_string=None, **filter_args): -- GitLab From 2c2b967f736055f6ab65a3ef7f03c05cc6798344 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Mon, 24 Apr 2023 21:31:54 +0200 Subject: [PATCH 43/55] doc(filters): improve documentation (and tests) --- Features.md | 24 ++++++++++++++++-------- Readme.md | 4 ++-- tests/test_query.py | 32 +++++++++++++++++++++++--------- vja/filter.py | 2 +- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/Features.md b/Features.md index 597080e..ee79b06 100644 --- a/Features.md +++ b/Features.md @@ -83,24 +83,32 @@ example. The displayed tasks may be filtered by several arguments like project or title, namespace and label ```shell +vja ls --bucket_id=1 +vja ls --due-date="before today" +vja ls --due-date="ge in 0 days" --due-date="before 5 days" +vja ls --favorite=True vja ls --label=@work -vja ls --title=ask vja ls --priority="gt 3" vja ls --priority="eq 5" -vja ls --due-date="before today" -vja ls --due-date="ge in 0 days" --due-date="before 5 days" -vja ls -u # show Tasks with minimum urgency -vja ls --urgency=8 # show quite urgent tasks +vja ls --title=ask # matches regex string +vja ls -u # show Tasks with minimum urgency of 3 +vja ls --urgency=8 # show only quite urgent tasks ``` In addition to these shortcut filters, more general filtering can be done by `--filter= `: ```shell -vja ls --filter="priority gt 2" -vja ls --filter="title contains clean up" -vja ls --filter="labels contains @work" vja ls --filter="created after 2 days ago" vja ls --filter="due_date before today in 7 days" +vja ls --filter="label_titles contains @work" +vja ls --filter="label_titles ne @work" +vja ls --filter="priority gt 2" +vja ls --filter="title contains clean up" +``` + +All filters can be combined (and operation): +```shell +vja ls --filter="label_titles ne @work" --project=1 --urgent ``` See `vja ls --help` for more. diff --git a/Readme.md b/Readme.md index 3866829..d4ca3b0 100755 --- a/Readme.md +++ b/Readme.md @@ -35,8 +35,8 @@ Before using vja you must provide a configuration. (If you cloned from git, you may copy the folder .vjacli to your `$HOME` directory instead.) - Adjust to your needs. `frontend_url` and `api_url` must point to your own Vikunja server. - Especially, the api_url must be reachable from your client. This can be verified, for example - by `curl https://mydomain.com/api/v1/info` + Especially, the api_url must be reachable from your client. This can be verified, for example, + by `curl https://mydomain.com/api/v1/info`. You may change the location of the configuration directory with an environment variable like `VJA_CONFIGDIR=/not/my/home` diff --git a/tests/test_query.py b/tests/test_query.py index 7ad2362..32b9af3 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -147,7 +147,7 @@ class TestTaskLsFilter: data = json.loads(res.output) assert len(data) > 0 assert data[0]['labels'][0]['title'] == 'my_tag' - res = invoke(runner, ['ls', '--jsonvja', '--label=Not created']) + res = invoke(runner, ['ls', '--jsonvja', '--label=unknown_label']) data = json.loads(res.output) assert len(data) == 0 @@ -198,14 +198,6 @@ class TestTaskLsFilter: assert len(data) == 0 def test_task_filter_general(self, runner): - res = invoke(runner, ['ls', '--jsonvja', '--filter=title contains At least one']) - assert len(json.loads(res.output)) > 0 - res = invoke(runner, ['ls', '--jsonvja', '--filter=title contains TASK_NOT_CREATED']) - assert len(json.loads(res.output)) == 0 - res = invoke(runner, ['ls', '--jsonvja', '--filter=priority gt 2']) - assert len(json.loads(res.output)) > 0 - res = invoke(runner, ['ls', '--jsonvja', '--filter=priority gt 5']) - assert len(json.loads(res.output)) == 0 res = invoke(runner, ['ls', '--jsonvja', '--filter=due_date after 2 days ago']) assert len(json.loads(res.output)) > 0 res = invoke(runner, ['ls', '--jsonvja', '--filter=due_date after 200 days']) @@ -216,9 +208,31 @@ class TestTaskLsFilter: data = json.loads(res.output) assert len(data) > 0 assert all(i['is_favorite'] for i in data) + res = invoke(runner, ['ls', '--jsonvja', '--filter=priority gt 2']) + assert len(json.loads(res.output)) > 0 + res = invoke(runner, ['ls', '--jsonvja', '--filter=priority gt 5']) + assert len(json.loads(res.output)) == 0 + res = invoke(runner, ['ls', '--jsonvja', '--filter=title contains At least one']) + assert len(json.loads(res.output)) > 0 + res = invoke(runner, ['ls', '--jsonvja', '--filter=title contains TASK_NOT_CREATED']) + assert len(json.loads(res.output)) == 0 + + def test_task_filter_general_label(self, runner): + res = invoke(runner, ['ls', '--json', '--filter=label_titles contains my_tag']) + data = json.loads(res.output) + assert len(data) > 0 + assert all('my_tag' in _labels_from_task_json(task) for task in data) + res = invoke(runner, ['ls', '--jsonvja', '--filter=label_titles ne my_tag']) + data = json.loads(res.output) + assert len(data) > 0 + assert all('my_tag' not in _labels_from_task_json(task) for task in data) def test_task_filter_general_combined(self, runner): res = invoke(runner, ['ls', '--jsonvja', '--filter=id gt 0', '--filter=id lt 2']) data = json.loads(res.output) assert len(data) == 1 assert all(i['id'] == 1 for i in data) + + +def _labels_from_task_json(task): + return ' '.join(map(lambda label: label['title'], task['labels'] or [])) diff --git a/vja/filter.py b/vja/filter.py index e801802..30df636 100644 --- a/vja/filter.py +++ b/vja/filter.py @@ -29,7 +29,7 @@ def _create_single_general_filter(value: str): field = arguments[0] operation = _operators[arguments[1]] value = arguments[2] - logger.debug("filter %s: %s %s", field, operation.__name__, value) + logger.debug("general filter %s: %s %s", field, operation.__name__, value) return lambda x: _general_filter(x, field, operation, value) -- GitLab From 60d6915845050c5b5b8e528feea69a42f8bbe5d3 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Thu, 27 Apr 2023 22:32:11 +0200 Subject: [PATCH 44/55] ci: wait for running api container --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3b7c502..0aafbf1 100755 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -35,7 +35,7 @@ integration-test: DOCKER_TLS_CERTDIR: "" script: - docker --version - - apk add --no-cache bash python3 py3-pip + - apk add --no-cache bash curl python3 py3-pip - python3 --version - pip install -r requirements_dev.txt -- GitLab From f6a70e58506104f5c0fd6eb421baf9017f31feb9 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Thu, 4 May 2023 22:02:32 +0200 Subject: [PATCH 45/55] feat(defer task): defer passed due date relative to now --- Readme.md | 1 - tests/test_command.py | 18 ++++++++++++++---- vja/service_command.py | 8 +++++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index d4ca3b0..043b63b 100755 --- a/Readme.md +++ b/Readme.md @@ -108,7 +108,6 @@ Run integration test (requires docker and docker-compose) ```shell docker-compose -f tests/docker-compose.yml up -d -./run.sh VJA_CONFIGDIR=tests/.vjatest pytest docker-compose -f tests/docker-compose.yml down ``` diff --git a/tests/test_command.py b/tests/test_command.py index bfd23db..4ae78f1 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -6,12 +6,15 @@ from tests.conftest import invoke from vja.cli import cli ADD_SUCCESS_PATTERN = re.compile(r'.*Created task (\d+) in project .*') -DATE_1 = datetime.datetime(2023, 3, 30, 15, 0, 0, 0) +TODAY = datetime.datetime.now().replace(microsecond=0) +TODAY_ISO = TODAY.isoformat() +YESTERDAY = TODAY + datetime.timedelta(days=-1) +YESTERDAY_ISO = YESTERDAY.isoformat() +TOMORROW_ISO = (TODAY + datetime.timedelta(days=1)).isoformat() +DATE_1 = TODAY + datetime.timedelta(days=10) DATE_2 = DATE_1 + datetime.timedelta(days=1) DATE_1_ISO = DATE_1.isoformat() DATE_2_ISO = DATE_2.isoformat() -TODAY = datetime.datetime.now() -TODAY_ISO = TODAY.isoformat() class TestAddTask: @@ -219,7 +222,7 @@ class TestDeferTask: assert after['due_date'] == DATE_2_ISO assert after['reminders'][0]['reminder'] == DATE_2_ISO - def test_dont_modify_relative_reminder(self, runner): + def test_dont_defer_relative_reminder(self, runner): invoke(runner, f'edit 2 --due-date={DATE_1_ISO} -r') invoke(runner, 'defer 2 1d') @@ -229,6 +232,13 @@ class TestDeferTask: assert after['reminders'][0]['relative_period'] == 0 assert after['reminders'][0]['relative_to'] == 'due_date' + def test_defer_past_due_realtive_to_now(self, runner): + invoke(runner, f'edit 2 --due-date={YESTERDAY_ISO}') + + invoke(runner, 'defer 2 1d') + + after = json_for_task_id(runner, 2) + assert after['due_date'][:10] == TOMORROW_ISO[:10] class TestMultipleTasks: def test_edit_three_tasks(self, runner): diff --git a/vja/service_command.py b/vja/service_command.py index bee4536..2850f20 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -1,3 +1,4 @@ +import datetime import logging from vja import VjaError @@ -188,7 +189,12 @@ class CommandService: task_remote = self._api_client.get_task(task_id) due_date = parse_json_date(task_remote['due_date']) if due_date: - args.update({'due': datetime_to_isoformat(due_date + timedelta)}) + now = datetime.datetime.now().replace(microsecond=0) + if due_date < now: + args.update({'due': datetime_to_isoformat(now + timedelta)}) + else: + args.update({'due': datetime_to_isoformat(due_date + timedelta)}) + old_reminders = task_remote['reminders'] if old_reminders and len(old_reminders) > 0: reminder_date = parse_json_date(old_reminders[0]['reminder']) -- GitLab From 3c027b09b996dcfc8ff650b75c565d6500a124b4 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 2 Jun 2023 13:22:54 +0200 Subject: [PATCH 46/55] feat!: remove namespaces --- Features.md | 34 ++++++++++-------- Readme.md | 13 +++++++ tests/conftest.py | 5 ++- tests/run.sh | 6 ++-- tests/test_command.py | 6 ++-- tests/test_query.py | 2 +- vja/apiclient.py | 13 +++---- vja/cli.py | 40 +++++++++++---------- vja/filter.py | 8 ++--- vja/model.py | 30 ++++------------ vja/output.py | 8 +---- vja/{list_service.py => project_service.py} | 31 ++++++++-------- vja/service_command.py | 35 +++++++++--------- vja/service_query.py | 19 +++++----- vja/task_service.py | 8 ++--- 15 files changed, 126 insertions(+), 132 deletions(-) rename vja/{list_service.py => project_service.py} (66%) diff --git a/Features.md b/Features.md index ee79b06..5666fa1 100644 --- a/Features.md +++ b/Features.md @@ -29,13 +29,13 @@ context: ```shell -vja add Getting things done --note="find out how" -priority=3 --favorite=True --due="tomorrow at 11:00" --reminder --tag=@work +vja add Getting things done --note="find out how" -priority=3 --favorite=True --due="tomorrow at 11:00" --reminder --label=@work ``` or more concise ```shell -vja add One more task -l 1 -p 4 -t "Label1" -n "my note" -d "23:00" -f True +vja add One more task -o 1 -p 4 -l "Label1" -n "my note" -d "23:00" -f True ``` See @@ -83,6 +83,8 @@ example. The displayed tasks may be filtered by several arguments like project or title, namespace and label ```shell +vja ls --project=1 +vja ls --base-project=myproject vja ls --bucket_id=1 vja ls --due-date="before today" vja ls --due-date="ge in 0 days" --due-date="before 5 days" @@ -158,10 +160,10 @@ Set new due_date and set reminder=due_date vja edit 1 --due="in 4 days at 15:00" -r ``` -Toggle tag (=label). Use with --force to create new label: +Toggle label. Use with --force to create new label: ```shell -vja edit 1 -t @work +vja edit 1 -l @work ``` Mark as done @@ -171,6 +173,14 @@ vja edit 1 --done="true" vja check 1 # Shortcut to toggle the done flag of task 1 ``` +See + +```shell +vja edit --help +``` + +for more. + ### Defer task There is a shortcut for setting a delay on a task by giving a timedelta expression. @@ -218,21 +228,13 @@ The same goes for `vja add`. ### Batch editing -Multiple edits and defers are possible by giving more task ids +Multiple edits and defers are possible by giving more task ids. Take care though, there is no confirmation request. ```shell vja edit 1 5 8 --due="next monday 14:00" vja defer 1 2 3 1d ``` -See - -```shell -vja edit --help -``` - -for more. - ## Open Vikunja in browser Open starting page @@ -249,8 +251,12 @@ vja open 42 ## Manage projects, labels, buckets +There is only a very basic support for managing entities other than tasks. I believe it is better to use the frontend. + ### Manage projects +Projects can be added and be shown but not be modified: + ```shell vja project add New Project ``` @@ -296,7 +302,7 @@ Do not use `--custom-format` if you feel uncomfortable with that. ## Terminate session -You may remove your traces by logging out. This will remove the local access token so that during subsequent execution +You may remove your traces by logging out. This will remove the local access token so that at a subsequent execution vja will prompt you again. ```shell diff --git a/Readme.md b/Readme.md index 043b63b..1a7d293 100755 --- a/Readme.md +++ b/Readme.md @@ -10,6 +10,19 @@ This is a simple CLI for Vikunja > [The todo app to organize your life.](https:/ It provides a command line interface for adding, viewing and editing todo tasks on a Vikunja Server. The goal is to support a command line based task workflow ~ similar to taskwarrior. +> #### Breaking changes in vja 2.0 +> vja 2.0 supports (and requires) the most recent Vikunja API > 0.20.4. +> In the wake of this transition the following breaking modifications to the vja command line interface have been +> introduced: +> - Labels: Are now given with `-l` (`-label`). (`-t` and `--tag` are no longer supported). +> - "Namespaces": Vikunja removed namespaces in favor of nested projects. `-n` (`--namespace`) was removed as option + from `vja ls`. +> - Projects (former "lists"): Must be given with `-o` (`--project`). `vja ls -u` may be used to filter on the project + or an upper project. This more or less resembles the old namespaces. +> +> Examples and more details can be found in the +> updated [Features.md](https://gitlab.com/ce72/vja/-/blob/main/Features.md) + ## Installation - Install from pypi: diff --git a/tests/conftest.py b/tests/conftest.py index 5474214..89e675a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -36,7 +36,10 @@ def _login_as_test_user(): def _create_project_and_task(): run_vja('vja project add test-project') - run_vja('vja add At least one task --force-create --priority=5 --due-date=today --tag=my_tag --favorite=True') + run_vja('vja project add child --parent-project-id=1') + run_vja('vja project add grand-child --parent-project-id=2') + run_vja('vja add At least one task --force-create --priority=5 --due-date=today --label=my_tag --favorite=True --project-id=1') + run_vja('vja add Task in subproject --force-create --project-id=3') run_vja('vja add A task without a label --force-create') diff --git a/tests/run.sh b/tests/run.sh index 65073b7..45bcd52 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -13,8 +13,8 @@ run-test () { vja project show 1 vja label add Next Action vja label ls - vja add "Look around" --prio=2 --tag="Next Action" --note="my note" --due="next monday at 15:00" --favorite=True --reminder="friday 12:00" - vja add "Stay at home" -p 4 -t "Next Action" -n "my note" -d "23:00" -f True --list=2 + vja add "Look around" --prio=2 --label="Next Action" --note="my note" --due="next monday at 15:00" --favorite=True --reminder="friday 12:00" + vja add "Stay at home" -p 4 -l "Next Action" -n "my note" -d "23:00" -f True --project=2 vja add Go home vja ls vja ls --project=1 @@ -32,7 +32,7 @@ run-test () { vja show 1 --jsonvja vja toggle 1 vja project show 1 --json - vja bucket ls -l 1 + vja bucket ls -o 1 vja label ls vja -v logout vja -v -u test -p test ls diff --git a/tests/test_command.py b/tests/test_command.py index 4ae78f1..6ec1c70 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -104,9 +104,9 @@ class TestEditGeneral: def test_toggle_label(self, runner): labels_0 = json_for_task_id(runner, 1)['labels'] - invoke(runner, 'edit 1 --tag=tag1 --force-create') + invoke(runner, 'edit 1 --label=tag1 --force-create') labels_1 = json_for_task_id(runner, 1)['labels'] - invoke(runner, 'edit 1 --tag=tag1') + invoke(runner, 'edit 1 --label=tag1') labels_2 = json_for_task_id(runner, 1)['labels'] assert labels_0 != labels_1 @@ -126,7 +126,7 @@ class TestEditGeneral: invoke(runner, 'project add another project') invoke(runner, 'edit 1 --project-id=1') project_1 = json_for_task_id(runner, 1)['project']['id'] - invoke(runner, 'edit 1 -l 2') + invoke(runner, 'edit 1 -o 2') project_2 = json_for_task_id(runner, 1)['project']['id'] assert project_1 == 1 diff --git a/tests/test_query.py b/tests/test_query.py index 32b9af3..e330441 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -30,7 +30,7 @@ class TestProject: def test_project_ls_custom_format(self, runner): res = invoke(runner, 'project ls --custom-format=ids_only') for line in res.output: - assert re.match(r'^\d*$', line) + assert re.match(r'^-?\d*$', line) class TestBucket: diff --git a/vja/apiclient.py b/vja/apiclient.py index 0af8bce..7f4a792 100755 --- a/vja/apiclient.py +++ b/vja/apiclient.py @@ -41,7 +41,7 @@ class ApiClient: def __init__(self, api_url, token_file): logger.debug('Connecting to api_url %s', api_url) self._api_url = api_url - self._cache = {'projects': None, 'labels': None, 'namespaces': None, 'tasks': None} + self._cache = {'projects': None, 'labels': None, 'tasks': None} self._login = Login(api_url, token_file) def _create_url(self, path): @@ -111,11 +111,6 @@ class ApiClient: def get_user(self): return self._get_json(self._create_url('/user')) - def get_namespaces(self): - if self._cache['namespaces'] is None: - self._cache['namespaces'] = self._get_json(self._create_url('/namespaces')) or [] - return self._cache['namespaces'] - def get_projects(self): if self._cache['projects'] is None: self._cache['projects'] = self._get_json(self._create_url('/projects')) or [] @@ -124,9 +119,9 @@ class ApiClient: def get_project(self, project_id): return self._get_json(self._create_url(f'/projects/{str(project_id)}')) - def put_project(self, namespace_id, title): - payload = {'title': title} - return self._put_json(self._create_url(f'/namespaces/{str(namespace_id)}/projects'), payload=payload) + def put_project(self, parent_project_id, title): + payload = {'title': title, 'parent_project_id': parent_project_id} + return self._put_json(self._create_url('/projects'), payload=payload) def get_buckets(self, project_id): return self._get_json(self._create_url(f'/projects/{str(project_id)}/buckets')) diff --git a/vja/cli.py b/vja/cli.py index 6bb3750..44b356f 100755 --- a/vja/cli.py +++ b/vja/cli.py @@ -9,8 +9,8 @@ from click_aliases import ClickAliasedGroup from vja.apiclient import ApiClient from vja.config import VjaConfiguration -from vja.list_service import ListService from vja.output import Output +from vja.project_service import ProjectService from vja.service_command import CommandService from vja.service_query import QueryService from vja.task_service import TaskService @@ -23,11 +23,11 @@ class Application: def __init__(self): self._configuration = VjaConfiguration() api_client = ApiClient(self._configuration.get_api_url(), self._configuration.get_token_file()) - list_service = ListService(api_client) + project_service = ProjectService(api_client) urgency_service = Urgency.from_config(self._configuration) - task_service = TaskService(list_service, urgency_service) - self._command_service = CommandService(list_service, task_service, api_client) - self._query_service = QueryService(list_service, task_service, api_client) + task_service = TaskService(project_service, urgency_service) + self._command_service = CommandService(project_service, task_service, api_client) + self._query_service = QueryService(project_service, task_service, api_client) self._output = Output() @property @@ -100,15 +100,16 @@ def project_group(): @project_group.command('add', help='Add project with title') -@click.option('namespace_id', '-n', '--namespace-id', help='Create project in namespace, default: first namespace found') +@click.option('parent_project_id', '-o', '--parent-project-id', '--parent_project_id', type=click.INT, + help='Create project as child of parent project id') @click.argument('title', nargs=-1, required=True) @with_application -def project_add(application, title, namespace_id=None): - project = application.command_service.add_project(namespace_id, " ".join(title)) +def project_add(application, title, parent_project_id=None): + project = application.command_service.add_project(parent_project_id, " ".join(title)) click.echo(f'Created project {project.id}') -@project_group.command('ls', help='Print projects ... (id; title; description; namespace; namespace_id)') +@project_group.command('ls', help='Print projects ... (id; title; description; parent_project_id)') @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, @@ -142,7 +143,7 @@ def bucket_group(): @bucket_group.command('ls', help='Print kanban buckets of given project ... (id; title; is_done; limit; count tasks)') -@click.option('project_id', '-l', '--list', '--project-id', '--project_id', required=True, type=click.INT, +@click.option('project_id', '-o', '--project', '--project-id', '--project_id', required=True, type=click.INT, help='Show buckets of project with id') @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @@ -191,7 +192,7 @@ def label_add(application, title): @cli.command('add', aliases=['create'], help='Add new task') @click.argument('title', required=True, nargs=-1) -@click.option('project_id', '-l', '--folder', '--project', '--list', +@click.option('project_id', '-o', '--project', '--project-id', '--project_id', help='Project (id or name), defaults to project from user settings, than to first favorite project') @click.option('note', '-n', '--note', '--description', help='Set description (note)') @@ -201,7 +202,7 @@ def label_add(application, title): help='Set due date (supports parsedatetime expressions)') @click.option('favorite', '-f', '--star', '--favorite', type=click.BOOL, help='Mark as favorite') -@click.option('tag', '-t', '--tag', '--label', +@click.option('label', '-l', '--label', help='Set label (label must exist on server)') @click.option('reminder', '-r', '--alarm', '--remind', '--reminder', is_flag=False, flag_value='due', help='Set reminder (supports parsedatetime and timedelta expressions). ' @@ -243,7 +244,7 @@ def task_clone(ctx, application, task_id, title, is_clone_bucket=False): help='Append note to existing description separated by new line') @click.option('prio', '-p', '--prio', '--priority', type=click.INT, help='Set priority') -@click.option('project_id', '-l', '--folder-id', '--project-id', '--list-id', '--project_id', type=click.INT, +@click.option('project_id', '-o', '--project', '--project-id', '--project_id', help='Move to project with id') @click.option('position', '--project-position', '--project_position', '--position', type=click.INT, help='Set project position') @@ -257,7 +258,7 @@ def task_clone(ctx, application, task_id, title, is_clone_bucket=False): help='Mark as favorite') @click.option('completed', '-c', '--completed', '--done', type=click.BOOL, help='Mark as completed') -@click.option('tag', '-t', '--tag', '--label', +@click.option('label', '-l', '--label', help='Set label (label must exist on server unless called with --force-create)') @click.option('reminder', '-r', '--alarm', '--remind', '--reminder', is_flag=False, flag_value='due', help='Set reminder (supports parsedatetime and timedelta expressions). ' @@ -302,7 +303,7 @@ def task_defer(ctx, application, task_ids, delay_by): @cli.command('ls', help='List tasks ... (task-id; priority; is_favorite; title; due_date; ' - 'has reminder; namespace; project; labels; urgency)') + 'has reminder; parent-project; project; labels; urgency)') @click.option('is_json', '--json', default=False, is_flag=True, help='Print as Vikunja json') @click.option('is_jsonvja', '--jsonvja', default=False, is_flag=True, @@ -325,12 +326,13 @@ def task_defer(ctx, application, task_ids, delay_by): help='General filter. Must be like e.g. --filter="priority ge 2" ' 'where in (eq, ne, gt, lt, ge, le, before, after, contains). ' 'Multiple occurrences of --filter are allowed and will be combined with logical AND.') -@click.option('label_filter', '-t', '--tag', '--label', +@click.option('label_filter', '-l', '--label', help='Filter by label (name or id)') -@click.option('project_filter', '-l', '--project', +@click.option('project_filter', '-o', '--project', '--project-id', '--project_id', help='Filter by project (name or id)') -@click.option('namespace_filter', '-n', '--namespace', - help='Filter by namespace (name or id)') +@click.option('upper_project_filter', '-u', '--base-project', '--base', '--upper-project', + help='Filter by base project (name or id). ' + 'All tasks whose project has the given argument as a ancestor are considered.') @click.option('priority_filter', '-p', '--prio', '--priority', help='Filter by priority. The TEXT value must be like , ' 'Shortcut for --filter="priority "') diff --git a/vja/filter.py b/vja/filter.py index 30df636..8d51456 100644 --- a/vja/filter.py +++ b/vja/filter.py @@ -69,10 +69,10 @@ def _create_project_filter(value): return _create_general_filter([f'project.title eq {value}']) -def _create_namespace_filter(value): +def _create_upper_project_filter(value): if str(value).isdigit(): - return _create_general_filter([f'project.namespace.id eq {value}']) - return _create_general_filter([f'project.namespace.title eq {value}']) + return lambda x: x.id == int(value) or any(ancestor.id == int(value) for ancestor in x.ancestor_projects) + return lambda x: x.title == value or any(ancestor.title == int(value) for ancestor in x.ancestor_projects) def _create_title_filter(value): @@ -106,7 +106,7 @@ _filter_mapping = { 'general_filter': _create_general_filter, 'label_filter': _create_label_filter, 'project_filter': _create_project_filter, - 'namespace_filter': _create_namespace_filter, + 'upper_project_filter': _create_upper_project_filter, 'title_filter': _create_title_filter, 'priority_filter': _create_priority_filter, 'urgency_filter': _create_urgency_filter, diff --git a/vja/model.py b/vja/model.py index f301692..1d27d96 100755 --- a/vja/model.py +++ b/vja/model.py @@ -58,24 +58,6 @@ class User: return cls(json, json['id'], json['username'], json['name'], json['settings']['default_project_id']) -@dataclass(frozen=True) -@data_dict -class Namespace: - json: dict = field(repr=False) - id: int - title: str - description: str - is_archived: bool - - @classmethod - def from_json(cls, json): - return cls(json, json['id'], json['title'], json['description'], json['is_archived']) - - @classmethod - def from_json_array(cls, json_array): - return [Namespace.from_json(x) for x in json_array or []] - - @dataclass(frozen=True) @data_dict class Project: @@ -85,16 +67,18 @@ class Project: description: str is_favorite: bool is_archived: bool - namespace: Namespace + parent_project_id: int + ancestor_projects: typing.List['Project'] @classmethod - def from_json(cls, json, namespace): + def from_json(cls, json, ancestor_projects): return cls(json, json['id'], json['title'], json['description'], json['is_archived'], json['is_favorite'], - namespace) + json['parent_project_id'], + ancestor_projects) @classmethod - def from_json_array(cls, json_array, namespace): - return [Project.from_json(x, namespace) for x in json_array or []] + def from_json_array(cls, json_array, ancestor_projects): + return [Project.from_json(x, ancestor_projects) for x in json_array or []] @dataclass(frozen=True) diff --git a/vja/output.py b/vja/output.py index 59c8e6a..241b510 100644 --- a/vja/output.py +++ b/vja/output.py @@ -5,10 +5,8 @@ import click from vja.model import User, Task, Project -NAMESPACE_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.description:20.20}' - PROJECT_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.description:20.20} ' \ - '{x.namespace.title:20.20} {x.namespace.id:5}' + '{x.parent_project_id:5} ' BUCKET_LIST_FORMAT_DEFAULT = '{x.id:5} {x.title:20.20} {x.is_done_bucket:2} {x.limit:3} {x.count_tasks:5}' @@ -33,10 +31,6 @@ class Output: def task(self, task: Task, is_json, is_jsonvja): self._dump(task, is_json, is_jsonvja) - def namespace_array(self, object_array, is_json, is_jsonvja, custom_format=None): - line_format = custom_format or NAMESPACE_LIST_FORMAT_DEFAULT - self._dump_array(object_array, line_format, is_json, is_jsonvja) - def project_array(self, object_array, is_json, is_jsonvja, custom_format=None): line_format = custom_format or PROJECT_LIST_FORMAT_DEFAULT self._dump_array(object_array, line_format, is_json, is_jsonvja) diff --git a/vja/list_service.py b/vja/project_service.py similarity index 66% rename from vja/list_service.py rename to vja/project_service.py index 33f23c5..a50ad99 100644 --- a/vja/list_service.py +++ b/vja/project_service.py @@ -3,26 +3,16 @@ from typing import Optional from vja import VjaError from vja.apiclient import ApiClient -from vja.model import Namespace, Project, User +from vja.model import Project, User logger = logging.getLogger(__name__) -class ListService: +class ProjectService: def __init__(self, api_client: ApiClient): self._api_client = api_client - self._namespace_by_id: Optional[dict] = None self._project_by_id: Optional[dict] = None - def find_namespace_by_id(self, namespace_id: int) -> Namespace: - if not self._namespace_by_id: - self._namespace_by_id = {x['id']: Namespace.from_json(x) for x in self._api_client.get_namespaces()} - namespace_object = self._namespace_by_id.get(namespace_id) - if not namespace_object: - logger.warning( - 'Inconsistent data: namespace_id %s is referring to non existing cached Namespace.', str(namespace_id)) - return namespace_object - def find_project_by_id(self, project_id: int) -> Project: if not self._project_by_id: self._project_by_id = {x['id']: self.convert_project_json(x) for x in self._api_client.get_projects()} @@ -53,5 +43,18 @@ class ListService: return project_found def convert_project_json(self, project_json: dict) -> Project: - namespace = self.find_namespace_by_id(project_json['namespace_id']) - return Project.from_json(project_json, namespace) + ancestor_projects = [] + # project_id = project_json['id'] + # parent_project_id = project_json['parent_project_id'] + # if parent_project_id != id find parent and add it to the ancestors and proceed with parent the same way + # ancestor = self.get_ancestor_project(project_id, parent_project_id) + # while ancestor: + # ancestor_projects.append(ancestor) + # ancestor = self.get_ancestor_project(ancestor.id, ancestor.parent_project_id) + return Project.from_json(project_json, ancestor_projects) + + def get_ancestor_project(self, project_id, parent_project_id) -> Optional[Project]: + if project_id == parent_project_id or parent_project_id == 0 or project_id == 0: + return None + ancestor = self.find_project_by_id(parent_project_id) + return ancestor diff --git a/vja/service_command.py b/vja/service_command.py index 2850f20..810099e 100644 --- a/vja/service_command.py +++ b/vja/service_command.py @@ -3,17 +3,17 @@ import logging from vja import VjaError from vja.apiclient import ApiClient -from vja.list_service import ListService from vja.model import Label from vja.parse import parse_date_arg_to_iso, parse_json_date, parse_date_arg_to_timedelta, datetime_to_isoformat +from vja.project_service import ProjectService from vja.task_service import TaskService logger = logging.getLogger(__name__) class CommandService: - def __init__(self, list_service: ListService, task_service: TaskService, api_client: ApiClient): - self._list_service = list_service + def __init__(self, project_service: ProjectService, task_service: TaskService, api_client: ApiClient): + self._project_service = project_service self._task_service = task_service self._api_client = api_client @@ -25,12 +25,9 @@ class CommandService: logger.info('Logged out') # project - def add_project(self, namespace_id, title): - if not namespace_id: - namespaces = self._api_client.get_namespaces() - namespace_id = min(namespace['id'] if namespace['id'] > 0 else 99999 for namespace in namespaces) - project_json = self._api_client.put_project(namespace_id, title) - return self._list_service.convert_project_json(project_json) + def add_project(self, parent_project_id, title): + project_json = self._api_client.put_project(parent_project_id, title) + return self._project_service.convert_project_json(project_json) # label def add_label(self, title): @@ -65,10 +62,10 @@ class CommandService: if str(project_arg).isdigit(): project_id = project_arg else: - project_id = self._list_service.find_project_by_title(project_arg).id + project_id = self._project_service.find_project_by_title(project_arg).id else: - project_id = self._list_service.get_default_project().id - tag_name = args.pop('tag') if args.get('tag') else None + project_id = self._project_service.get_default_project().id + label_name = args.pop('label') if args.get('label') else None is_force = args.pop('force_create') if args.get('force_create') is not None else False self._parse_reminder_arg(args.get('reminder'), args) @@ -76,12 +73,12 @@ class CommandService: payload = self._args_to_payload(args) if not is_force: - self._validate_add_task(title, tag_name) + self._validate_add_task(title, label_name) logger.debug('put task: %s', payload) task_json = self._api_client.put_task(project_id, payload) task = self._task_service.task_from_json(task_json) - label = self._label_from_name(tag_name, is_force) if tag_name else None + label = self._label_from_name(label_name, is_force) if label_name else None if label: self._api_client.add_label_to_task(task.id, label.id) return task @@ -107,7 +104,7 @@ class CommandService: def edit_task(self, task_id: int, args: dict): task_remote = self._api_client.get_task(task_id) - tag_name = args.pop('tag') if args.get('tag') else None + label_name = args.pop('label') if args.get('label') else None is_force = args.pop('force_create') if args.get('force_create') is not None else False self._update_reminder(args, task_remote) @@ -126,7 +123,7 @@ class CommandService: task_json = self._api_client.post_task(task_id, task_remote) task_new = self._task_service.task_from_json(task_json) - label = self._label_from_name(tag_name, is_force) if tag_name else None + label = self._label_from_name(label_name, is_force) if label_name else None if label: if task_new.has_label(label): self._api_client.remove_label_from_task(task_new.id, label.id) @@ -223,12 +220,12 @@ class CommandService: return None return label_found[0] - def _validate_add_task(self, title, tag_name): + def _validate_add_task(self, title, label_name): tasks_remote = self._api_client.get_tasks(exclude_completed=True) if any(task for task in tasks_remote if task['title'] == title): raise VjaError("Task with title does exist. You may want to run with --force-create.") - if tag_name: + if label_name: labels_remote = Label.from_json_array(self._api_client.get_labels()) - if not any(label for label in labels_remote if label.title == tag_name): + if not any(label for label in labels_remote if label.title == label_name): raise VjaError( "Label does not exist. You may want to execute \"label add\" or run with --force-create.") diff --git a/vja/service_query.py b/vja/service_query.py index c0a5e4a..ac19243 100644 --- a/vja/service_query.py +++ b/vja/service_query.py @@ -2,9 +2,9 @@ import logging from vja.apiclient import ApiClient from vja.filter import create_filters -from vja.list_service import ListService -from vja.model import Namespace, Label, User, Bucket +from vja.model import Label, User, Bucket from vja.parse import rgetattr +from vja.project_service import ProjectService from vja.task_service import TaskService logger = logging.getLogger(__name__) @@ -12,8 +12,8 @@ DEFAULT_SORT_STRING = 'done, -urgency, due_date, -priority, project.title, title class QueryService: - def __init__(self, list_service: ListService, task_service: TaskService, api_client: ApiClient): - self._list_service = list_service + def __init__(self, project_service: ProjectService, task_service: TaskService, api_client: ApiClient): + self._project_service = project_service self._task_service = task_service self._api_client = api_client @@ -21,16 +21,13 @@ class QueryService: def find_current_user(self): return User.from_json(self._api_client.get_user()) - # namespace - def find_all_namespaces(self): - return Namespace.from_json_array(self._api_client.get_namespaces()) - # project def find_all_projects(self): - return [self._list_service.convert_project_json(project_json) for project_json in (self._api_client.get_projects())] + return [self._project_service.convert_project_json(project_json) for project_json in + (self._api_client.get_projects())] def find_project_by_id(self, project_id): - return self._list_service.convert_project_json(self._api_client.get_project(project_id)) + return self._project_service.convert_project_json(self._api_client.get_project(project_id)) # bucket def find_all_buckets_in_project(self, project_id): @@ -71,7 +68,7 @@ class QueryService: def sortable_task_value(task, field): field_name = field - if field in ('label', 'labels', 'tag', 'tags'): + if field in ('label', 'labels'): field_name = 'label_titles' field_value = rgetattr(task, field_name) if isinstance(field_value, str): diff --git a/vja/task_service.py b/vja/task_service.py index 83024fa..5586214 100644 --- a/vja/task_service.py +++ b/vja/task_service.py @@ -1,19 +1,19 @@ import logging -from vja.list_service import ListService from vja.model import Task, Label +from vja.project_service import ProjectService from vja.urgency import Urgency logger = logging.getLogger(__name__) class TaskService: - def __init__(self, list_service: ListService, urgency: Urgency): - self._list_service = list_service + def __init__(self, project_service: ProjectService, urgency: Urgency): + self._project_service = project_service self._urgency = urgency def task_from_json(self, task_json: dict) -> Task: - project_object = self._list_service.find_project_by_id(task_json['project_id']) + project_object = self._project_service.find_project_by_id(task_json['project_id']) labels = Label.from_json_array(task_json['labels']) task = Task.from_json(task_json, project_object, labels) task.urgency = self._urgency.compute_for(task) -- GitLab From 8fa7747305cff1e22934dc260534deda890d8c54 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 Jun 2023 11:28:40 +0000 Subject: [PATCH 47/55] chore(release): Release 2.0.0-beta.1 update changelog [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) ### ⚠ BREAKING CHANGES * remove namespaces * **api:** remove reminder_dates * **api:** New projects api (only backend side) * Preliminary support for new reminder array ### Features * **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) * **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) * **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) * defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) * **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) * fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) * Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) * **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) * remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) * rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) * Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) ### Bug Fixes * **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) * **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) * **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) * do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) * sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) ### Misc * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) * **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) * **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) * **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) * Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) ### Documentation * Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) * describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) * **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) ### Automation * automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) * automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) * automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) * automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) * capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) * cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) * cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) * cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) * cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) * cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) * install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) * pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) * pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) * remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) * remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) * remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) * remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) * remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) * remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) * remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) * update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) * wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) --- CHANGELOG.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 869a51f..1cb0f0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,78 @@ +## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) + + +### ⚠ BREAKING CHANGES + +* remove namespaces +* **api:** remove reminder_dates +* **api:** New projects api (only backend side) +* Preliminary support for new reminder array + +### Features + +* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) +* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) +* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) +* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) +* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) +* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) +* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) +* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) +* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) +* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) +* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) + + +### Bug Fixes + +* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) +* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) +* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) +* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) +* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) + + +### Misc + +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) +* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) +* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) +* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) +* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) + + +### Documentation + +* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) +* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) +* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) + + +### Automation + +* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) +* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) +* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) +* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) +* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) +* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) +* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) +* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) +* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) +* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) +* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) +* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) +* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) +* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) +* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) +* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) +* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) +* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) +* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) +* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) +* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) +* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) + ## [2.0.0-beta.4](https://gitlab.com/ce72/vja/compare/2.0.0-beta.3...2.0.0-beta.4) (2023-04-24) diff --git a/setup.cfg b/setup.cfg index 418868a..c8a9fe3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b4 +version = 2.0.0b1 -- GitLab From cc346c7aea5b2486a79be2f142801c209adf82d7 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 2 Jun 2023 13:33:31 +0200 Subject: [PATCH 48/55] ci: fix version number --- CHANGELOG.md | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cb0f0c..849e362 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) +## [2.0.0-beta.5](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) ### ⚠ BREAKING CHANGES diff --git a/setup.cfg b/setup.cfg index c8a9fe3..a5ae36b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b1 +version = 2.0.0b5 -- GitLab From 8745e3a9374a5185c1fd884411ae2e338e77720d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 Jun 2023 11:37:13 +0000 Subject: [PATCH 49/55] chore(release): Release 2.0.0-beta.1 update changelog [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) ### ⚠ BREAKING CHANGES * remove namespaces * **api:** remove reminder_dates * **api:** New projects api (only backend side) * Preliminary support for new reminder array ### Features * **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) * **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) * **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) * defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) * **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) * fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) * Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) * **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) * remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) * rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) * Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) ### Bug Fixes * **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) * **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) * **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) * do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) * sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) ### Documentation * Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) * describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) * **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) ### Misc * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) * **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) * **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) * **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) * Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) ### Automation * automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) * automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) * automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) * automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) * capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) * cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) * cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) * cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) * cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) * cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) * fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) * install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) * pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) * pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) * remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) * remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) * remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) * remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) * remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) * remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) * remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) * update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) * wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) --- CHANGELOG.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 849e362..632b25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,80 @@ +## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) + + +### ⚠ BREAKING CHANGES + +* remove namespaces +* **api:** remove reminder_dates +* **api:** New projects api (only backend side) +* Preliminary support for new reminder array + +### Features + +* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) +* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) +* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) +* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) +* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) +* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) +* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) +* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) +* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) +* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) +* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) + + +### Bug Fixes + +* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) +* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) +* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) +* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) +* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) + + +### Documentation + +* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) +* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) +* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) + + +### Misc + +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) +* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) +* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) +* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) +* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) + + +### Automation + +* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) +* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) +* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) +* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) +* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) +* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) +* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) +* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) +* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) +* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) +* fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) +* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) +* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) +* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) +* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) +* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) +* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) +* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) +* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) +* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) +* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) +* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) +* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) + ## [2.0.0-beta.5](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) diff --git a/setup.cfg b/setup.cfg index a5ae36b..c8a9fe3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b5 +version = 2.0.0b1 -- GitLab From 4518c3fa5343762c2eaaa05ab2e60c61294b9b6a Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 2 Jun 2023 13:39:45 +0200 Subject: [PATCH 50/55] ci: fix version number --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index c8a9fe3..22b1249 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b1 +version = 2.0.1b1 -- GitLab From a96579c02a01f66008283e4178aa2a389e1d7da1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 Jun 2023 11:42:52 +0000 Subject: [PATCH 51/55] chore(release): Release 2.0.0-beta.1 update changelog [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) ### ⚠ BREAKING CHANGES * remove namespaces * **api:** remove reminder_dates * **api:** New projects api (only backend side) * Preliminary support for new reminder array ### Features * **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) * **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) * **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) * defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) * **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) * fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) * Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) * **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) * remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) * rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) * Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) ### Bug Fixes * **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) * **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) * **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) * do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) * sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) ### Documentation * Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) * describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) * **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) ### Misc * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8745e3a](https://gitlab.com/ce72/vja/commit/8745e3a9374a5185c1fd884411ae2e338e77720d)) * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) * **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) * **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) * **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) * Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) ### Automation * automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) * automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) * automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) * automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) * capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) * cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) * cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) * cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) * cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) * cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) * fix version number ([4518c3f](https://gitlab.com/ce72/vja/commit/4518c3fa5343762c2eaaa05ab2e60c61294b9b6a)) * fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) * install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) * pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) * pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) * remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) * remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) * remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) * remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) * remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) * remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) * remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) * update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) * wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) --- CHANGELOG.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 632b25b..98c8d18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,85 @@ * **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) +### Misc + +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8745e3a](https://gitlab.com/ce72/vja/commit/8745e3a9374a5185c1fd884411ae2e338e77720d)) +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) +* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) +* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) +* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) +* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) + + +### Automation + +* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) +* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) +* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) +* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) +* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) +* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) +* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) +* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) +* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) +* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) +* fix version number ([4518c3f](https://gitlab.com/ce72/vja/commit/4518c3fa5343762c2eaaa05ab2e60c61294b9b6a)) +* fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) +* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) +* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) +* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) +* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) +* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) +* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) +* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) +* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) +* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) +* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) +* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) +* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) + +## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) + + +### ⚠ BREAKING CHANGES + +* remove namespaces +* **api:** remove reminder_dates +* **api:** New projects api (only backend side) +* Preliminary support for new reminder array + +### Features + +* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) +* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) +* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) +* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) +* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) +* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) +* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) +* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) +* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) +* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) +* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) + + +### Bug Fixes + +* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) +* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) +* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) +* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) +* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) + + +### Documentation + +* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) +* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) +* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) + + ### Misc * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) diff --git a/setup.cfg b/setup.cfg index 22b1249..c8a9fe3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.1b1 +version = 2.0.0b1 -- GitLab From a985a5e28f2b1212a4a4f48aa41eadb0dacebcd3 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 2 Jun 2023 13:55:35 +0200 Subject: [PATCH 52/55] ci: fix version number --- CHANGELOG.md | 231 --------------------------------------------------- setup.cfg | 2 +- 2 files changed, 1 insertion(+), 232 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98c8d18..869a51f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,234 +1,3 @@ -## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) - - -### ⚠ BREAKING CHANGES - -* remove namespaces -* **api:** remove reminder_dates -* **api:** New projects api (only backend side) -* Preliminary support for new reminder array - -### Features - -* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) -* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) -* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) -* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) -* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) -* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) -* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) -* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) -* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) -* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) -* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) - - -### Bug Fixes - -* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) -* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) -* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) -* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) -* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) - - -### Documentation - -* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) -* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) -* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) - - -### Misc - -* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8745e3a](https://gitlab.com/ce72/vja/commit/8745e3a9374a5185c1fd884411ae2e338e77720d)) -* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) -* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) -* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) -* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) -* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) -* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) - - -### Automation - -* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) -* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) -* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) -* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) -* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) -* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) -* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) -* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) -* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) -* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) -* fix version number ([4518c3f](https://gitlab.com/ce72/vja/commit/4518c3fa5343762c2eaaa05ab2e60c61294b9b6a)) -* fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) -* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) -* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) -* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) -* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) -* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) -* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) -* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) -* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) -* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) -* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) -* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) -* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) - -## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) - - -### ⚠ BREAKING CHANGES - -* remove namespaces -* **api:** remove reminder_dates -* **api:** New projects api (only backend side) -* Preliminary support for new reminder array - -### Features - -* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) -* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) -* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) -* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) -* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) -* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) -* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) -* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) -* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) -* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) -* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) - - -### Bug Fixes - -* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) -* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) -* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) -* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) -* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) - - -### Documentation - -* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) -* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) -* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) - - -### Misc - -* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) -* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) -* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) -* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) -* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) -* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) - - -### Automation - -* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) -* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) -* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) -* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) -* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) -* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) -* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) -* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) -* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) -* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) -* fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) -* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) -* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) -* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) -* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) -* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) -* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) -* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) -* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) -* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) -* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) -* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) -* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) - -## [2.0.0-beta.5](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) - - -### ⚠ BREAKING CHANGES - -* remove namespaces -* **api:** remove reminder_dates -* **api:** New projects api (only backend side) -* Preliminary support for new reminder array - -### Features - -* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) -* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) -* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) -* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) -* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) -* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) -* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) -* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) -* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) -* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) -* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) - - -### Bug Fixes - -* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) -* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) -* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) -* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) -* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) - - -### Misc - -* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) -* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) -* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) -* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) -* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) - - -### Documentation - -* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) -* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) -* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) - - -### Automation - -* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) -* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) -* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) -* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) -* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) -* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) -* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) -* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) -* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) -* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) -* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) -* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) -* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) -* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) -* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) -* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) -* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) -* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) -* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) -* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) -* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) -* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) - ## [2.0.0-beta.4](https://gitlab.com/ce72/vja/compare/2.0.0-beta.3...2.0.0-beta.4) (2023-04-24) diff --git a/setup.cfg b/setup.cfg index c8a9fe3..418868a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b1 +version = 2.0.0b4 -- GitLab From 5f35c3a2bced9bd44b4b8528295b6f5f23b4a467 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Fri, 2 Jun 2023 12:04:41 +0000 Subject: [PATCH 53/55] chore(release): Release 2.0.0-beta.1 update changelog [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) ### ⚠ BREAKING CHANGES * remove namespaces * **api:** remove reminder_dates * **api:** New projects api (only backend side) * Preliminary support for new reminder array ### Features * **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) * **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) * **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) * defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) * **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) * fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) * Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) * **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) * remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) * rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) * Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) ### Bug Fixes * **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) * **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) * **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) * do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) * sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) ### Documentation * Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) * describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) * **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) ### Misc * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([a96579c](https://gitlab.com/ce72/vja/commit/a96579c02a01f66008283e4178aa2a389e1d7da1)) * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8745e3a](https://gitlab.com/ce72/vja/commit/8745e3a9374a5185c1fd884411ae2e338e77720d)) * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) * **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) * **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) * **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) * **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) * Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) ### Automation * automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) * automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) * automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) * automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) * capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) * cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) * cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) * cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) * cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) * cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) * fix version number ([a985a5e](https://gitlab.com/ce72/vja/commit/a985a5e28f2b1212a4a4f48aa41eadb0dacebcd3)) * fix version number ([4518c3f](https://gitlab.com/ce72/vja/commit/4518c3fa5343762c2eaaa05ab2e60c61294b9b6a)) * fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) * install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) * pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) * pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) * remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) * remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) * remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) * remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) * remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) * remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) * remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) * update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) * wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) --- CHANGELOG.md | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 869a51f..2b15d24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,84 @@ +## [2.0.0-beta.1](https://gitlab.com/ce72/vja/compare/1.5.1...2.0.0-beta.1) (2023-06-02) + + +### ⚠ BREAKING CHANGES + +* remove namespaces +* **api:** remove reminder_dates +* **api:** New projects api (only backend side) +* Preliminary support for new reminder array + +### Features + +* **api:** New projects api (only backend side) ([b1df704](https://gitlab.com/ce72/vja/commit/b1df70496a070b827c7431c68181d4ec18aa5190)) +* **api:** remove reminder_dates ([6f18cff](https://gitlab.com/ce72/vja/commit/6f18cff9ffae2e95dafd9c936400b5e216b44008)) +* **cli:** alias --urgent for --urgency ([3701ab2](https://gitlab.com/ce72/vja/commit/3701ab25ddeebc7f07959c0ac2bdca9833b5d15f)) +* defer reminder ([aec5f53](https://gitlab.com/ce72/vja/commit/aec5f53ed530a3e1a486b7cad56a9c1613ae100a)) +* **defer task:** defer passed due date relative to now ([f6a70e5](https://gitlab.com/ce72/vja/commit/f6a70e58506104f5c0fd6eb421baf9017f31feb9)) +* fetch long_token when logging in (with a ttl of 30 days) ([1e8a7b8](https://gitlab.com/ce72/vja/commit/1e8a7b86ae4781b812909132d1574380965e99d3)) +* Preliminary support for new reminder array ([fe2c332](https://gitlab.com/ce72/vja/commit/fe2c33281206fcf4e121875164ab36ea78369987)) +* **reminders:** Set relative reminders like "1h before due" ([18534b4](https://gitlab.com/ce72/vja/commit/18534b4921a04e603ad4003a4a3f3ad9196de10c)) +* remove namespaces ([3c027b0](https://gitlab.com/ce72/vja/commit/3c027b09b996dcfc8ff650b75c565d6500a124b4)) +* rename lists to project within vja ([54b0b0a](https://gitlab.com/ce72/vja/commit/54b0b0a46cfaaa20236fe79580a9a28909056d7c)) +* Support for new reminder array (read) ([5caff10](https://gitlab.com/ce72/vja/commit/5caff109bf444087ec83f8f6e3257d5ffddefaa1)) + + +### Bug Fixes + +* **clone:** clone labels too ([0516908](https://gitlab.com/ce72/vja/commit/05169086c09ff4b77d597799defff00b01f4b591)) +* **clone:** do not clone positions and have --bucket ([15fac96](https://gitlab.com/ce72/vja/commit/15fac96ec4f34fbde4906eef925646fef8ba0d6e)) +* **clone:** do not clone positions and have --bucket ([9e0a9aa](https://gitlab.com/ce72/vja/commit/9e0a9aa8ce9e8d6b845063888c22ece7f40b1028)) +* do not unset reminder if missing in vja edit ([7b8c922](https://gitlab.com/ce72/vja/commit/7b8c922acaf726060c9de5ad574da585bc8e2e9a)) +* sharpen test ([c5dbf43](https://gitlab.com/ce72/vja/commit/c5dbf43d582b244f8b17787ed12a06d160a20856)) + + +### Documentation + +* Add table of contents to Features.md ([e394ca5](https://gitlab.com/ce72/vja/commit/e394ca5e3959a77e1a8bb39285f4dc348d997cbd)) +* describe env variable VJA_CONFIGDIR ([ef0c2bd](https://gitlab.com/ce72/vja/commit/ef0c2bd9b6b38414a091787c3d641cc9e9799f9a)) +* **filters:** improve documentation (and tests) ([2c2b967](https://gitlab.com/ce72/vja/commit/2c2b967f736055f6ab65a3ef7f03c05cc6798344)) + + +### Misc + +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([a96579c](https://gitlab.com/ce72/vja/commit/a96579c02a01f66008283e4178aa2a389e1d7da1)) +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8745e3a](https://gitlab.com/ce72/vja/commit/8745e3a9374a5185c1fd884411ae2e338e77720d)) +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([8fa7747](https://gitlab.com/ce72/vja/commit/8fa7747305cff1e22934dc260534deda890d8c54)) +* **release:** Release 2.0.0-beta.1 update changelog [skip ci] ([9d27ea2](https://gitlab.com/ce72/vja/commit/9d27ea2639c0ffec7582199f004508006479385e)) +* **release:** Release 2.0.0-beta.2 update changelog [skip ci] ([ed78554](https://gitlab.com/ce72/vja/commit/ed78554db8f5adaec000fca4358d709755ee20a5)) +* **release:** Release 2.0.0-beta.3 update changelog [skip ci] ([1d10ce6](https://gitlab.com/ce72/vja/commit/1d10ce675ab4dd4305196e7048261b018c4dd9f7)) +* **release:** Release 2.0.0-beta.4 update changelog [skip ci] ([65b7fbe](https://gitlab.com/ce72/vja/commit/65b7fbe811cd2d2e3ab78cdc54e8f7c0980731f8)) +* Remove redundant test ([719943a](https://gitlab.com/ce72/vja/commit/719943a9d1b77a7663d87abac602f8d869c246b1)) + + +### Automation + +* automate beta releases ([a325254](https://gitlab.com/ce72/vja/commit/a32525446577421f95b51cb578390d2c72d114c3)) +* automate beta releases ([a3fed80](https://gitlab.com/ce72/vja/commit/a3fed80753d817a8026d1ac8eb65291576c5a10f)) +* automate beta releases ([f2dc40a](https://gitlab.com/ce72/vja/commit/f2dc40ae6d731b96946c999f3f9d639b38f2b601)) +* automate beta releases ([c57f4bc](https://gitlab.com/ce72/vja/commit/c57f4bcd40fcbad44b1d364884864bf764b012e9)) +* capture click output ([727c282](https://gitlab.com/ce72/vja/commit/727c2823f2adab62e4e91835ed39219f2b274fe2)) +* cleanup gitlab-ci ([cb6f743](https://gitlab.com/ce72/vja/commit/cb6f743f14ab85afd8059c8c9f4baa68e492b215)) +* cleanup gitlab-ci ([cab2530](https://gitlab.com/ce72/vja/commit/cab2530d7bdfe9261acf9ae4f30d304e8279b6aa)) +* cleanup gitlab-ci ([0716eb9](https://gitlab.com/ce72/vja/commit/0716eb94ebd32ebe4c6fbea7b75f35d66d9e2439)) +* cleanup gitlab-ci ([017cf44](https://gitlab.com/ce72/vja/commit/017cf444633a7f800c6f8d1960ea84e093a79c65)) +* cleanup test setup ([c8a3872](https://gitlab.com/ce72/vja/commit/c8a387244ee86728241970d86e8b59d259a90c40)) +* fix version number ([a985a5e](https://gitlab.com/ce72/vja/commit/a985a5e28f2b1212a4a4f48aa41eadb0dacebcd3)) +* fix version number ([4518c3f](https://gitlab.com/ce72/vja/commit/4518c3fa5343762c2eaaa05ab2e60c61294b9b6a)) +* fix version number ([cc346c7](https://gitlab.com/ce72/vja/commit/cc346c7aea5b2486a79be2f142801c209adf82d7)) +* install coverage from requirements_dev.txt ([9b03ba1](https://gitlab.com/ce72/vja/commit/9b03ba180ceb1a9d8125a4713a5e2799777e4e36)) +* pipeline on branches only manual ([9b05c2d](https://gitlab.com/ce72/vja/commit/9b05c2ddaf778f179a7ddd16a56fa1d5d9b5b5fc)) +* pipeline on branches only manual ([3a936d9](https://gitlab.com/ce72/vja/commit/3a936d9a0425ca3c6c87c61b526e87b7474398c3)) +* remove build stage ([8e4f36c](https://gitlab.com/ce72/vja/commit/8e4f36cee4ebaff4fcf3c703e6e1b265d955d302)) +* remove build stage ([e4858e3](https://gitlab.com/ce72/vja/commit/e4858e363aed6369ef29ef0fe3ed56115083a11b)) +* remove build stage ([e27df75](https://gitlab.com/ce72/vja/commit/e27df75b220380148aab79e75af0e5194041d381)) +* remove build stage ([49d2fe2](https://gitlab.com/ce72/vja/commit/49d2fe2d4261fa993aa06365fd004876d8fff055)) +* remove build stage ([1661721](https://gitlab.com/ce72/vja/commit/166172141e63f3ef22c576196aacaf7de5bea227)) +* remove redundant apk packages ([bf6c0ea](https://gitlab.com/ce72/vja/commit/bf6c0eae179929555ecba1315d19683f052a046e)) +* remove redundant apk packages ([a34a24d](https://gitlab.com/ce72/vja/commit/a34a24d396bb508d4635bc1cb405d3ab9d6bbdc7)) +* update semantic-release configuration ([de4df86](https://gitlab.com/ce72/vja/commit/de4df867ec80fbead7e8831edbc8d38fd46e0a76)) +* wait for running api container ([60d6915](https://gitlab.com/ce72/vja/commit/60d6915845050c5b5b8e528feea69a42f8bbe5d3)) + ## [2.0.0-beta.4](https://gitlab.com/ce72/vja/compare/2.0.0-beta.3...2.0.0-beta.4) (2023-04-24) diff --git a/setup.cfg b/setup.cfg index 418868a..c8a9fe3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,3 @@ [metadata] -version = 2.0.0b4 +version = 2.0.0b1 -- GitLab From a28e5fca97294351b30e64857a4580164927d895 Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 2 Jun 2023 19:25:38 +0200 Subject: [PATCH 54/55] test: add --due-date with/without time --- tests/test_command.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/test_command.py b/tests/test_command.py index 6ec1c70..5aee06c 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -10,7 +10,8 @@ TODAY = datetime.datetime.now().replace(microsecond=0) TODAY_ISO = TODAY.isoformat() YESTERDAY = TODAY + datetime.timedelta(days=-1) YESTERDAY_ISO = YESTERDAY.isoformat() -TOMORROW_ISO = (TODAY + datetime.timedelta(days=1)).isoformat() +TOMORROW = TODAY + datetime.timedelta(days=1) +TOMORROW_ISO = TOMORROW.isoformat() DATE_1 = TODAY + datetime.timedelta(days=10) DATE_2 = DATE_1 + datetime.timedelta(days=1) DATE_1_ISO = DATE_1.isoformat() @@ -70,8 +71,7 @@ class TestEditGeneral: def test_edit_title(self, runner): before = json_for_task_id(runner, 1) new_title = f'{before["title"]}42' - res = runner.invoke(cli, ['edit', '1', '-i', f'{new_title}']) - assert res.exit_code == 0, res + invoke(runner, ['edit', '1', '-i', f'{new_title}']) after = json_for_task_id(runner, 1) assert after['title'] == new_title @@ -83,14 +83,19 @@ class TestEditGeneral: assert after['project']['id'] == before['project']['id'] assert after['created'] == before['created'] - def test_edit_due_date(self, runner): - before = json_for_task_id(runner, 1) + def test_edit_due_date_without_time(self, runner): + + invoke(runner, 'edit 1 --due=tomorrow') + + after = json_for_task_id(runner, 1) + assert after['due_date'] == (TOMORROW.replace(hour=0, minute=0, second=0)).isoformat() + + def test_edit_due_date_with_time(self, runner): - invoke(runner, 'edit 1 --due=today') + invoke(runner, ['edit', '1', '--due=tomorrow 15:00']) after = json_for_task_id(runner, 1) - assert after['due_date'][:10] == TODAY_ISO[:10] - assert after['updated'] >= before['updated'] + assert after['due_date'] == (TOMORROW.replace(hour=15, minute=0, second=0)).isoformat() def test_unset_due_date(self, runner): before = json_for_task_id(runner, 1) @@ -100,7 +105,6 @@ class TestEditGeneral: after = json_for_task_id(runner, 1) assert after['due_date'] is None - assert after['updated'] >= before['updated'] def test_toggle_label(self, runner): labels_0 = json_for_task_id(runner, 1)['labels'] -- GitLab From 7607fa853fbdfbbbffec4c0a3e73e16c3f69fdfb Mon Sep 17 00:00:00 2001 From: cernst72 Date: Fri, 2 Jun 2023 19:38:47 +0200 Subject: [PATCH 55/55] ci: add rc as prerelase branch name --- .releaserc.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.releaserc.yml b/.releaserc.yml index d72169d..cb441b8 100644 --- a/.releaserc.yml +++ b/.releaserc.yml @@ -2,6 +2,7 @@ tagFormat: "${version}" branches: - main - { name: beta, prerelease: true } + - { name: rc, prerelease: true } plugins: - - "@semantic-release/commit-analyzer" -- GitLab