diff --git a/regolith/helpers/a_todohelper.py b/regolith/helpers/a_todohelper.py index 36636acfe..5008d86ec 100644 --- a/regolith/helpers/a_todohelper.py +++ b/regolith/helpers/a_todohelper.py @@ -47,7 +47,7 @@ def subparser(subpi): help=f"The importance of the task. " f"Corresponds roughly to (3) tt, (2) tf, (1) ft, (0) ff in the Eisenhower matrix of " f"importance vs. urgency. An important and urgent task would be 3.", - default=1 + default=None ) subpi.add_argument("-t", "--tags", nargs="+", help="Tags to be associated with this task. Enter as single words separated by spaces. " @@ -144,7 +144,12 @@ def db_updater(self): due_date = date_parser.parse(rc.due_date).date() if begin_date > due_date: raise ValueError("begin_date can not be after due_date") - if rc.importance not in ALLOWED_IMPORTANCE: + if rc.importance is None: + if rc.milestone_uuid: + importance = 2 + else: + importance = 1 + elif rc.importance not in ALLOWED_IMPORTANCE: raise ValueError( f"importance should be chosen from {ALLOWED_IMPORTANCE}") else: diff --git a/regolith/helpers/l_milestoneshelper.py b/regolith/helpers/l_milestoneshelper.py index 8894131ab..64acc3a70 100644 --- a/regolith/helpers/l_milestoneshelper.py +++ b/regolith/helpers/l_milestoneshelper.py @@ -3,18 +3,22 @@ Projecta are small bite-sized project quanta that typically will result in one manuscript. """ +import datetime as dt +import dateutil.parser as date_parser from regolith.dates import get_due_date from regolith.helpers.basehelper import SoutHelperBase from regolith.fsclient import _id_key +from regolith.helpers.l_todohelper import _format_todos from regolith.tools import ( all_docs_from_collection, get_pi_id, key_value_pair_filter, - collection_str + collection_str, get_task, print_task ) from regolith.schemas import PROJECTUM_STATI, PROJECTUM_PAUSED_STATI, \ - PROJECTUM_CANCELLED_STATI, PROJECTUM_FINISHED_STATI, PROJECTUM_ACTIVE_STATI + PROJECTUM_CANCELLED_STATI, PROJECTUM_FINISHED_STATI, \ + PROJECTUM_ACTIVE_STATI, TODO_STATI from gooey import GooeyParser TARGET_COLL = "projecta" @@ -26,8 +30,11 @@ def subparser(subpi): listbox_kwargs = {} + date_kwargs = {} if isinstance(subpi, GooeyParser): - listbox_kwargs['widget'] = 'Listbox' + listbox_kwargs['widget'] = 'Listbox', + date_kwargs['widget'] = 'DateChooser' + subpi.add_argument('--helper-help', action="store_true", help=f'This helper will list all ACTIVE milestones by default. To ' @@ -68,6 +75,9 @@ def subparser(subpi): ) subpi.add_argument("--all", action="store_true", help="Lists all milestones in general") + subpi.add_argument("--date", + help="Enter a date such that the helper can calculate how many days are left from that date to the due-date. Default is today.", + **date_kwargs) # The --filter and --keys flags should be in every lister subpi.add_argument("-f", "--filter", nargs="+", help="Search this collection by giving key element pairs" @@ -85,7 +95,7 @@ class MilestonesListerHelper(SoutHelperBase): """ # btype must be the same as helper target in helper.py btype = HELPER_TARGET - needed_colls = [f'{TARGET_COLL}'] + needed_colls = [f'{TARGET_COLL}', "todos"] def construct_global_ctx(self): """Constructs the global context""" @@ -115,6 +125,11 @@ def sout(self): collection = key_value_pair_filter(self.gtx["projecta"], rc.filter) else: collection = self.gtx["projecta"] + if not rc.date: + today = dt.date.today() + else: + today = date_parser.parse(rc.date).date() + if (not rc.lead) and (not rc.verbose) and (not rc.stati) and ( not rc.current) and (not rc.person) and (not rc.all): @@ -217,6 +232,11 @@ def sout(self): print(f" Notes:") for note in ms.get("notes"): print(f" - {note}") + if ms.get("tasks"): + print(f" Tasks:") + tasks = [_format_todos(get_task(self.gtx['todos'], task_id), today) for task_id in ms.get("tasks")] + tasks.sort(key='due_date') + print_task(tasks, TODO_STATI) print(f" uuid: {ms.get('uuid')}") else: print( diff --git a/regolith/helpers/u_finishprumhelper.py b/regolith/helpers/u_finishprumhelper.py index 8a26bc634..5eb9f65cb 100644 --- a/regolith/helpers/u_finishprumhelper.py +++ b/regolith/helpers/u_finishprumhelper.py @@ -56,7 +56,7 @@ def construct_global_ctx(self): def db_updater(self): rc = self.rc - key = rc.projectum_id + key = rc.projectum_id.strip() filterid = {'_id': key} found_projectum = rc.client.find_one(rc.database, rc.coll, filterid) if not found_projectum: diff --git a/regolith/schemas.py b/regolith/schemas.py index 22f2e39be..b31df59c5 100644 --- a/regolith/schemas.py +++ b/regolith/schemas.py @@ -2090,6 +2090,18 @@ "running_index": 1, "tags": ["reading", "downtime"] }, + {"description": "added todo", + "uuid": "test-uuid", + "due_date": "2020-07-20", + "begin_date": "2020-06-15", + "deadline": True, + "duration": 60.0, + "importance": 2, + "status": "started", + "assigned_by": "scopatz", + "running_index": 3, + "tags": ["reading", "downtime"] + }, {"description": "prepare the presentation", "uuid": "2saefadf-wdaagea3", "due_date": "2020-07-29", diff --git a/regolith/tools.py b/regolith/tools.py index 230f4e3d4..b7094f08a 100644 --- a/regolith/tools.py +++ b/regolith/tools.py @@ -2316,3 +2316,9 @@ def get_appointments(person, appointments, target_grant=None): round(weighted_duration, 2), appt.get('grant'))) return appointments +def get_task(task_coll, task_id): + tasks = [task for task in task_coll if task.get("uuid", "") == task_id] + if len(tasks) > 1: + print(f"WARNING: there are multiple tasks with id {task_id}. Picking " + f"the one with description {tasks[0].get('description')}") + return tasks[0] diff --git a/tests/outputs/a_todo/todos.yaml b/tests/outputs/a_todo/todos.yaml index d48cf6519..a77b42613 100644 --- a/tests/outputs/a_todo/todos.yaml +++ b/tests/outputs/a_todo/todos.yaml @@ -14,6 +14,19 @@ sbillinge: tags: - reading - downtime + - description: added todo + uuid: test-uuid + due_date: '2020-07-20' + begin_date: '2020-06-15' + deadline: true + duration: 60.0 + importance: 2 + status: started + assigned_by: scopatz + running_index: 3 + tags: + - reading + - downtime - description: prepare the presentation uuid: 2saefadf-wdaagea3 due_date: '2020-07-29' @@ -43,4 +56,4 @@ sbillinge: tags: - tag1 - tag2 - running_index: 3 + running_index: 4 diff --git a/tests/outputs/f_todo/todos.yaml b/tests/outputs/f_todo/todos.yaml index 4b9bd0c0a..8cb1c1cb4 100644 --- a/tests/outputs/f_todo/todos.yaml +++ b/tests/outputs/f_todo/todos.yaml @@ -14,6 +14,19 @@ sbillinge: tags: - reading - downtime + - description: added todo + uuid: test-uuid + due_date: '2020-07-20' + begin_date: '2020-06-15' + deadline: true + duration: 60.0 + importance: 2 + status: started + assigned_by: scopatz + running_index: 3 + tags: + - reading + - downtime - description: prepare the presentation uuid: 2saefadf-wdaagea3 due_date: '2020-07-29' @@ -43,5 +56,5 @@ sbillinge: tags: - tag1 - tag2 - running_index: 3 + running_index: 4 end_date: 2020-07-20 diff --git a/tests/outputs/u_todo/todos.yaml b/tests/outputs/u_todo/todos.yaml index 320f4bda1..e2c5f4e47 100644 --- a/tests/outputs/u_todo/todos.yaml +++ b/tests/outputs/u_todo/todos.yaml @@ -14,6 +14,19 @@ sbillinge: tags: - reading - downtime + - description: added todo + uuid: test-uuid + due_date: '2020-07-20' + begin_date: '2020-06-15' + deadline: true + duration: 60.0 + importance: 2 + status: started + assigned_by: scopatz + running_index: 3 + tags: + - reading + - downtime - description: prepare the presentation uuid: 2saefadf-wdaagea3 due_date: '2020-07-29' @@ -47,5 +60,5 @@ sbillinge: - tag2 - newtag1 - newtag2 - running_index: 3 + running_index: 4 end_date: 2020-07-07 diff --git a/tests/test_helpers.py b/tests/test_helpers.py index c9bc72057..a3ae565ac 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -116,8 +116,8 @@ ), (["helper", "l_milestones", "--verbose"], "2021-08-03 (milest): lead: pliu, pl_secondprojectum, status: converged\n Type: \n Title: Milestone\n log url: None\n Purpose: None\n Audience: \n uuid: milestone_uuid_pl2\n" - "2021-05-05 (sb_fir): lead: ascopatz, sb_firstprojectum, status: proposed\n Type: \n Title: deliverable\n log url: https://docs.google.com/document/d/1YC_wtW5Q\n Purpose: deliver\n Audience: beginning grad in chemistry\n Notes:\n - deliverable note\n uuid: sb_firstprojectum\n" - "2020-05-27 (milest): lead: ascopatz, sb_firstprojectum, status: proposed\n Type: mergedpr\n Title: planning meeting\n log url: https://docs.google.com/document/d/1YC_wtW5Q\n Purpose: develop a detailed plan with dates\n Audience: ascopatz, scopatz, ascopatz\n uuid: milestone_uuid_sb1_2\n" + "2021-05-05 (sb_fir): lead: ascopatz, sb_firstprojectum, status: proposed\n Type: \n Title: deliverable\n log url: https://docs.google.com/document/d/1YC_wtW5Q\n Purpose: deliver\n Audience: beginning grad in chemistry\n Notes:\n - deliverable note\n Tasks:\n - (1) read paper (79|2|60.0|1saefa)\n uuid: sb_firstprojectum\n" + "2020-05-27 (milest): lead: ascopatz, sb_firstprojectum, status: proposed\n Type: mergedpr\n Title: planning meeting\n log url: https://docs.google.com/document/d/1YC_wtW5Q\n Purpose: develop a detailed plan with dates\n Audience: ascopatz, scopatz, ascopatz\n Tasks:\n - (3) added todo (80|2|60.0|test_u)\n uuid: milestone_uuid_sb1_2\n" "2020-05-20 (milest): lead: ascopatz, sb_firstprojectum, status: proposed\n Type: meeting\n Title: Project lead presentation\n log url: https://docs.google.com/document/d/1YC_wtW5Q\n Purpose: lead presents background reading and initial project plan\n Audience: ascopatz, scopatz, ascopatz\n Notes:\n - do background reading\n - understand math\n uuid: milestone_uuid_sb1\n" ), (["helper", "l_milestones", "--verbose", "--current"], @@ -376,6 +376,12 @@ "----------------------------------------------------------------------------\n" "(importance)(days to due): (Task number) Task (decreasing priority going up)\n" "----------------------------------------------------------------------------\n" + "(3) added todo (80|2|60.0|reading,downtime|scopatz|test-u)\n" + "(1) read paper (79|2|60.0|reading,downtime|scopatz|1saefa)\n" + "------------------------------\n" + "Tasks (decreasing priority going up)\n" + "------------------------------\n" + "2020-07-20(80 days): (3) added todo (80|2|60.0|reading,downtime|scopatz|test-u)\n" "2020-07-19(79 days): (1) read paper (79|2|60.0|reading,downtime|scopatz|1saefa)\n" "------------------------------\n" "Deadlines:\n" @@ -392,6 +398,12 @@ "----------------------------------------------------------------------------\n" "(importance)(days to due): (Task number) Task (decreasing priority going up)\n" "----------------------------------------------------------------------------\n" + "(3) added todo (7|2|60.0|reading,downtime|scopatz|test-u)\n" + "(1) read paper (6|2|60.0|reading,downtime|scopatz|1saefa)\n" + "------------------------------\n" + "Tasks (decreasing priority going up)\n" + "------------------------------\n" + "2020-07-20(7 days): (3) added todo (7|2|60.0|reading,downtime|scopatz|test-u)\n" "2020-07-19(6 days): (1) read paper (6|2|60.0|reading,downtime|scopatz|1saefa)\n" "------------------------------\n" "Deadlines:\n" @@ -404,12 +416,12 @@ "(index) action (days to due date|importance|expected duration (mins)|tags|assigned by)\n" "--------------------------------------------------------------------------------\n" "started:\n" - "(0)(16 days): (2) prepare the presentation (16|0|30.0|downtime|sbillinge|2saefa)\n" + "(2) prepare the presentation (16|0|30.0|downtime|sbillinge|2saefa)\n" " - about 10 minutes\n" " - don't forget to upload to the website\n" - "----------------------------------------------------------------------------\n" - "(importance)(days to due): (Task number) Task (decreasing priority going up)\n" - "----------------------------------------------------------------------------\n" + "------------------------------\n" + "Tasks (decreasing priority going up)\n" + "------------------------------\n" "------------------------------\n" "Deadlines:\n" "------------------------------\n" @@ -422,12 +434,12 @@ "(index) action (days to due date|importance|expected duration (mins)|tags|assigned by)\n" "--------------------------------------------------------------------------------\n" "started:\n" - "(0)(-255 days): (2) prepare the presentation (-255|0|30.0|downtime|sbillinge|2saefa)\n" + "(2) prepare the presentation (-255|0|30.0|downtime|sbillinge|2saefa)\n" " - about 10 minutes\n" " - don't forget to upload to the website\n" - "----------------------------------------------------------------------------\n" - "(importance)(days to due): (Task number) Task (decreasing priority going up)\n" - "----------------------------------------------------------------------------\n" + "------------------------------\n" + "Tasks (decreasing priority going up)\n" + "------------------------------\n" "------------------------------\n" "Deadlines:\n" "------------------------------\n" @@ -548,9 +560,9 @@ "The milestone uuid milestone_uuid_sb1_2 in projectum sb_firstprojectum has been updated in projecta.\n" "The task \"test a_todo\" for sbillinge has been added in todos collection.\n" ), - (["helper", "f_todo", "--index", "3", "--assigned-to", "sbillinge", + (["helper", "f_todo", "--index", "4", "--assigned-to", "sbillinge", "--end-date", "2020-07-20", "--date", "2020-07-13"], - "The task \"(3) test a_todo\" in test for sbillinge has been marked as finished.\n" + "The task \"(4) test a_todo\" in test for sbillinge has been marked as finished.\n" ), (["helper", "f_todo", "--assigned-to", "sbillinge", "--date", "2020-07-13"], @@ -566,6 +578,12 @@ "----------------------------------------------------------------------------\n" "(importance)(days to due): (Task number) Task (decreasing priority going up)\n" "----------------------------------------------------------------------------\n" + "(3) added todo (7|2|60.0|reading,downtime|scopatz|test-u)\n" + "(1) read paper (6|2|60.0|reading,downtime|scopatz|1saefa)\n" + "------------------------------\n" + "Tasks (decreasing priority going up)\n" + "------------------------------\n" + "2020-07-20(7 days): (3) added todo (7|2|60.0|reading,downtime|scopatz|test-u)\n" "2020-07-19(6 days): (1) read paper (6|2|60.0|reading,downtime|scopatz|1saefa)\n" "------------------------------\n" "Deadlines:\n" @@ -574,13 +592,13 @@ (["helper", "f_todo", "--index", "99100"], "WARNING: indices >= 9900 are used for milestones which should be finished using u_milestone and not f_todo\n" ), - (["helper", "u_todo", "--index", "3", "--assigned-to", "sbillinge", + (["helper", "u_todo", "--index", "4", "--assigned-to", "sbillinge", "--description", "update the description", "--due-date", "2020-07-06", "--estimated-duration", "35", "--importance", "2", "--status", "finished", "--notes", "some new notes", "notes2", "--tags", "newtag1", "newtag2", "--begin-date", "2020-06-06", "--deadline", "t", "--end-date", "2020-07-07", "--date", "2020-07-13"], - "The task \"(3) test a_todo\" in test for sbillinge has been updated.\n" + "The task \"(4) test a_todo\" in test for sbillinge has been updated.\n" ), (["helper", "u_todo", "--assigned-to", "sbillinge", "--stati", "started", "finished", "--filter", "description", "the", "--date", @@ -595,6 +613,7 @@ " - don't forget to upload to the website\n" "finished:\n" "(2)(-7 days): (3) update the description (-7|2|35.0|tag1,tag2,newtag1,newtag2|sbillinge|test-u)\n" + "(4) update the description (-7|2|35.0|tag1,tag2,newtag1,newtag2|sbillinge|test-u)\n" " - test notes 1\n" " - test notes 2\n" " - some new notes\n" @@ -603,6 +622,10 @@ "(importance)(days to due): (Task number) Task (decreasing priority going up)\n" "----------------------------------------------------------------------------\n" "2020-07-06(-7 days): (3) update the description (-7|2|35.0|tag1,tag2,newtag1,newtag2|sbillinge|test-u)\n" + "------------------------------\n" + "Tasks (decreasing priority going up)\n" + "------------------------------\n" + "2020-07-06(-7 days): (4) update the description (-7|2|35.0|tag1,tag2,newtag1,newtag2|sbillinge|test-u)\n" " - test notes 1\n" " - test notes 2\n" " - some new notes\n" diff --git a/tests/test_tools.py b/tests/test_tools.py index 6621329ec..fb9b1bec2 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -15,8 +15,8 @@ from regolith.tools import ( filter_publications, filter_presentations, - fuzzy_retrieval, fragment_retrieval, + fuzzy_retrieval, number_suffix, latex_safe, update_schemas, @@ -45,7 +45,8 @@ get_tags, dereference_institution, get_target_repo_info, get_target_token, create_repo, get_uuid, - get_appointments + get_appointments, + get_task ) PEOPLE_COLL = [ @@ -2353,4 +2354,92 @@ def test_get_uuid(mocker): def test_get_appointments(tga): expected = tga[3] actual = get_appointments(tga[0], tga[1], tga[2]) - assert expected == actual \ No newline at end of file + assert expected == actual + +tgt = [ + ([{'uuid': 'task_id', + '_id': 'sbillinge', + 'due_date': dt.date(2022, 6, 30), + 'begin_date': '2022-05-01', + 'description': 'what I have to do', + 'deadline': True, + 'duration': 60, + 'importance': 2, + 'status': 'started', + 'assigned_by': 'sbillinge', + 'running_index': 92, + 'tags': ['reading', 'downtime']}, + {'uuid': 'another_task_id', + '_id': 'sbillinge', + 'due_date': dt.date(2022, 6, 30), + 'begin_date': '2022-05-01', + 'description': 'what else', + 'deadline': False, + 'duration': 10, + 'importance': 3, + 'status': 'started', + 'assigned_by': 'sbillinge', + 'running_index': 94, + 'tags': [] + } + ], + 'task_id', + {'uuid': 'task_id', + '_id': 'sbillinge', + 'due_date': dt.date(2022, 6, 30), + 'begin_date': '2022-05-01', + 'description': 'what I have to do', + 'deadline': True, + 'duration': 60, + 'importance': 2, + 'status': 'started', + 'assigned_by': 'sbillinge', + 'running_index': 92, + 'tags': ['reading', 'downtime']} + ), + ([{'uuid': 'task_id', + '_id': 'sbillinge', + 'due_date': dt.date(2022, 6, 30), + 'begin_date': '2022-05-01', + 'description': 'what I have to do', + 'deadline': True, + 'duration': 60, + 'importance': 2, + 'status': 'started', + 'assigned_by': 'sbillinge', + 'running_index': 92, + 'tags': ['reading', 'downtime']}, + {'uuid': 'task_id', + '_id': 'sbillinge', + 'due_date': dt.date(2022, 6, 30), + 'begin_date': '2022-05-01', + 'description': 'what else', + 'deadline': False, + 'duration': 10, + 'importance': 3, + 'status': 'started', + 'assigned_by': 'sbillinge', + 'running_index': 94, + 'tags': [] + } + ], + 'task_id', + {'uuid': 'task_id', + '_id': 'sbillinge', + 'due_date': dt.date(2022, 6, 30), + 'begin_date': '2022-05-01', + 'description': 'what I have to do', + 'deadline': True, + 'duration': 60, + 'importance': 2, + 'status': 'started', + 'assigned_by': 'sbillinge', + 'running_index': 92, + 'tags': ['reading', 'downtime']} + ), +] +@pytest.mark.parametrize("tgt", tgt) +def test_get_task(tgt): + actual = get_task(tgt[0], tgt[1]) + expected = tgt[2] + assert actual == expected