13 Commits

Author SHA1 Message Date
Aaron Gutierrez
55970ab144 more WIP 2015-08-17 20:54:33 -07:00
Aaron Gutierrez
65bd30d026 Merge branch 'master' into subtask 2015-08-17 20:43:05 -07:00
Aaron Gutierrez
6243a9bb68 color project icons 2015-08-17 20:40:08 -07:00
Aaron Gutierrez
3a5837ae5d Enter opens parent task details. Fixes #45840013545374 2015-08-17 20:30:16 -07:00
Aaron Gutierrez
dac83e00a1 WIP subtasks 2015-08-17 20:17:53 -07:00
86e1d830de fix style problem if task name is empty 2015-08-07 12:33:43 -07:00
0fff014307 Show subtasks in details view 2015-08-06 23:16:42 -07:00
6664d299b9 Special case assignee typeahead in personal projects 2015-08-06 22:30:09 -07:00
7f76ebd441 Change project opening to be right, not left 2015-08-06 22:16:36 -07:00
5d176075a7 Details pane can scroll now. Fixes #44621775554616 2015-08-06 22:11:35 -07:00
e18c923202 Redraw screen after adding task 2015-08-06 22:11:04 -07:00
6ba98525d5 exclude tags file 2015-08-06 21:25:58 -07:00
3894b81ebc improved login prompt 2015-08-06 21:25:49 -07:00
3 changed files with 107 additions and 33 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,8 @@
*.swp
*.pyc
tags
.state
.oauth
secrets.py

View File

@@ -58,12 +58,13 @@ class CmdAsana:
},
)
(url, state) = self.client.session.authorization_url()
print("Go to the following link and enter the code:")
print(url)
try:
import webbrowser
webbrowser.open(url)
except Exception:
print("Go to the following link and enter the code:")
print(url)
pass
code = sys.stdin.readline().strip()
token = self.client.session.fetch_token(code=code)
@@ -134,6 +135,7 @@ class CmdAsana:
def update(task):
task_list,_ = self.frame.contents[1]
task_list.insertNewTask(task)
self.loop.draw_screen()
thread = Thread(target=runInThread)
thread.start()
@@ -169,12 +171,17 @@ class CmdAsana:
def userTypeAhead(self, text, callback):
def runInThread():
users = self.client.workspaces.typeahead(self.state['workspace_id'],
{
'type': 'user',
'query': text,
'count': 5
})
if self.state['workspace_id'] != PERSONAL:
users = self.client.workspaces \
.typeahead(self.state['workspace_id'],
{
'type': 'user',
'query': text,
'count': 5
})
else:
users = [self.me]
callback(users)
self.loop.draw_screen()
@@ -263,10 +270,11 @@ class CmdAsana:
def runInThread():
task = self.client.tasks.find_by_id(task_id)
stories = self.client.stories.find_by_task(task_id)
update(task, stories)
subtasks = self.client.tasks.subtasks(task_id)
update(task, stories, subtasks)
def update(task, stories):
task_details = ui.TaskDetails(task, stories)
def update(task, stories, subtasks):
task_details = ui.TaskDetails(task, stories, subtasks)
self.connectDetailsSignals(task_details)
self.replaceBody(task_details)
@@ -294,6 +302,9 @@ class CmdAsana:
'updatetask',
'usertypeahead',
'assigntask',
'complete',
'newtask',
'details',
])
urwid.register_signal(ui.AssigneeTypeAhead, [
@@ -332,6 +343,9 @@ class CmdAsana:
urwid.connect_signal(task_details, 'updatetask', self.updateTask)
urwid.connect_signal(task_details, 'usertypeahead', self.userTypeAhead)
urwid.connect_signal(task_details, 'assigntask', self.assignTask)
urwid.connect_signal(task_details, 'complete', self.completeTask)
urwid.connect_signal(task_details, 'newtask', self.newTask)
urwid.connect_signal(task_details, 'details', self.showDetails)
def handleInput(self, key):
if key in ('q', 'Q'):

102
ui.py
View File

@@ -12,6 +12,7 @@ palette = [
('header', 'bold,light green', ''),
('secondary', 'light gray', ''),
('task', 'light green', ''),
('project', 'yellow', ''),
('section', 'white', 'dark green'),
('workspace', 'white', 'dark blue'),
('pager', 'standout', ''),
@@ -61,7 +62,7 @@ class ProjectIcon(urwid.SelectableIcon):
super(ProjectIcon, self).__init__(project['name'])
def keypress(self, size, key):
if key in ('enter', 'left', 'l'):
if key in ('enter', 'right', 'l'):
self.onClick(self.project['id'])
else:
return super(ProjectIcon, self).keypress(size, key)
@@ -71,8 +72,8 @@ class ProjectList(urwid.ListBox):
self.projects = projects
body = urwid.SimpleFocusListWalker(
[ProjectIcon({'name': 'My Tasks', 'id': None},
self.loadProject),
[urwid.AttrMap(ProjectIcon({'name': 'My Tasks', 'id': None},
self.loadProject), 'project'),
None]
)
super(ProjectList, self).__init__(body)
@@ -82,8 +83,8 @@ class ProjectList(urwid.ListBox):
self.body.pop()
for i in range(50):
try:
self.body.append(ProjectIcon(self.projects.next(),
self.loadProject))
self.body.append(urwid.AttrMap(ProjectIcon(self.projects.next(),
self.loadProject), 'project'))
except StopIteration:
return
@@ -112,7 +113,8 @@ class TaskList(urwid.ListBox):
body = urwid.SimpleFocusListWalker([])
for task_widget,_ in task_widgets.contents:
self.connectSignals(task_widget)
style = 'section' if task_widget.task['name'][-1] == ':' else 'task'
style = 'section' if len(task_widget.task['name']) and \
task_widget.task['name'][-1] == ':' else 'task'
body.append(urwid.AttrMap(task_widget, style, focus_map='selected'))
super(TaskList, self).__init__(body)
@@ -264,8 +266,37 @@ class AssigneeTypeAhead(urwid.Pile):
self.contents = [self.contents[0]]
self.edit.set_edit_text(user['name'])
class TaskDetails(urwid.Pile):
def __init__(self, task, stories):
class ProjectTypeAhead(urwid.Pile):
def __init__(self, task):
body = [('pack', urwid.AttrMap(ProjectIcon(project, self.loadProject),
'project'))
for project in task['projects']]
self.edit = urwid.Edit('Add Project: ')
urwid.connect_signal(self.edit, 'change', self.typeAhead)
body.append(('pack', self.edit))
super(ProjecTypeAhead).__init__(body)
def typeAhead(self, widget, text):
urwid.emit_signal(self, 'projecttypeahead', text, self.updateTypeAhead)
def updateTypeAhead(self, projects):
projects = [(TypeAheadButton(p, self.add), ('pack', None))
for p in projects]
body = [('pack', urwid.AttrMap(ProjectIcon(project, self.loadProject),
'project'))
for project in self.task['projects']]
body.append(('pack', self.edit))
self.contents = body + projects
class TaskDetails(urwid.ListBox):
def __init__(self, task, stories, subtasks):
self.task = task
self.stories = stories
@@ -283,27 +314,54 @@ class TaskDetails(urwid.Pile):
urwid.connect_signal(assignee_type_ahead, 'usertypeahead',
self.userTypeAhead)
urwid.connect_signal(assignee_type_ahead, 'assigntask', self.assignTask)
containers = []
projects = [('pack', ProjectIcon(project, self.loadProject))
for project in task['projects']]
if task['parent'] != None:
parent = TaskEdit(task['parent'])
urwid.connect_signal(parent, 'updatetask', self.updateSubtask)
urwid.connect_signal(parent, 'details', self.showDetails)
body = projects + \
#Remap enter to load details of parent
urwid.connect_signal(parent, 'newtask', self.showDetails)
containers.append(parent)
all_subtasks = [t for t in subtasks]
subtask_list = TaskList(all_subtasks)
urwid.connect_signal(subtask_list, 'complete', self.completeTask)
urwid.connect_signal(subtask_list, 'newtask', self.newTask)
urwid.connect_signal(subtask_list, 'updatetask', self.updateSubtask)
urwid.connect_signal(subtask_list, 'details', self.showDetails)
body = containers + \
[
('pack', urwid.Divider('=')),
('pack', task_name_edit),
('pack', assignee_type_ahead),
('pack', urwid.Divider('-')),
('pack', self.description_edit),
('pack', urwid.Divider('-')),
urwid.Divider('='),
task_name_edit,
assignee_type_ahead,
urwid.Divider('-'),
self.description_edit,
urwid.Divider('-'),
urwid.BoxAdapter(subtask_list, len(all_subtasks)),
urwid.Divider('-'),
] + \
[('pack', urwid.Text('[' + story['created_by']['name'] + '] ' + \
story['text'])) for story in stories] + \
[
('weight', 1, urwid.Filler(comment_edit, 'bottom'))
]
[urwid.Text('[' + story['created_by']['name'] + '] ' + \
story['text']) for story in stories] + \
[comment_edit]
super(TaskDetails, self).__init__(body)
def completeTask(self, task_id):
urwid.emit_signal(self, 'complete', task_id)
def newTask(self, task_after_id=None):
urwid.emit_signal(self, 'newtask', task_after_id)
def updateSubtask(self, task_id, name):
urwid.emit_signal(self, 'updatetask', task_id, name)
def showDetails(self, task_id):
urwid.emit_signal(self, 'details', task_id)
def keypress(self, size, key):
key = super(TaskDetails, self).keypress(size, key)