summaryrefslogtreecommitdiffstats
path: root/girok/utils/display.py
diff options
context:
space:
mode:
Diffstat (limited to 'girok/utils/display.py')
-rw-r--r--girok/utils/display.py253
1 files changed, 253 insertions, 0 deletions
diff --git a/girok/utils/display.py b/girok/utils/display.py
new file mode 100644
index 0000000..ad44329
--- /dev/null
+++ b/girok/utils/display.py
@@ -0,0 +1,253 @@
+from datetime import datetime
+import calendar
+
+from rich import print
+from rich.console import Console
+from rich.tree import Tree
+from rich.align import Align
+from rich import box
+from rich.style import Style
+from rich.table import Table, Column
+from rich.text import Text
+from rich.align import Align
+import shutil
+
+import girok.utils.task as task_utils
+import girok.utils.calendar as calendar_utils
+import girok.utils.general as general_utils
+from girok.config import get_config
+import girok.constants as constants
+
+console = Console()
+cfg = get_config()
+
+def display_categories(cats_dict: dict, highlight_cat=None):
+ tree = Tree("")
+ for idx, cat in enumerate(cats_dict):
+ display_category(
+ cats_dict,
+ cat,
+ top_most=True,
+ tree=tree,
+ cumul_path=cat,
+ highlight_cat=highlight_cat,
+ color=cats_dict[cat]['color']
+ )
+ console.print(tree)
+
+
+def display_category(
+ cats_dict: dict,
+ cat: str,
+ top_most=True,
+ tree: Tree=None,
+ cumul_path="",
+ highlight_cat=None,
+ color=None,
+):
+ style = Style(
+ color=constants.TABLE_HEADER_COLOR if highlight_cat != cumul_path else "#B9D66A",
+ bold=True
+ )
+ # if not top_most:
+ # style = Style(color=constants.TABLE_TASK_NAME_COLOR, bold=True)
+
+ # if top_most:
+ circle = Text(constants.CIRCLE_EMOJI + " ", style=Style(color=constants.CIRCLE_COLOR[color]))
+
+ dir_name = Text(f"{cat}", style=style)
+ # if top_most:
+ dir_name = Text.assemble(circle, dir_name)
+
+ tree = tree.add(dir_name)
+ for sub in cats_dict[cat]['subcategories'].keys():
+ display_category(
+ cats_dict[cat]['subcategories'],
+ sub,
+ top_most=False,
+ tree=tree,
+ cumul_path=cumul_path + "/" + sub,
+ highlight_cat=highlight_cat,
+ color=color
+ )
+
+
+def center_print(text, type: str = None, wrap: bool = False):
+ if type == "title":
+ style = Style(
+ color=constants.DISPLAY_TERMINAL_COLOR_TITLE_TEXT,
+ bgcolor=constants.DISPLAY_TERMINAL_COLOR_TITLE_BACKGROUND
+ )
+ elif type == "success":
+ style = Style(
+ color=constants.DISPLAY_TERMINAL_COLOR_SUCCESS_TEXT,
+ bgcolor=constants.DISPLAY_TERMINAL_COLOR_SUCCESS_BACKGROUND
+ )
+ elif type == "error":
+ style = Style(
+ color=constants.DISPLAY_TERMINAL_COLOR_ERROR_TEXT,
+ bgcolor=constants.DISPLAY_TERMINAL_COLOR_ERROR_BACKGROUND
+ )
+ elif type == "warning":
+ style = Style(
+ color=constants.DISPLAY_TERMINAL_COLOR_WARNING_TEXT,
+ bgcolor=constants.DISPLAY_TERMINAL_COLOR_WARNING_BACKGROUND
+ )
+ else:
+ style = Style(
+ color=constants.DISPLAY_TERMINAL_COLOR_TITLE_TEXT,
+ bgcolor=constants.DISPLAY_TERMINAL_COLOR_TITLE_BACKGROUND
+ )
+ if wrap:
+ width = shutil.get_terminal_size().columns // 2
+ else:
+ width = shutil.get_terminal_size().columns
+
+ content = Text(text, style=style)
+ console.print(Align.center(content, style=style, width=width), height=100)
+
+
+def display_tasks_by_category(
+ task_tree,
+ color_dict,
+ marked_task_id: int = None,
+ marked_color: str = constants.TABLE_TASK_DELETED_COLOR
+):
+ # print(task_tree)
+ task_ids_cache = {}
+ tree = Tree("")
+ for idx, cat_name in enumerate(task_tree):
+ tree.add(display_category_with_tasks(
+ cat_name=cat_name,
+ task_tree=task_tree[cat_name],
+ color_dict=color_dict,
+ top_most=True,
+ task_ids_cache=task_ids_cache,
+ marked_task_id=marked_task_id,
+ marked_color=marked_color
+ ))
+ general_utils.cache_task_ids(cfg=cfg, cache=task_ids_cache)
+ return tree
+
+
+def display_category_with_tasks(
+ cat_name,
+ task_tree: dict,
+ color_dict,
+ top_most,
+ task_ids_cache,
+ marked_task_id: int = None,
+ marked_color: str = constants.TABLE_TASK_DELETED_COLOR,
+):
+ dir_name = Text(f"{cat_name}", style=Style(color=constants.TABLE_HEADER_COLOR, bold=True))
+ dir_name = Text.assemble(
+ Text(f"{constants.CIRCLE_EMOJI} ", style=Style(color=constants.CIRCLE_COLOR[color_dict[cat_name]])),
+ dir_name
+ )
+
+ tree = Tree(dir_name)
+
+ for sub_cat_name in task_tree['sub_categories']:
+ sub_tree = display_category_with_tasks(
+ cat_name=sub_cat_name,
+ task_tree=task_tree['sub_categories'][sub_cat_name],
+ color_dict=color_dict,
+ top_most=False,
+ task_ids_cache=task_ids_cache,
+ marked_task_id=marked_task_id,
+ marked_color=marked_color
+ )
+ tree.add(sub_tree)
+
+ for task in task_tree['tasks']:
+ # Cache task id
+ if not(task['task_id'] == marked_task_id and marked_color == constants.TABLE_TASK_DELETED_COLOR):
+ task_ids_cache[len(task_ids_cache) + 1] = task['task_id']
+
+ deadline = datetime.strptime(task['deadline'], "%Y-%m-%dT%H:%M:%S")
+ year, month, day = deadline.year, deadline.month, deadline.day
+ h, m, s = str(deadline.time()).split(":")
+
+ weekday_name = task_utils.get_weekday_name_from_date(year, month, day)
+
+ h = int(h)
+ is_time = task['is_time']
+ afternoon = h >= 12
+ if h > 12:
+ h -= 12
+
+ time = f" / {h}:{m} {'PM' if afternoon else 'AM'}" if is_time else ''
+ remaining_days = task_utils.get_day_offset_between_two_dates(datetime.now(), deadline)
+ day_offset_message = f"{remaining_days} days left" if remaining_days > 0 else f"{abs(remaining_days)} days passed"
+
+ if remaining_days == 0:
+ day_offset_message = "Due Today"
+
+ if not(task['task_id'] == marked_task_id and marked_color == constants.TABLE_TASK_DELETED_COLOR):
+ task_id = Text(f"[{len(task_ids_cache)}] ", style=Style(color="white" if task['task_id'] != marked_task_id else marked_color))
+ else:
+ task_id = ""
+ task_name = Text(task['name'], style=Style(color=constants.TABLE_TASK_NAME_COLOR if task['task_id'] != marked_task_id else marked_color, bold=True))
+ task_remaining_days = Text(f" [{day_offset_message}]", style=Style(color='#F5F7F2' if task['task_id'] != marked_task_id else marked_color))
+ task_date = Text(f" - {year}/{month}/{day} {weekday_name}", style=Style(color="white" if task['task_id'] != marked_task_id else marked_color))
+ node_name = Text.assemble(task_id, task_name, task_remaining_days, task_date, style=Style(strike=True if task['task_id'] == marked_task_id and marked_color == constants.TABLE_TASK_DELETED_COLOR else False))
+
+ tree.add(node_name)
+
+ return tree
+
+
+def display_tasks_by_list(tasks: list, marked_task_id: int = None, color: str = constants.TABLE_TASK_DELETED_COLOR):
+ table = build_task_table(tasks, marked_task_id, color)
+ print(Align(table, align="center"))
+
+
+def build_task_table(tasks: list, marked_task_id: int = None, color: str = constants.TABLE_TASK_DELETED_COLOR):
+ tasks = sorted(tasks, key=lambda x: calendar_utils.get_date_obj_from_str_separated_by_T(x['deadline']))
+ num_tasks = len(tasks)
+ table = Table(
+ Column(header="ID", justify="center", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color=constants.TABLE_TASK_NAME_COLOR)),
+ Column(header="Name", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color=constants.TABLE_TASK_NAME_COLOR)),
+ Column(header="Category", justify="center", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color=constants.TABLE_TEXT_COLOR)),
+ Column(header="Deadline", justify="center", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color="green")),
+ Column(header="Tag", justify="center", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color=constants.TABLE_TEXT_COLOR)),
+ Column(header="Priority", justify="center", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color=constants.TABLE_TEXT_COLOR)),
+ Column(header="Remaining", justify="center", header_style=Style(color=constants.TABLE_HEADER_COLOR), style=Style(color=constants.TABLE_TEXT_COLOR)),
+ box=box.SIMPLE_HEAVY,
+ show_lines=False if num_tasks > 15 else True,
+ border_style=Style(color="#D7E1C9", bold=True)
+ )
+
+ task_ids_cache = {}
+ for idx, task in enumerate(tasks):
+ # Cache task id
+ task_ids_cache[idx + 1] = task['task_id']
+
+ date = calendar_utils.get_date_obj_from_str_separated_by_T(task['deadline'])
+ deadline = f"{date.day} {calendar.month_name[date.month]} {date.year}"
+ remaining_days = task_utils.get_day_offset_between_two_dates(datetime.now(), date)
+ day_offset_message = f"{remaining_days} days left" if remaining_days > 0 else f"{abs(remaining_days)} days passed"
+ if remaining_days == 0:
+ day_offset_message = "Due Today"
+ circle = Text(constants.CIRCLE_EMOJI + " ", style=Style(color=constants.CIRCLE_COLOR[task['color']]))
+ task_name = Text.assemble(circle, task['name'], style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_TASK_NAME_COLOR, bold=True))
+
+ table.add_row(
+ Text(str(idx + 1), style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_TEXT_COLOR)),
+ task_name,
+ Text(task['task_category_full_path'] if task['task_category_full_path'] else "None", style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_TEXT_COLOR)),
+ Text(deadline, style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_DEADLINE_COLOR)),
+ Text(task['tag'] if task['tag'] else '-', style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_TEXT_COLOR)),
+ Text(str(task['priority']) if task['priority'] else '-', style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_TEXT_COLOR)),
+ Text(day_offset_message, style=Style(color=color if marked_task_id == task['task_id'] else constants.TABLE_TEXT_COLOR))
+ )
+
+ general_utils.cache_task_ids(cfg=cfg, cache=task_ids_cache)
+
+ return table
+
+
+
+
+
+