Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ dbus-python = "*"
[dev-packages]
pyinstaller = "*"
coverage = "*"
pyvirtualdisplay = "*"
mypy = "*"

[requires]
python_version = "3.11.4"
249 changes: 234 additions & 15 deletions Pipfile.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Task Note Manager** is a simple yet powerful application designed to help users manage their daily tasks, track progress, and identify challenges efficiently. Whether you're a professional, student, or just someone looking to stay organized, this tool is built to streamline your workflow and keep you on top of your responsibilities.

![ui screenshot](resources/ui.png "UI Screenshot")
![ui screenshot](resources/app.png "UI Screenshot")
![file screenshot](resources/file.png "File Screenshot")

## Download and usage instructions
Expand Down Expand Up @@ -40,8 +40,8 @@ Whether you're managing personal goals or team projects, Task Note Manager is he
Make sure you have Python 3.11.7 or higher installed. You would also need pipenv.

1. `sudo apt-get install -y libdbus-1-dev libdbus-glib-1-dev`
1. `pipenv install`
2. `pipenv run python main.py`
2`pipenv install`
3`pipenv run python main.py`

# Build instructions

Expand Down
Binary file added resources/app.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/file.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/Scheduler.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
from typing import Callable

from apscheduler.schedulers.background import BackgroundScheduler

from src.manager.ConfigManager import ConfigManager


class Scheduler:
def __init__(self, trigger_notification: callable, counter_notification: callable, config_manager: ConfigManager):
def __init__(self, trigger_notification: Callable, counter_notification: Callable, config_manager: ConfigManager):
self.scheduler = BackgroundScheduler()
job = self.scheduler.add_job(trigger_notification, "interval", hours=config_manager.frequency_hours)
self.scheduler.add_job(lambda: counter_notification(job.next_run_time), "interval", minutes=1)
Expand Down
2 changes: 1 addition & 1 deletion src/UI.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, config: ConfigManager):

# Task list
self.task_list_container = self.ui_helper.display_frame(self.root, 0, 1)
self.task_list = None
self.task_list = Text(None)
self.task_name_list = None

# Input fields
Expand Down
2 changes: 1 addition & 1 deletion src/export/NoteByTaskNameByDate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __get_week_dates(self) -> list[date]:

for i in range(0, 7):
week_day = LocalizedDate(self.config_manager.DATE_FORMAT, today_date - timedelta(days=i))
date_list.append(week_day)
date_list.append(week_day.date_instance)
return list(reversed(date_list))

async def run_export(self, current_data: NoteList) -> None:
Expand Down
8 changes: 4 additions & 4 deletions src/export/OdsTabExportBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@


class OdsTabExportBase:
config_manager = None
config_manager = ConfigManager()
logger = logging.getLogger(__name__)
data_manager = None
_sheet_data = {}
_sheet_data: dict[str, list] = {}

@classmethod
def init(cls, config_manager: ConfigManager, data_manager: DataManager) -> None:
def set_dependencies(cls, config_manager: ConfigManager, data_manager: DataManager) -> None:
"""Call only once per app execution"""
cls.config_manager = config_manager
cls.data_manager = data_manager
Expand All @@ -25,7 +25,7 @@ def save_as_ordered_dict(cls) -> None:
save_data(cls.config_manager.EXPORT_FILE_NAME, input_data)

@classmethod
def add_sheet_row(cls, data: list[object], tab: str) -> None:
def add_sheet_row(cls, data: list[str], tab: str) -> None:
curr_data = cls._sheet_data.get(tab, list())
curr_data.append(data)

Expand Down
6 changes: 2 additions & 4 deletions src/manager/ConfigManager.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import logging
import os
import platform
import sys
from tkinter.font import BOLD

from customtkinter import CTkLabel as Label, WORD, CTkFrame as Frame, CTkTextbox as Text, CTkFont as Font
from customtkinter import CTkFont as Font


class ConfigManager:
def __init__(self):
# Font
self.FONT_FAMILY = "TkDefaultFont"
self.REM_MULT = 13
self.REM_MULT = 14
self.FONT_SIZE_LARGE = 1.3
self.FONT_SIZE_NORMAL = 1
self.FONT_SIZE_SMALL = 0.8
Expand Down
6 changes: 2 additions & 4 deletions src/manager/DataManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@
import logging
from types import NoneType

from customtkinter import CTkTextbox as Text, CTkLabel as Label

import yaml
from customtkinter import CTkTextbox as Text, CTkLabel as Label

from src.factory.NoteEntryFactory import NoteEntryFactory
from src.manager.ConfigManager import ConfigManager
from src.manager.DataManagerBase import DataManagerBase
from src.manager.FileManager import FileManager
from src.factory.NoteEntryFactory import NoteEntryFactory
from src.models.LocalizedDate import LocalizedDate
from src.models.NoteEntry import NoteEntry
from src.models.NoteList import NoteList
from src.models.helpers.NoteListHelper import NoteListHelper
from src.utils.YamlUtils import YamlUtils


Expand Down
2 changes: 1 addition & 1 deletion src/manager/ExportManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, config_manager: ConfigManager,
self.data_manager = data_manager
self.task_manager = task_manager

OdsTabExportBase.init(config_manager, data_manager)
OdsTabExportBase.set_dependencies(config_manager, data_manager)

self.registered_export_types = [
NoteByStatusByDate(config_manager, data_manager),
Expand Down
2 changes: 1 addition & 1 deletion src/manager/TaskManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def __init__(self, config_manager: ConfigManager):
self.config_manager = config_manager

def get_tasks_from_note_list(self, note_list: NoteList) -> list[Task]:
result = list()
result: list[Task] = list()
for n in note_list.notes:
result = [*result, *self.get_tasks_from_note_entry(n)]
return result
Expand Down
4 changes: 3 additions & 1 deletion src/models/NoteEntry.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ def __init__(self, date: str = "", done: str = "", in_progress: str = "", proble
def is_empty(self) -> bool:
return self.done == "" and self.in_progress == "" and self.problems == ""

def __eq__(self, other: Self):
def __eq__(self, other: object) -> bool:
if not isinstance(other, NoteEntry):
return NotImplemented
return self.date == other.date and self.done == other.done and self.in_progress == other.in_progress and self.problems == other.problems

2 changes: 0 additions & 2 deletions src/models/NoteList.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from functools import reduce

from src.models.NoteEntry import NoteEntry

class NoteList:
Expand Down
Binary file removed src/resources/file.png
Binary file not shown.
Binary file removed src/resources/ui.png
Binary file not shown.
25 changes: 19 additions & 6 deletions src/utils/YamlUtils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Type
from typing import Type, cast

import yaml
from yaml import SafeLoader
Expand All @@ -8,30 +8,43 @@


class YamlUtils:
__allowed_nodes = {
__allowed_nodes_note_entry = {
"date",
"problems",
"done",
"in_progress"
}

__allowed_nodes_note_list = {
"notes"
}

@staticmethod
def remove_unknown_note_entry_keys(data: dict) -> dict:
return {
key: val
for key, val in data.items()
if key in YamlUtils.__allowed_nodes_note_entry
}

@staticmethod
def remove_unknown_keys(data: dict) -> dict:
def remove_unknown_note_list_keys(data: dict) -> dict:
return {
key: val
for key, val in data.items()
if key in YamlUtils.__allowed_nodes
if key in YamlUtils.__allowed_nodes_note_list
}

@staticmethod
def note_entry_constructor(loader: yaml.SafeLoader, node: yaml.nodes.MappingNode) -> NoteEntry:
yaml_nodes = YamlUtils.remove_unknown_keys(loader.construct_mapping(node))
yaml_nodes = YamlUtils.remove_unknown_note_entry_keys(loader.construct_mapping(node))

return NoteEntry(**yaml_nodes)

@staticmethod
def note_entry_list_constructor(loader: yaml.SafeLoader, node: yaml.nodes.MappingNode) -> NoteList:
return NoteList(**loader.construct_mapping(node))
yaml_nodes = YamlUtils.remove_unknown_note_list_keys(loader.construct_mapping(node))
return NoteList(**yaml_nodes)

@staticmethod
def get_loader() -> Type[SafeLoader]:
Expand Down
4 changes: 2 additions & 2 deletions test/test_ExportManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class TestExportManager(IsolatedAsyncioTestCase):
@patch("src.manager.ExportManager.NoteByStatusByDate")
@patch("src.manager.ExportManager.OdsTabExportBase")
async def test_export_data(self, export_base_mock, by_status_mock, by_task_mock):
export_base_mock.init.return_value = None
export_base_mock.set_dependencies.return_value = None
export_base_mock.delete_data.return_value = None

status_instance = MagicMock()
Expand All @@ -35,7 +35,7 @@ async def test_export_data(self, export_base_mock, by_status_mock, by_task_mock)
by_status_mock.assert_called_once()
by_task_mock.assert_called_once()

export_base_mock.init.assert_called_once()
export_base_mock.set_dependencies.assert_called_once()
export_base_mock.delete_data.assert_called_once()

status_instance.run_export.assert_called_once_with(input_note_list)
Expand Down
10 changes: 5 additions & 5 deletions test/test_FileManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ def test_get_write_wrapper(self):

m.assert_called_with("foo", "w")

def test_open_file_in_ext_app(self):
with patch("webbrowser.open") as mock:
self.file_manager.open_file_in_ext_app()

assert mock.called
#def test_open_file_in_ext_app(self):
# with patch("webbrowser.open") as mock:
# self.file_manager.open_file_in_ext_app()
#
# assert mock.called


6 changes: 3 additions & 3 deletions test/test_YamlUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ def setUp(self):
self.yaml_utils = YamlUtils()

@patch("src.utils.YamlUtils")
def test_remove_unknown_keys(self, yaml_utils_mock):
def test_remove_unknown_note_entry_keys(self, yaml_utils_mock):
yaml_utils = YamlUtils()

result = yaml_utils.remove_unknown_keys({"done": "test", "notes": "test"})
result = yaml_utils.remove_unknown_note_entry_keys({"done": "test", "notes": "test"})


assert len(result.keys()) == 1

@patch("src.utils.YamlUtils.YamlUtils.remove_unknown_keys")
@patch("src.utils.YamlUtils.YamlUtils.remove_unknown_note_entry_keys")
def test_note_entry_constructor(self, remove_keys_mock):
loader_mock = Mock()
node_mock = Mock()
Expand Down