import click import json from tinydb import Query from planner import db from planner.models import * @click.group() @click.option('-v', '--db', type=str, default='./planning.json', show_default=True) @click.pass_context def main(ctx, db): """Basic CLI project-handling""" ctx.ensure_object(dict) @main.group() @click.pass_context def milestone(ctx): """Handle milestones""" ctx.obj['model'] = Milestone @main.group() @click.pass_context def sprint(ctx): """Handle sprints""" ctx.obj['model'] = Sprint @main.group() @click.pass_context def item(ctx): """Handle items""" ctx.obj['model'] = Item @main.group() @click.pass_context def comment(ctx): """Handle comments""" ctx.obj['model'] = Comment def save_or_display_errors(model, data): ok, m_doc = model.validate(data) if ok : m = model.get(m_doc) m.save() click.secho(f"{m} was successfully added", fg='green') else: click.secho(f"Errors : {m_doc}", fg='red') @milestone.command('new') @click.option('--name', prompt='Milestone name') @click.option('--description', prompt='Milestone description') @click.pass_context def new_milestone(ctx, name, description): """Add a new milestone""" model = ctx.obj['model'] data = { 'name': name, 'description': description } save_or_display_errors(model, data) @sprint.command('new') @click.option('--name', prompt='Sprint name') @click.option('--description', prompt='Sprint description') @click.option('--milestone_id', prompt='Related milestone ID', type=int) @click.pass_context def new_sprint(ctx, name, description, milestone_id): """Add a new sprint""" model = ctx.obj['model'] data = { 'name': name, 'description': description, 'milestone_id': milestone_id } save_or_display_errors(model, data) @item.command('new') @click.option('--name', prompt='Item name') @click.option('--description', prompt='Item description') @click.option('--milestone_id', type=int) @click.option('--sprint_id', type=int) @click.option('--category', type=str) @click.pass_context def new_item(ctx, name, description, milestone_id=None, sprint_id=None, category=None): """Add a new sprint""" model = ctx.obj['model'] if not milestone_id and not sprint_id: parent_type = click.prompt('Related to [M]ilestone or [S]print ?', type=click.Choice(['m', 's'])) if parent_type == 'm': milestone_id = click.prompt('Related milestone ID', type=int) elif parent_type == 's': sprint_id = click.prompt('Related sprint ID', type=int) if not category: choices = { 'limitation': 'l', 'feature': 'f', 'constraint': 'c', 'unknown': 'u' } category_choice = click.prompt( 'Which category ? ({})'.format(', '.join(choices.keys())), type=click.Choice([v for v in choices.values()]) ) inv_choices = {v: k for k, v in choices.items()} category = inv_choices[category_choice] data = {'name': name, 'description': description, 'category': category} if milestone_id: data.update({'milestone_id': milestone_id}) if sprint_id: data.update({'sprint_id': sprint_id}) save_or_display_errors(model, data) @comment.command('new') @click.option('--item_id', prompt='ID of item on which to comment', type=int) @click.option('--text', prompt='Text', type=str) @click.pass_context def new_comment(ctx, item_id, text): """Add a new comment""" model = ctx.obj['model'] data = { 'text': text, 'item_id': item_id, } save_or_display_errors(model, data) @click.command() @click.pass_context def list(ctx): """List""" model = ctx.obj['model'] list = model.list() click.echo('\n'.join([i.as_term for i in list])) @main.command() @click.argument('short_uuid') @click.pass_context def edit(ctx, short_uuid): """Edit data""" for model in [Milestone, Sprint, Comment, Item]: result_list = db.table(model.class_name()).search( Query().uuid.test(lambda s: s.startswith(short_uuid)) ) if result_list: break if result_list: result = result_list[0] editable = json.dumps(result_list[0], indent=4) edited_json = click.edit(editable) if edited_json: updated_instance = json.loads(edited_json) db.table(model.class_name()).update(updated_instance, doc_ids=[result.doc_id]) click.secho(f"Successfully updated {updated_instance}", fg='green') else: click.secho(f"No matching result found", fg='red') milestone.add_command(list) sprint.add_command(list) item.add_command(list) comment.add_command(list) if __name__ == '__main__': main()