Fix pykban to make working version
This commit is contained in:
parent
14ec441322
commit
893b5e9473
@ -19,7 +19,9 @@ classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Environment :: Console"
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"textual"
|
||||
]
|
||||
[project.urls]
|
||||
Homepage = "https://alexselimov.com/git/aselimov/pykanban"
|
||||
Issues = "https://github.com/aselimov/PyKanban/issues"
|
||||
|
19
resources/.board.yaml
Normal file
19
resources/.board.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
columns:
|
||||
- To Do
|
||||
- In Progress
|
||||
- Review
|
||||
- Done
|
||||
tasks:
|
||||
- column: To Do
|
||||
description: "We want to be able to retire some done tickets \nwithout having to\
|
||||
\ delete them."
|
||||
score: '5'
|
||||
summary: Work out some way to handle sprints
|
||||
- column: To Do
|
||||
description: 'I want to add footers which describe the key shortcuts,
|
||||
|
||||
Additionally this should be disabledable via a command line argument
|
||||
|
||||
'
|
||||
score: '5'
|
||||
summary: 'Add some footers for the key shortcuts '
|
@ -3,24 +3,32 @@ from textual.widgets import Static, Label, ListItem, ListView, TextArea, Input
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.screen import Screen
|
||||
from textual.binding import Binding
|
||||
from board import Board, Task
|
||||
from .board import Board, Task
|
||||
|
||||
|
||||
def run_tui():
|
||||
kb = KanbanForm()
|
||||
kb.run()
|
||||
|
||||
|
||||
class TaskList(ListView):
|
||||
"""
|
||||
Inherited widget from Listview to use as the kanban board columns
|
||||
Inherited widget from Listview to use as the kanban board columns
|
||||
"""
|
||||
|
||||
# Keybinds
|
||||
BINDINGS = [
|
||||
Binding("k", "cursor_up", "Cursor Up", show=False, priority=True),
|
||||
Binding("j", "cursor_down", "Cursor Down", show=False, priority=True),
|
||||
]
|
||||
|
||||
|
||||
class EditTaskScreen(Screen):
|
||||
"""
|
||||
This is a screen used to edit the name of a task
|
||||
This is a screen used to edit the name of a task
|
||||
"""
|
||||
CSS="""
|
||||
|
||||
CSS = """
|
||||
Label{
|
||||
width:50%;
|
||||
background: #282828;
|
||||
@ -47,10 +55,11 @@ class EditTaskScreen(Screen):
|
||||
}
|
||||
"""
|
||||
BINDINGS = [
|
||||
Binding('ctrl+s', 'save', 'Save Changes', priority=True),
|
||||
Binding('escape', 'exit', 'Exit Without Changes', priority=True),
|
||||
Binding("ctrl+s", "save", "Save Changes", priority=True),
|
||||
Binding("escape", "exit", "Exit Without Changes", priority=True),
|
||||
]
|
||||
def __init__(self,text):
|
||||
|
||||
def __init__(self, text):
|
||||
"""
|
||||
Initialize the screen
|
||||
"""
|
||||
@ -61,19 +70,18 @@ class EditTaskScreen(Screen):
|
||||
"""
|
||||
Compose the widgets on the screen, this screen doesn't need dynamic layout changes
|
||||
"""
|
||||
yield Label('Task Name:')
|
||||
yield Label("Task Name:")
|
||||
yield Input(value=self.text.summary)
|
||||
yield Label('Score:')
|
||||
yield Label("Score:")
|
||||
if self.text.score:
|
||||
yield Input(value=self.text.score)
|
||||
else:
|
||||
yield Input(value="")
|
||||
yield Label('Description:')
|
||||
yield Label("Description:")
|
||||
if self.text.description:
|
||||
yield TextArea(self.text.description, language='markdown')
|
||||
yield TextArea(self.text.description, language="markdown")
|
||||
else:
|
||||
yield TextArea(language='markdown')
|
||||
|
||||
yield TextArea(language="markdown")
|
||||
|
||||
def action_save(self):
|
||||
query = self.query(selector=Input)
|
||||
@ -86,11 +94,13 @@ class EditTaskScreen(Screen):
|
||||
def action_exit(self):
|
||||
self.dismiss(None)
|
||||
|
||||
|
||||
class EditColScreen(Screen):
|
||||
"""
|
||||
This is a screen used to edit the name of a task
|
||||
This is a screen used to edit the name of a task
|
||||
"""
|
||||
CSS="""
|
||||
|
||||
CSS = """
|
||||
Label{
|
||||
width:50%;
|
||||
background: #282828;
|
||||
@ -104,10 +114,11 @@ class EditColScreen(Screen):
|
||||
}
|
||||
"""
|
||||
BINDINGS = [
|
||||
Binding('ctrl+s', 'save', 'Save Changes', priority=True),
|
||||
Binding('enter', 'save', 'Save Changes', priority=True),
|
||||
Binding("ctrl+s", "save", "Save Changes", priority=True),
|
||||
Binding("enter", "save", "Save Changes", priority=True),
|
||||
]
|
||||
def __init__(self,text):
|
||||
|
||||
def __init__(self, text):
|
||||
"""
|
||||
Initialize the screen
|
||||
"""
|
||||
@ -118,67 +129,94 @@ class EditColScreen(Screen):
|
||||
"""
|
||||
Compose the widgets on the screen, this screen doesn't need dynamic layout changes
|
||||
"""
|
||||
yield Label('Column Name:')
|
||||
yield Label("Column Name:")
|
||||
yield Input(value=self.text)
|
||||
|
||||
|
||||
def action_save(self):
|
||||
query = self.query(selector=Input)
|
||||
self.dismiss(query.nodes[0].value)
|
||||
|
||||
|
||||
class KanbanForm(App):
|
||||
CSS_PATH = 'layout.tcss'
|
||||
CSS_PATH = "layout.tcss"
|
||||
BINDINGS = [
|
||||
Binding("a", "new_task", "Add New Task", show=False, ),
|
||||
Binding("l", "fnext", "Focus Next", show=False, ),
|
||||
Binding("h", "fprev", "Focus Prev", show=False, ),
|
||||
Binding(
|
||||
"a",
|
||||
"new_task",
|
||||
"Add New Task",
|
||||
show=False,
|
||||
),
|
||||
Binding(
|
||||
"l",
|
||||
"fnext",
|
||||
"Focus Next",
|
||||
show=False,
|
||||
),
|
||||
Binding(
|
||||
"h",
|
||||
"fprev",
|
||||
"Focus Prev",
|
||||
show=False,
|
||||
),
|
||||
Binding("L", "move_up", "Focus Next", show=False),
|
||||
Binding("H", "move_down", "Focus Prev", show=False),
|
||||
Binding("e", "edit_task", "Edit Task", show=False,),
|
||||
Binding("r", "edit_column", "Edit Column Name", show=False,),
|
||||
Binding("d", "delete_task", "Delete Task", show=False,),
|
||||
Binding('q', 'exit', "Exit")
|
||||
]
|
||||
Binding(
|
||||
"e",
|
||||
"edit_task",
|
||||
"Edit Task",
|
||||
show=False,
|
||||
),
|
||||
Binding(
|
||||
"r",
|
||||
"edit_column",
|
||||
"Edit Column Name",
|
||||
show=False,
|
||||
),
|
||||
Binding(
|
||||
"x",
|
||||
"delete_task",
|
||||
"Delete Task",
|
||||
show=False,
|
||||
),
|
||||
Binding("q", "exit", "Exit"),
|
||||
]
|
||||
|
||||
def compose(self):
|
||||
"""
|
||||
Initialization function for form
|
||||
"""
|
||||
# Initialize our board class
|
||||
self.board = Board(file = '.board.yaml')
|
||||
self.board = Board(file=".board.yaml")
|
||||
self.cols = list()
|
||||
|
||||
self.col_widgets = list()
|
||||
|
||||
|
||||
|
||||
with Horizontal():
|
||||
for i,col in enumerate(self.board.get_columns()):
|
||||
if i < len(self.board.get_columns())-1:
|
||||
col_class = 'column'
|
||||
for i, col in enumerate(self.board.get_columns()):
|
||||
if i < len(self.board.get_columns()) - 1:
|
||||
col_class = "column"
|
||||
else:
|
||||
col_class = 'last-column'
|
||||
col_class = "last-column"
|
||||
with Vertical(classes=col_class):
|
||||
if i == 0:
|
||||
yield Static(col, classes='header-focused')
|
||||
yield Static(col, classes="header-focused")
|
||||
else:
|
||||
yield Static(col, classes='header')
|
||||
yield Static(col, classes="header")
|
||||
yield TaskList(
|
||||
*[ListItem(Label(task.summary)) for task in self.board.get_tasks()[i]])
|
||||
*[ListItem(Label(task.summary)) for task in self.board.get_tasks()[i]]
|
||||
)
|
||||
|
||||
def action_fnext(self):
|
||||
""" Focus next column"""
|
||||
"""Focus next column"""
|
||||
query = self.query(selector=Static)
|
||||
query = [node for node in query.nodes if str(node) == 'Static()']
|
||||
query = [node for node in query.nodes if str(node) == "Static()"]
|
||||
icol, _ = self.get_col_task()
|
||||
query[icol].classes="header"
|
||||
query[icol].classes = "header"
|
||||
self.children[0].focus_next()
|
||||
try:
|
||||
query[icol+1].classes="header-focused"
|
||||
query[icol + 1].classes = "header-focused"
|
||||
except IndexError:
|
||||
query[0].classes="header-focused"
|
||||
|
||||
|
||||
query[0].classes = "header-focused"
|
||||
|
||||
def action_move_up(self):
|
||||
icol, itask = self.get_col_task()
|
||||
@ -187,23 +225,22 @@ class KanbanForm(App):
|
||||
if moved:
|
||||
query = self.query(selector=TaskList)
|
||||
self.focused.highlighted_child.remove()
|
||||
query.nodes[icol+1].append(ListItem(Label(text)))
|
||||
query.nodes[icol + 1].append(ListItem(Label(text)))
|
||||
self.focused.action_cursor_down()
|
||||
self.action_fnext()
|
||||
self.focused.action_cursor_down()
|
||||
|
||||
|
||||
def action_fprev(self):
|
||||
""" Focus previous column """
|
||||
"""Focus previous column"""
|
||||
query = self.query(selector=Static)
|
||||
query = [node for node in query.nodes if str(node) == 'Static()']
|
||||
query = [node for node in query.nodes if str(node) == "Static()"]
|
||||
icol, _ = self.get_col_task()
|
||||
query[icol].classes="header"
|
||||
query[icol].classes = "header"
|
||||
self.children[0].focus_previous()
|
||||
try:
|
||||
query[icol-1].classes="header-focused"
|
||||
query[icol - 1].classes = "header-focused"
|
||||
except IndexError:
|
||||
query[-1].classes="header-focused"
|
||||
query[-1].classes = "header-focused"
|
||||
|
||||
def action_move_down(self):
|
||||
icol, itask = self.get_col_task()
|
||||
@ -212,7 +249,7 @@ class KanbanForm(App):
|
||||
if moved:
|
||||
query = self.query(selector=TaskList)
|
||||
self.focused.highlighted_child.remove()
|
||||
query.nodes[icol-1].append(ListItem(Label(text)))
|
||||
query.nodes[icol - 1].append(ListItem(Label(text)))
|
||||
self.focused.action_cursor_down()
|
||||
self.action_fprev()
|
||||
self.focused.action_cursor_down()
|
||||
@ -221,9 +258,9 @@ class KanbanForm(App):
|
||||
icol, itask = self.get_col_task()
|
||||
task = self.board.get_task(icol, itask)
|
||||
self.push_screen(EditTaskScreen(task), self.update_task)
|
||||
|
||||
|
||||
def action_new_task(self):
|
||||
self.push_screen(EditTaskScreen(Task(None,None,None)), self.new_task)
|
||||
self.push_screen(EditTaskScreen(Task(None, None, None)), self.new_task)
|
||||
|
||||
def action_edit_column(self):
|
||||
icol, itask = self.get_col_task()
|
||||
@ -233,25 +270,23 @@ class KanbanForm(App):
|
||||
def action_delete_task(self):
|
||||
icol, itask = self.get_col_task()
|
||||
self.focused.highlighted_child.remove()
|
||||
self.board.del_task(icol,itask)
|
||||
self.board.del_task(icol, itask)
|
||||
|
||||
def update_col(self, text):
|
||||
""" Update the column
|
||||
"""
|
||||
"""Update the column"""
|
||||
icol, itask = self.get_col_task()
|
||||
query = self.query(selector=Static)
|
||||
query = [node for node in query.nodes if str(node) == 'Static()']
|
||||
query = [node for node in query.nodes if str(node) == "Static()"]
|
||||
query[icol].update(text)
|
||||
self.board.get_columns()[icol] = text
|
||||
|
||||
|
||||
def action_exit(self):
|
||||
""" Exit the application """
|
||||
self.board.write_yaml(file='.board.yaml')
|
||||
"""Exit the application"""
|
||||
self.board.write_yaml(file=".board.yaml")
|
||||
self.exit()
|
||||
|
||||
def get_col_task(self):
|
||||
"""
|
||||
"""
|
||||
This function gets the relevant column and task from the Board object for the current
|
||||
selected item in the tui.
|
||||
"""
|
||||
@ -267,15 +302,15 @@ class KanbanForm(App):
|
||||
to_move = focused_col.highlighted_child
|
||||
task_index = None
|
||||
for i, child in enumerate(focused_col.children):
|
||||
if to_move == child:
|
||||
if to_move == child:
|
||||
task_index = i
|
||||
|
||||
return col_index, task_index
|
||||
|
||||
|
||||
def update_task(self, task):
|
||||
""" This function gets the text inputted in the edit screen and updates the underlying
|
||||
task and the board class
|
||||
|
||||
"""This function gets the text inputted in the edit screen and updates the underlying
|
||||
task and the board class
|
||||
|
||||
"""
|
||||
if task:
|
||||
icol, itask = self.get_col_task()
|
||||
@ -283,20 +318,9 @@ class KanbanForm(App):
|
||||
self.board.update_task(icol, itask, task)
|
||||
|
||||
def new_task(self, task):
|
||||
""" This function adds a new task to our board
|
||||
"""
|
||||
"""This function adds a new task to our board"""
|
||||
if task:
|
||||
icol,_ = self.get_col_task()
|
||||
icol, _ = self.get_col_task()
|
||||
self.focused.mount(ListItem(Label(task.summary)))
|
||||
self.board.add_task(icol, task)
|
||||
self.focused.action_cursor_down()
|
||||
|
||||
# def on_key(self):
|
||||
# with open('log','a') as f:
|
||||
# f.write("{}".format(self.children[0].focus_next))
|
||||
|
||||
if __name__ == "__main__":
|
||||
kb = KanbanForm()
|
||||
kb.run()
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user