在底层使用 rich 来处理用户输入并向终端显示漂亮的看板。每个任务在每个面板上都有一个唯一的 ID,并且还具有与其关联的可选标签和截止日期,这些信息显示在其标题旁边。
利用 platformdirs user_config_dir 来保存配置文件和用于板特定任务文件的 user_data_dir 。 创建第一个板后,您可以使用看板配置来显示当前设置表。 表标题中的配置路径和任务文件的路径可以在 kanban_boards 部分中找到。
可以在行首扫描定义类型的文件以查找特定模式。检查自动任务创建以获取更多信息。
第一次初始化时,会在 user_config_dir 目录中的看板文件夹中创建初始文件,其可以手动编辑或在应用程序中编辑。它会跟踪您创建的所有图板的位置。
每个创建的板都有自己的名称和 .json 文件,该文件存储该板的所有任务。 文件存储在 $USER_DATA_DIR 下的板特定文件夹中。更改面板时,您还可以概览每个面板可见列中的任务以及该面板上最紧急或过期的任务。
应用中带有 5 个预定义的彩色列:[Ready、Doing、Done、Archived、Deleted] 更多列可以在初始文件中手动添加,可见性可以在设置中使用 configure 进行配置。
对于每项任务,都会根据您更新任务状态的时刻,跟踪其在“正在执行”列中的持续时间。创建时的初始任务结构如下所示:
"1": {
"Title": "Welcome Task",
"Description": "Welcome, I hope this helps your productivity",
"Tag": "HI",
"Status": "Ready",
"Begin_Time": " ",
"Complete_Time": " " ",
"Duration": "0",
"Creation_Date": "2023-11-22 13:57:05"
}
样式:
Ready (11 Task/s) Doing (3 Task/s) Done (0 Task/s) [ 01 ] (H) give this repo a ∗ |-1| [ 12 ] ( H O ) Very Important Task |06| [ 02 ] (E) be productive [ 13 ] (HO) This must be done till tomorrow [ 03 ] (L) Read a good Book [ 04 ] (L) Go for a walk [ 05 ] (0) Call friend [ 06 ] (G) Clean whiteboard [ 07 ] (I) Buy Birthday present [ 08 ] (T) Write Tests for X [ 09 ] (H) Clean my room [ 10 ] (U) Make up more Task examples [ 11 ] (B) Puuh Done \begin{array}{|l|l|l|} \hline \text { Ready (11 Task/s) } & \text { Doing (3 Task/s) } & \text{Done (0 Task/s)} \\ \hline[01] \text { (H) give this repo a } * \text { |-1| } & {[12](\mathrm{HO}) \text { Very Important Task |06| }} \\ {[02] \text { (E) be productive }} & {[13] \text { (HO) This must be done till tomorrow }} \\ {[03] \text { (L) Read a good Book }} & \\ {[04] \text { (L) Go for a walk }} & \\ {[05] \text { (0) Call friend }} & \\ {[06] \text { (G) Clean whiteboard }} & \\ {[07] \text { (I) Buy Birthday present }} & \\ {[08] \text { (T) Write Tests for X }} & \\ {[09] \text { (H) Clean my room }} & \\ {[10] \text { (U) Make up more Task examples }} & \\ {[11] \text { (B) Puuh Done }} & \\ \hline \end{array} Ready (11 Task/s) [01] (H) give this repo a ∗ |-1| [02] (E) be productive [03] (L) Read a good Book [04] (L) Go for a walk [05] (0) Call friend [06] (G) Clean whiteboard [07] (I) Buy Birthday present [08] (T) Write Tests for X [09] (H) Clean my room [10] (U) Make up more Task examples [11] (B) Puuh Done Doing (3 Task/s) [12](HO) Very Important Task |06| [13] (HO) This must be done till tomorrow Done (0 Task/s)
配置
import configparser
from pathlib import Path
from .constants import (
CONFIG_FILE_NAME,
CONFIG_FILE_PATH,
CONFIG_PATH,
DATA_PATH,
KANBAN_BOARDS_FOLDER_NAME,
KANBAN_BOARDS_PATH,
TASK_FILE_NAME,
)
from .utils import console
class Config:
def __init__(self, path=CONFIG_FILE_PATH) -> None:
self.configpath = path
self._config = configparser.ConfigParser(default_section=None)
self._config.optionxform = str
self._config.read(path)
def __repr__(self) -> str:
output = ""
for sec in self.config:
if sec:
output += 15 * "-"
output += f"Section: {sec}"
output += 15 * "-" + "\n"
for key, val in self.config[sec].items():
output += f"{key}: {val}\n"
return output
def save(self):
with open(self.configpath, "w") as configfile:
self.config.write(configfile)
@property
def config(self) -> configparser.ConfigParser:
return self._config
@property
def active_board(self) -> str:
return self._config["settings.general"]["Active_Board"]
...
控件:
from json import dump, load
from rich.pretty import pprint
from .config import (
cfg,
check_if_board_name_exists_in_config,
check_if_current_active_board_in_board_list,
delete_board_from_config,
get_json_path,
)
from .constants import (
DUMMY_DB,
KANBAN_BOARDS_PATH,
REPORT_FILE_NAME,
REPORT_FILE_PATH,
TASK_FILE_NAME,
)
from .interface import (
create_config_table,
create_github_like_report_table,
create_table,
input_ask_for_action,
input_ask_for_action_settings,
input_ask_for_change_board,
input_ask_for_delete_board,
input_ask_for_new_board_name,
input_ask_which_task_to_update,
input_ask_which_tasks_to_show,
input_change_column_settings,
input_change_done_limit_settings,
input_change_files_to_scan_settings,
input_change_footer_settings,
input_change_min_col_width_settings,
input_change_patterns_to_scan_settings,
input_confirm_add_todos_to_board,
input_confirm_delete_board,
input_confirm_set_board_active,
input_create_new_task,
input_update_task,
)
from .utils import (
check_board_name_valid,
check_if_done_col_leq_X,
check_if_there_are_visible_tasks_in_board,
check_scanner_files_valid,
check_scanner_patterns_valid,
console,
create_report_document,
current_time_to_str,
delete_json_file,
get_tag_id_choices,
move_first_done_task_to_archive,
scan_files,
scan_for_todos,
split_todo_in_tag_and_title,
)
# DB Controls
#####################################################################################
def create_new_db() -> None:
while True:
while True:
new_board_name = input_ask_for_new_board_name()
if check_board_name_valid(new_board_name):
break
console.print(f":warning: '{new_board_name}' is [red]not[/] a valid Name.")
if not check_if_board_name_exists_in_config(new_board_name):
break
console.print(
f":warning: Board '{new_board_name}' already exists, choose another Name."
)
cfg.kanban_boards_dict = new_board_name
if not new_db_path.exists():
new_db_path.mkdir()
with open(get_json_path(new_board_name), "w", encoding="utf-8") as f:
dump(DUMMY_DB, f, ensure_ascii=False, indent=4)
console.print(
f"Created new [orange3]{TASK_FILE_NAME}[/] file at "
+ f"[orange3]{KANBAN_BOARDS_PATH / new_board_name}[/] to save tasks."
)
if input_confirm_set_board_active(name=new_board_name):
cfg.active_board = new_board_name
def save_db(data):
path = cfg.active_board_path
with open(path, "w", encoding="utf-8") as f:
dump(data, f, ensure_ascii=False, indent=4)
...