initial commit
This commit is contained in:
commit
ae3e4668b7
6 changed files with 1617 additions and 0 deletions
2
__init__.py
Normal file
2
__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
from plankapy import Planka
|
||||||
|
from controllers import Project, Board, Card, List, Stopwatch, Label, Task, CommentAction, Attachment, User, CardMembership, BoardMembership, CardLabel, ProjectManager, Background
|
231
config/planka_routes.json
Normal file
231
config/planka_routes.json
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
{"access-token":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"active": "/api/access-tokens/me"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH": null,
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"active": "/api/access-tokens"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"attachment":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"attachment": "/api/attachments/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"attachment": "/api/attachments/:id:"
|
||||||
|
},
|
||||||
|
"POST": null
|
||||||
|
},
|
||||||
|
"board-membership":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"board-membership": "/api/board-memberships/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"board-membership": "/api/board-memberships/:id:"
|
||||||
|
},
|
||||||
|
"POST": null
|
||||||
|
},
|
||||||
|
"board":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"board": "/api/boards/:id:"
|
||||||
|
},
|
||||||
|
"GET":
|
||||||
|
{
|
||||||
|
"board": "/api/boards/:id:"
|
||||||
|
},
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"board": "/api/boards/:id:"
|
||||||
|
},
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"board-membership": "/api/boards/:id:/memberships",
|
||||||
|
"label": "/api/boards/:id:/labels",
|
||||||
|
"list": "/api/boards/:id:/lists"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"card-membership":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"card-membership": "/api/cards/:id:/memberships"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH": null,
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"card-membership": "/api/cards/:id:/memberships"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"card":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"card": "/api/cards/:id:",
|
||||||
|
"membership": "/api/cards/:id:/memberships",
|
||||||
|
"label": "/api/cards/:id:/labels/:id:"
|
||||||
|
},
|
||||||
|
"GET":
|
||||||
|
{
|
||||||
|
"card": "/api/cards/:id:",
|
||||||
|
"actions": "/api/cards/:id:/actions"
|
||||||
|
},
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"card": "/api/cards/:id:"
|
||||||
|
},
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"membership":"/api/cards/:id:/memberships",
|
||||||
|
"label":"/api/cards/:id:/labels",
|
||||||
|
"task":"/api/cards/:id:/tasks",
|
||||||
|
"attachment":"/api/cards/:id:/attachments",
|
||||||
|
"comment-action":"/api/cards/:id:/comment-actions"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"comment-action":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"comment-action": "/api/comment-actions/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"comment-action": "/api/comment-actions/:id:"
|
||||||
|
},
|
||||||
|
"POST": null
|
||||||
|
},
|
||||||
|
"label":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"label": "/api/labels/:id:",
|
||||||
|
"card-label": "/api/cards/:id:/labels/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"label": "/api/labels/:id:"
|
||||||
|
},
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"card-label":"/api/cards/:id:/labels",
|
||||||
|
"board-label": "/api/boards/:id:/labels"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"list":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"list": "/api/lists/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"list": "/api/lists/:id:"
|
||||||
|
},
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"card": "/api/lists/:id:/cards"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification":
|
||||||
|
{
|
||||||
|
"DELETE": null,
|
||||||
|
"GET":
|
||||||
|
{
|
||||||
|
"notifications": "/api/notifications",
|
||||||
|
"notification": "/api/notifications/:id:"
|
||||||
|
},
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"notification": "/api/notifications/:id:"
|
||||||
|
},
|
||||||
|
"POST": null
|
||||||
|
},
|
||||||
|
"project-manager":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"project-manager": "/api/project-managers/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH": null,
|
||||||
|
"POST": null
|
||||||
|
},
|
||||||
|
"project":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"project": "/api/projects/:id:"
|
||||||
|
},
|
||||||
|
"GET":
|
||||||
|
{
|
||||||
|
"projects": "/api/projects",
|
||||||
|
"project": "/api/projects/:id:"
|
||||||
|
},
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"project": "/api/projects/:id:"
|
||||||
|
},
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"project": "/api/projects",
|
||||||
|
"background-image": "/api/projects/:id:/background-image",
|
||||||
|
"project-manager": "/api/projects/:id:/managers",
|
||||||
|
"board": "/api/projects/:id:/boards"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"task":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"task": "/api/tasks/:id:"
|
||||||
|
},
|
||||||
|
"GET": null,
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"task": "/api/tasks/:id:"
|
||||||
|
},
|
||||||
|
"POST": null
|
||||||
|
},
|
||||||
|
"user":
|
||||||
|
{
|
||||||
|
"DELETE":
|
||||||
|
{
|
||||||
|
"user": "/api/users/:id:"
|
||||||
|
},
|
||||||
|
"GET":
|
||||||
|
{
|
||||||
|
"users": "/api/users",
|
||||||
|
"user": "/api/users/:id:"
|
||||||
|
},
|
||||||
|
"PATCH":
|
||||||
|
{
|
||||||
|
"user": "/api/users/:id:",
|
||||||
|
"user-email": "/api/users/:id:/email",
|
||||||
|
"user-password": "/api/users/:id:/password",
|
||||||
|
"user-username": "/api/users/:id:/username"
|
||||||
|
},
|
||||||
|
"POST":
|
||||||
|
{
|
||||||
|
"user": "/api/users",
|
||||||
|
"user-avatar": "/api/users/:id:/avatar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
143
config/planka_templates.json
Normal file
143
config/planka_templates.json
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
{
|
||||||
|
"project":
|
||||||
|
{
|
||||||
|
"name": "str"
|
||||||
|
},
|
||||||
|
"board":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"type": "str",
|
||||||
|
"position": "int"
|
||||||
|
},
|
||||||
|
"list":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"position": "int"
|
||||||
|
},
|
||||||
|
"card":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"description": "str",
|
||||||
|
"position": "int",
|
||||||
|
"dueDate": "str",
|
||||||
|
"stopwatch": "Stopwatch"
|
||||||
|
},
|
||||||
|
"task":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"isCompleted": "bool",
|
||||||
|
"position": "int"
|
||||||
|
},
|
||||||
|
"label":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"color": "str",
|
||||||
|
"position": "int"
|
||||||
|
},
|
||||||
|
"card-label":
|
||||||
|
{
|
||||||
|
"cardId": "int",
|
||||||
|
"labelId": "int"
|
||||||
|
},
|
||||||
|
"card-membership":
|
||||||
|
{
|
||||||
|
"cardId": "int",
|
||||||
|
"userId": "int"
|
||||||
|
},
|
||||||
|
"board-membership":
|
||||||
|
{
|
||||||
|
"boardId": "int",
|
||||||
|
"userId": "int"
|
||||||
|
},
|
||||||
|
"project-manager":
|
||||||
|
{
|
||||||
|
"projectId": "int",
|
||||||
|
"userId": "int"
|
||||||
|
},
|
||||||
|
"user":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"email": "str",
|
||||||
|
"password": "str",
|
||||||
|
"username": "str",
|
||||||
|
"phone": "str",
|
||||||
|
"organization": "str",
|
||||||
|
"subscribeToOwnCards": "bool"
|
||||||
|
},
|
||||||
|
"comment-action":
|
||||||
|
{
|
||||||
|
"cardId": "str",
|
||||||
|
"text": "str"
|
||||||
|
},
|
||||||
|
"attachment":
|
||||||
|
{
|
||||||
|
"cardId": "int",
|
||||||
|
"requestId": "int"
|
||||||
|
},
|
||||||
|
"stopwatch":
|
||||||
|
{
|
||||||
|
"startedAt": "str",
|
||||||
|
"total": "int"
|
||||||
|
},
|
||||||
|
"background":
|
||||||
|
{
|
||||||
|
"name": "str",
|
||||||
|
"type": "str"
|
||||||
|
},
|
||||||
|
"gradients":
|
||||||
|
[
|
||||||
|
"old-lime",
|
||||||
|
"ocean-dive",
|
||||||
|
"tzepesch-style",
|
||||||
|
"jungle-mesh",
|
||||||
|
"strawberry-dust",
|
||||||
|
"purple-rose",
|
||||||
|
"sun-scream",
|
||||||
|
"warm-rust",
|
||||||
|
"sky-change",
|
||||||
|
"green-eyes",
|
||||||
|
"blue-xchange",
|
||||||
|
"blood-orange",
|
||||||
|
"sour-peel",
|
||||||
|
"green-ninja",
|
||||||
|
"algae-green",
|
||||||
|
"coral-reef",
|
||||||
|
"steel-grey",
|
||||||
|
"heat-waves",
|
||||||
|
"velvet-lounge",
|
||||||
|
"purple-rain",
|
||||||
|
"blue-steel",
|
||||||
|
"blueish-curve",
|
||||||
|
"prism-light",
|
||||||
|
"green-mist",
|
||||||
|
"red-curtain"
|
||||||
|
],
|
||||||
|
"colors":
|
||||||
|
[
|
||||||
|
"berry-red",
|
||||||
|
"pumpkin-orange",
|
||||||
|
"lagoon-blue",
|
||||||
|
"pink-tulip",
|
||||||
|
"light-mud",
|
||||||
|
"orange-peel",
|
||||||
|
"bright-moss",
|
||||||
|
"antique-blue",
|
||||||
|
"dark-granite",
|
||||||
|
"lagune-blue",
|
||||||
|
"sunny-grass",
|
||||||
|
"morning-sky",
|
||||||
|
"light-orange",
|
||||||
|
"midnight-blue",
|
||||||
|
"tank-green",
|
||||||
|
"gun-metal",
|
||||||
|
"wet-moss",
|
||||||
|
"red-burgundy",
|
||||||
|
"light-concrete",
|
||||||
|
"apricot-red",
|
||||||
|
"desert-sand",
|
||||||
|
"navy-blue",
|
||||||
|
"egg-yellow",
|
||||||
|
"coral-green",
|
||||||
|
"light-cocoa"
|
||||||
|
]
|
||||||
|
}
|
359
controllers.py
Normal file
359
controllers.py
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
from plankapy import Planka
|
||||||
|
import time
|
||||||
|
|
||||||
|
OFFSET = 65535
|
||||||
|
REFRESH = 10 # Seconds
|
||||||
|
|
||||||
|
class Controller(object):
|
||||||
|
def __init__(self, instance:Planka, **kwargs:dict):
|
||||||
|
self.instance:Planka = instance
|
||||||
|
self.kwargs:dict = kwargs
|
||||||
|
self.template:dict = None
|
||||||
|
self.routes:dict = None
|
||||||
|
self.active:dict = None
|
||||||
|
|
||||||
|
def get_route(self, method:str, action:str) -> str:
|
||||||
|
"""Gets the routes for the controller
|
||||||
|
@return: Routes
|
||||||
|
"""
|
||||||
|
if self.routes == None:
|
||||||
|
raise Exception("Routes not loaded")
|
||||||
|
if method not in self.routes:
|
||||||
|
raise Exception(f"Invalid method {method} for route {action}")
|
||||||
|
return self.routes[method][action]
|
||||||
|
|
||||||
|
def parse_route(self, method:str=None, action:str=None ,id:str=None, parent:object=None, req_id:bool=False) -> str:
|
||||||
|
"""Generates a route string from parameters
|
||||||
|
@method: HTTP method
|
||||||
|
@action: HTTP action
|
||||||
|
@id(optional): ID to use in route
|
||||||
|
@parent: Parent controller
|
||||||
|
@req_id: Whether or not the route requires an ID
|
||||||
|
(Parent ID will be used if needed)
|
||||||
|
@return: Route string
|
||||||
|
"""
|
||||||
|
route = self.get_route(method, action)
|
||||||
|
if route.count(":id:") > 1:
|
||||||
|
if parent == None:
|
||||||
|
raise Exception(f"Parent required for route '{route}'")
|
||||||
|
route = route.replace(":id:", str(parent.active()["id"]), 1)
|
||||||
|
if req_id:
|
||||||
|
route = route.replace(":id:", str(id), 1)
|
||||||
|
return route
|
||||||
|
|
||||||
|
def get_active(self) -> dict:
|
||||||
|
"""Gets the active object for the controller
|
||||||
|
@return: Active object
|
||||||
|
"""
|
||||||
|
if self.active:
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def set_active(self, active:dict) -> dict:
|
||||||
|
"""Sets the active object for the controller
|
||||||
|
@active: Active object
|
||||||
|
@return: Previous active object
|
||||||
|
"""
|
||||||
|
old = self.active
|
||||||
|
self.active = active
|
||||||
|
return old
|
||||||
|
|
||||||
|
def clear_active(self) -> None:
|
||||||
|
"""Clears the active object for the controller
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
|
self.active = None
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def get_template(self) -> dict:
|
||||||
|
"""Gets the template for the controller
|
||||||
|
@return: Template
|
||||||
|
"""
|
||||||
|
raise NotImplementedError("get_template() not implemented")
|
||||||
|
|
||||||
|
def build(self) -> dict:
|
||||||
|
"""Builds the object to be sent to the Planka API
|
||||||
|
@return: Object to be sent to Planka API
|
||||||
|
"""
|
||||||
|
keys = list(self.template.keys())
|
||||||
|
for key in self.kwargs:
|
||||||
|
if key in self.template:
|
||||||
|
self.template[key] = self.kwargs[key]
|
||||||
|
keys.remove(key)
|
||||||
|
if len(keys) > 0:
|
||||||
|
for key in keys:
|
||||||
|
self.template[key] = None
|
||||||
|
return self.template
|
||||||
|
|
||||||
|
def create(self, **kwargs) -> dict:
|
||||||
|
"""Creates an object in Planka
|
||||||
|
@return: Object created in Planka
|
||||||
|
"""
|
||||||
|
self.active = self.instance.request("POST", self.parse_route(method="POST", **kwargs), data=self.build())
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def update(self, data:dict=None, **kwargs) -> dict:
|
||||||
|
"""Patches an object in Planka
|
||||||
|
@data: Data to patch
|
||||||
|
@return: Object patched in Planka
|
||||||
|
"""
|
||||||
|
return self.instance.request("PATCH", self.parse_route(method="PATCH", **kwargs), data=data)
|
||||||
|
|
||||||
|
def delete(self, **kwargs) -> None:
|
||||||
|
"""Deletes an object in Planka
|
||||||
|
@return: None
|
||||||
|
"""
|
||||||
|
return self.instance.request("DELETE", self.parse_route(method="DELETE", **kwargs))
|
||||||
|
|
||||||
|
def get(self, **kwargs) -> dict:
|
||||||
|
"""Gets an object by ID
|
||||||
|
@kwargs: Additional arguments passed to _parse_route()
|
||||||
|
: @id: ID of object
|
||||||
|
: @route_parent(str): The dictionary key for the route parent in planka_routes.json\n
|
||||||
|
: @route_key(str): The dictionary key for the route in planka_routes.json\n
|
||||||
|
: @parent(Controller): Parent controller object\n
|
||||||
|
: @req_id(bool): Whether or not the route requires an ID\n
|
||||||
|
@return: Object
|
||||||
|
"""
|
||||||
|
return self.instance.request("GET", self.parse_route(method="GET", **kwargs))
|
||||||
|
|
||||||
|
class Project(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["project"]
|
||||||
|
self.routes = self.instance.routes["project"]
|
||||||
|
self.project_dict = None
|
||||||
|
self.last_updated = None
|
||||||
|
self.active = {"name": None, "id": None, "content": None}
|
||||||
|
|
||||||
|
def create(self) -> dict:
|
||||||
|
if self.kwargs['name'] in self.get_project_names():
|
||||||
|
self.active=self.get_project_by_name(self.kwargs['name'])
|
||||||
|
print(Exception(f"Project '{self.kwargs['name']}' already exists, setting active project to '{self.kwargs['name']}'"))
|
||||||
|
return self.active
|
||||||
|
project_item = super().create(action="project")['item']
|
||||||
|
self.active['name'] = self.kwargs['name']
|
||||||
|
self.active['id'] = project_item['id']
|
||||||
|
self.active['content'] = None
|
||||||
|
self.get_project_dictionary()
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def delete(self, id:str=None) -> None:
|
||||||
|
if id == None:
|
||||||
|
id = self.active["id"]
|
||||||
|
deleted = super().delete(id=id, action="project", req_id=True)
|
||||||
|
self.get_project_dictionary()
|
||||||
|
return deleted
|
||||||
|
|
||||||
|
def update(self, id:str=None, data:dict=None) -> dict:
|
||||||
|
if id == None:
|
||||||
|
id = self.active["id"]
|
||||||
|
return super().update(id=id, action="project",data=data, req_id=True)
|
||||||
|
|
||||||
|
def set_active(self, name:str) -> dict:
|
||||||
|
active = self.get_project_by_name(name)
|
||||||
|
return super().set_active(active)
|
||||||
|
|
||||||
|
def get_project(self, id:str=None) -> dict:
|
||||||
|
if id == None:
|
||||||
|
id = self.active()["id"]
|
||||||
|
return super().get(id=id, action="project", req_id=True)['included']
|
||||||
|
|
||||||
|
def get_projects(self) -> list:
|
||||||
|
return super().get(action="projects")
|
||||||
|
|
||||||
|
def get_project_names(self):
|
||||||
|
if self.project_dict == None:
|
||||||
|
self.project_dict = self.get_project_dictionary()
|
||||||
|
return list(self.project_dict.keys())
|
||||||
|
|
||||||
|
def get_project_dictionary(self) -> dict:
|
||||||
|
if self.last_updated == None or time.time() - self.last_updated > REFRESH:
|
||||||
|
self.last_updated = time.time()
|
||||||
|
self.project_dict = self.get_project_dictionary()
|
||||||
|
self.project_dict = {project['name']: {"name": project['name'] ,"id": project['id'], "content":self.get_project(project['id'])} for project in self.get_projects()['items']}
|
||||||
|
return self.project_dict
|
||||||
|
|
||||||
|
def get_project_by_name(self, name:str=None) -> dict:
|
||||||
|
return self.get_project_dictionary()[name]
|
||||||
|
|
||||||
|
def get_project_boards(self, name:str=None) -> list:
|
||||||
|
if name == None:
|
||||||
|
name = self.active["name"]
|
||||||
|
return self.get_project_dictionary()[name]["content"]['boards']
|
||||||
|
|
||||||
|
def get_project_users(self, name:str=None) -> list:
|
||||||
|
if name == None:
|
||||||
|
name = self.active["name"]
|
||||||
|
return self.get_project_dictionary()[name]["content"]['users']
|
||||||
|
|
||||||
|
def get_project_board_memberships(self, name:str=None) -> list:
|
||||||
|
if name == None:
|
||||||
|
name = self.active["name"]
|
||||||
|
return self.get_project_dictionary()[name]["content"]['boardMemberships']
|
||||||
|
|
||||||
|
def get_project_managers(self, name:str=None) -> list:
|
||||||
|
if name == None:
|
||||||
|
name = self.active["name"]
|
||||||
|
return self.get_project_dictionary()[name]["content"]['projectManagers']
|
||||||
|
|
||||||
|
def get_project_board_names(self, name:str=None) -> list:
|
||||||
|
if name == None:
|
||||||
|
name = self.active["name"]
|
||||||
|
return [board['name'] for board in self.get_project_boards(name)]
|
||||||
|
|
||||||
|
class Board(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["board"]
|
||||||
|
self.routes = self.instance.routes["board"]
|
||||||
|
self.board_dict = None
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "content": None}
|
||||||
|
|
||||||
|
def set_project(self, project:str) -> dict:
|
||||||
|
self.active['project'] = project
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def set_active(self, active: dict) -> dict:
|
||||||
|
self.active["name"] = active["name"]
|
||||||
|
self.active["id"] = active["id"]
|
||||||
|
self.active["project"] = active["project"]
|
||||||
|
self.active["content"] = active["content"]
|
||||||
|
return self.active
|
||||||
|
|
||||||
|
def get_board(self, name:str=None, projectName:str=None, projectController:Project=None) -> dict:
|
||||||
|
if name == None and self.active["name"] != None:
|
||||||
|
name = self.active["name"]
|
||||||
|
if name == None:
|
||||||
|
raise Exception("No board provided")
|
||||||
|
if projectController == None:
|
||||||
|
projectController = Project(instance=self.instance)
|
||||||
|
if projectName == None and projectController.active["name"] != None:
|
||||||
|
projectName = projectController.active["name"]
|
||||||
|
if projectName == None:
|
||||||
|
raise Exception("No project provided")
|
||||||
|
valid_names = projectController.get_project_board_names(projectName)
|
||||||
|
if name not in valid_names:
|
||||||
|
raise Exception(f"Board '{name}' not found in project '{projectName}'")
|
||||||
|
board_id = [board for board in projectController.get_project_boards(projectName) if board['name'] == name][0]['id']
|
||||||
|
board = super().get(id=board_id, action="board", req_id=True)['item']
|
||||||
|
return self.get(id=board_id, action="board", req_id=True)
|
||||||
|
|
||||||
|
def get_boards(self, projectController:Project=None, name:str=None) -> list:
|
||||||
|
if name == None and projectController.active["name"] != None:
|
||||||
|
name = projectController.active["name"]
|
||||||
|
projectController.get_project_boards(name)
|
||||||
|
|
||||||
|
class List(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["list"]
|
||||||
|
self.routes = self.instance.routes["list"]
|
||||||
|
self.active = {"name": None, "id": None, "board": None ,"content": None}
|
||||||
|
|
||||||
|
class Stopwatch(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["stopwatch"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "card": None ,"content": None}
|
||||||
|
|
||||||
|
class Card(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["card"]
|
||||||
|
self.routes = self.instance.routes["card"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "list": None ,"content": None}
|
||||||
|
|
||||||
|
class Label(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["label"]
|
||||||
|
self.routes = self.instance.routes["label"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "list": None , "card": None ,"content": None}
|
||||||
|
|
||||||
|
class Task(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["task"]
|
||||||
|
self.routes = self.instance.routes["task"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "list": None , "card": None ,"content": None}
|
||||||
|
|
||||||
|
class CommentAction(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["comment-action"]
|
||||||
|
self.routes = self.instance.routes["comment-action"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "list": None , "card": None ,"content": None}
|
||||||
|
|
||||||
|
class Attachment(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["attachment"]
|
||||||
|
self.routes = self.instance.routes["attachment"]
|
||||||
|
|
||||||
|
class User(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["user"]
|
||||||
|
self.routes = self.instance.routes["user"]
|
||||||
|
self.active = {"name": None, "id": None, "content": None}
|
||||||
|
|
||||||
|
class CardMembership(Controller):
|
||||||
|
def __init__(self,instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["card-membership"]
|
||||||
|
self.routes = self.instance.routes["card-membership"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "list": None , "card": None ,"content": None}
|
||||||
|
|
||||||
|
class BoardMembership(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["board-membership"]
|
||||||
|
self.routes = self.instance.routes["board-membership"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "content": None}
|
||||||
|
|
||||||
|
class CardLabel(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["card-label"]
|
||||||
|
self.routes = self.instance.routes["label"]
|
||||||
|
self.active = {"name": None, "id": None, "project": None, "board": None , "list": None , "card": None ,"content": None}
|
||||||
|
|
||||||
|
class ProjectManager(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance = instance
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.template = self.instance.templates["project-manager"]
|
||||||
|
self.routes = self.instance.routes["project-manager"]
|
||||||
|
self.active = {"name": None, "id": None, "user": None ,"project": None, "content": None}
|
||||||
|
|
||||||
|
class Background(Controller):
|
||||||
|
def __init__(self, instance:Planka=None, **kwargs):
|
||||||
|
self.instance:Planka = instance
|
||||||
|
self.kwargs:dict = kwargs
|
||||||
|
self.template:dict = self.instance.templates["background"]
|
||||||
|
self.gradients:list = self.instance.templates["gradients"]
|
||||||
|
|
||||||
|
planka = Planka("http://planka.corp.finelines-engineering.com", "hwelch", "Fiber4u!")
|
||||||
|
|
||||||
|
projectController = Project(planka)
|
||||||
|
|
||||||
|
projectController.set_active("Management API")
|
||||||
|
|
||||||
|
boardController = Board(planka)
|
||||||
|
|
||||||
|
boards = projectController.get_project_boards()
|
||||||
|
|
||||||
|
boardController.get_board(name=boards[0]['name'], projectController=projectController)
|
841
plankapy.py
Normal file
841
plankapy.py
Normal file
|
@ -0,0 +1,841 @@
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
API_URL = "http://127.0.0.1:3000"
|
||||||
|
API_USER = "demo@demo.demo"
|
||||||
|
API_PASS = "demo"
|
||||||
|
OFFSET = 65535
|
||||||
|
|
||||||
|
class Planka:
|
||||||
|
"""API wrapper class for Planka
|
||||||
|
@url: URL of Planka instance
|
||||||
|
@username: Username of Planka user
|
||||||
|
@password: Password of Planka user
|
||||||
|
"""
|
||||||
|
def __init__(self, url:str, username:str, password:str, api_end="/api", routes="config/planka_routes.json", templates="config/planka_templates.json"):
|
||||||
|
self.url = url
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.api_end = api_end
|
||||||
|
self.auth = None
|
||||||
|
with open(routes) as f:
|
||||||
|
self.routes = json.load(f)
|
||||||
|
with open(templates) as f:
|
||||||
|
self.templates = json.load(f)
|
||||||
|
self.authenticate()
|
||||||
|
|
||||||
|
def deauthenticate(self) -> bool:
|
||||||
|
"""Deletes the auth token from the Planka API
|
||||||
|
@return: True if successful, False if not
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.request("DELETE", self.get_route("access-token", "DELETE", "active"))
|
||||||
|
self.auth = None
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def validate(self) -> bool:
|
||||||
|
"""Validates the Planka API connection
|
||||||
|
@return: True if successful, False if not
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.request("GET", "/*")
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def authenticate(self) -> bool:
|
||||||
|
"""Gets an auth token from the Planka API
|
||||||
|
@return: True if successful, False if not
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
request = requests.post(f"{self.url}{self.get_route('access-token', 'POST', 'active')}", data={'emailOrUsername': self.username, 'password': self.password})
|
||||||
|
self.auth = request.json()['item']
|
||||||
|
if self.auth == None:
|
||||||
|
raise Exception("Invalid API credentials")
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
raise Exception("Invalid API credentials")
|
||||||
|
|
||||||
|
def request(self, method:str, endpoint:str, data:dict=None) -> dict:
|
||||||
|
"""Makes a request to the Planka API
|
||||||
|
@method: HTTP method
|
||||||
|
@endpoint: API endpoint
|
||||||
|
@data: Data to send with request (default: None)
|
||||||
|
@return: JSON response from Planka API
|
||||||
|
"""
|
||||||
|
if self.auth == None:
|
||||||
|
self.authenticate()
|
||||||
|
headers = \
|
||||||
|
{
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": f"Bearer {self.auth}"
|
||||||
|
}
|
||||||
|
url = f"{self.url}{endpoint}"
|
||||||
|
response = requests.request(method, url, headers=headers, json=data)
|
||||||
|
|
||||||
|
if response.status_code == 401:
|
||||||
|
raise Exception("Invalid API credentials")
|
||||||
|
|
||||||
|
if response.status_code not in [200, 201]:
|
||||||
|
raise Exception(f"Failed to {method} {url} with status code {response.status_code}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
return response.json()
|
||||||
|
except:
|
||||||
|
raise Exception(f"Failed to parse response from {url}")
|
||||||
|
|
||||||
|
def get_route(self, controller:str, method:str, action:str) -> str:
|
||||||
|
"""Returns a route from the planka_routes.json file
|
||||||
|
@controller: Name of controller
|
||||||
|
@method: HTTP method
|
||||||
|
@action: Name of request action
|
||||||
|
@return: Route string
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self.routes[controller][method][action]
|
||||||
|
except:
|
||||||
|
raise Exception(f"Route not found: {controller} {method} {action}")
|
||||||
|
|
||||||
|
def get_template(self, template:str) -> dict:
|
||||||
|
"""Returns a template from the templates.json file
|
||||||
|
@template: Name of template to return
|
||||||
|
@return: Template dictionary
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self.templates[template]
|
||||||
|
except:
|
||||||
|
raise Exception(f"Template not found: {template}")
|
||||||
|
|
||||||
|
class Controller():
|
||||||
|
def __init__(self, instance:Planka) -> None:
|
||||||
|
"""Controller class for Planka API
|
||||||
|
@instance: Planka API instance
|
||||||
|
"""
|
||||||
|
self.instance = instance
|
||||||
|
self.template:dict = None
|
||||||
|
self.data:dict = None
|
||||||
|
self.response:dict = None
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""Returns a string representation of the controller object
|
||||||
|
@return: String representation of controller object
|
||||||
|
"""
|
||||||
|
return f"{type(self).__name__}:\n{json.dumps(self.data, sort_keys=True, indent=4)}"
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
"""Returns a string representation of the controller object
|
||||||
|
@return: String representation of controller object
|
||||||
|
"""
|
||||||
|
return f"<{type(self).__name__}({self.__class__.__bases__[0].__name__})>{self.__str__()}"
|
||||||
|
|
||||||
|
def build(self, **kwargs) -> dict:
|
||||||
|
"""Builds the controller data
|
||||||
|
@return: Controller data dictionary
|
||||||
|
"""
|
||||||
|
if kwargs == {}:
|
||||||
|
return kwargs
|
||||||
|
data = {}
|
||||||
|
valid_keys = self.template.keys()
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
if key in valid_keys:
|
||||||
|
data[key] = value
|
||||||
|
self.data = data
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def create(self, route:str, data:dict=None) -> dict:
|
||||||
|
"""Creates a new controller object (POST)
|
||||||
|
@route: Route for controller object POST request
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
self.response = self.instance.request("POST", route, data)
|
||||||
|
return self.response
|
||||||
|
|
||||||
|
def get(self, route:str) -> dict:
|
||||||
|
"""Gets a controller object (GET)
|
||||||
|
@route: Route for controller object GET request
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
return self.instance.request("GET", route)
|
||||||
|
|
||||||
|
def update(self, route:str, data:dict=None) -> dict:
|
||||||
|
"""Updates a controller object (PATCH)
|
||||||
|
@route: Route for controller object PATCH request
|
||||||
|
@oid: ID of controller object
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not self.data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before updating")
|
||||||
|
self.response = self.instance.request("PATCH", route, data=data)
|
||||||
|
return self.response
|
||||||
|
|
||||||
|
def delete(self, route:str) -> dict:
|
||||||
|
"""Deletes a controller object (DELETE)
|
||||||
|
@route: Route for controller object DELETE request
|
||||||
|
@oid: ID of controller object
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
return self.instance.request("DELETE", route)
|
||||||
|
|
||||||
|
def last_response(self) -> dict:
|
||||||
|
"""Returns the last response from the controller object
|
||||||
|
@return: Last response dictionary
|
||||||
|
"""
|
||||||
|
return self.response
|
||||||
|
|
||||||
|
class Project(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("project")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def get(self, name:str=None, oid:str=None) -> dict:
|
||||||
|
"""Gets a project by name
|
||||||
|
@oid: ID of project to get (optional)
|
||||||
|
@name: Name of project if None returns all projects
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if oid:
|
||||||
|
return super().get(f"/api/projects/{oid}")
|
||||||
|
prjs = super().get(f"/api/projects")
|
||||||
|
if not name:
|
||||||
|
return prjs
|
||||||
|
prj_names = [prj["name"] for prj in prjs["items"]]
|
||||||
|
if name not in prj_names:
|
||||||
|
raise Exception(f"Project {name} not found")
|
||||||
|
prj_id = [prj for prj in prjs["items"] if prj["name"] == name][0]["id"]
|
||||||
|
return super().get(f"/api/projects/{prj_id}")
|
||||||
|
|
||||||
|
def get_project_names(self) -> list:
|
||||||
|
"""Gets a list of project names
|
||||||
|
@return: List of project names
|
||||||
|
"""
|
||||||
|
return [prj["name"] for prj in self.get()['items']]
|
||||||
|
|
||||||
|
def create(self) -> dict:
|
||||||
|
"""Creates a new project
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if not self.data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
if self.data["name"] in [prj["name"] for prj in self.get()['items']]:
|
||||||
|
raise Exception(f"Project {self.data['name']} already exists")
|
||||||
|
return super().create("/api/projects")
|
||||||
|
|
||||||
|
def update(self, name:str) -> dict:
|
||||||
|
"""Updates a project
|
||||||
|
@name: Name of project to update
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
prj_id = prj_id = self.get(name)['item']['id']
|
||||||
|
return super().update(f"/api/projects/{prj_id}")
|
||||||
|
|
||||||
|
def delete(self, name:str) -> dict:
|
||||||
|
"""Deletes a project
|
||||||
|
@name: Name of project to delete
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
prj_id = self.get(name)['item']['id']
|
||||||
|
return super().delete(f"/api/projects/{prj_id}")
|
||||||
|
|
||||||
|
class Board(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("board")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def get(self, project_name:str=None, board_name:str=None, oid:str=None) -> dict:
|
||||||
|
"""Gets a board by name
|
||||||
|
@oid: ID of board to get (optonal)
|
||||||
|
@name: Name of board if None returns all boards
|
||||||
|
@project_name: Name of project to get boards from
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if oid:
|
||||||
|
return super().get(f"/api/boards/{oid}")
|
||||||
|
if not (project_name):
|
||||||
|
raise Exception("Please provide a project name")
|
||||||
|
prj_con = Project(self.instance)
|
||||||
|
prj = prj_con.get(project_name)
|
||||||
|
boards = prj["included"]["boards"]
|
||||||
|
if not board_name:
|
||||||
|
return boards
|
||||||
|
board_names = [board["name"] for board in boards]
|
||||||
|
if board_name not in board_names:
|
||||||
|
raise Exception(f"Board `{board_name}` not found")
|
||||||
|
board_id = [board for board in boards if board["name"] == board_name][0]["id"]
|
||||||
|
return super().get(f"/api/boards/{board_id}")
|
||||||
|
|
||||||
|
def create(self, project_name:str) -> dict:
|
||||||
|
"""Creates a new board
|
||||||
|
@prj_name: Name of project to create board in
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if self.data == None:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
prj_con = Project(self.instance)
|
||||||
|
prj_id = prj_con.get(project_name)['item']['id']
|
||||||
|
return super().create(f"/api/projects/{prj_id}/boards")
|
||||||
|
|
||||||
|
def update(self, project_name:str=None, board_name:str=None, data:dict=None, oid:str=None) -> dict:
|
||||||
|
"""Updates a board
|
||||||
|
@oid: ID of board to update (optional)
|
||||||
|
@project_name: Name of project to update board in
|
||||||
|
@board_name: Name of board to update
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before updating")
|
||||||
|
if oid:
|
||||||
|
return super().update(f"/api/boards/{oid}", data=data)
|
||||||
|
if not (project_name and board_name):
|
||||||
|
raise Exception("Please provide project and board names")
|
||||||
|
board_id = self.get(project_name, board_name)['item']['id']
|
||||||
|
return super().update(f"/api/boards/{board_id}", data=self.data)
|
||||||
|
|
||||||
|
def delete(self, project_name:str=None, board_name:str=None, oid:str=None):
|
||||||
|
"""Deletes a board
|
||||||
|
@oid: ID of board to delete (optional)
|
||||||
|
@project_name: Name of project to delete board in
|
||||||
|
@board_name: Name of board to delete
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
if oid:
|
||||||
|
return super().delete(f"/api/boards/{oid}")
|
||||||
|
if project_name == None:
|
||||||
|
raise Exception("Please provide a project name")
|
||||||
|
if board_name == None:
|
||||||
|
raise Exception("Please provide a board name")
|
||||||
|
board_id = self.get(project_name, board_name)['item']['id']
|
||||||
|
return super().delete(f"/api/boards/{board_id}")
|
||||||
|
|
||||||
|
class List(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("list")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def get(self, project_name:str=None, board_name:str=None, list_name:str=None):
|
||||||
|
"""Gets a list by name
|
||||||
|
NOTE: No GET route for list by ID
|
||||||
|
@project_name: Name of project to get list from
|
||||||
|
@board_name: Name of board to get list from
|
||||||
|
@list_name: Name of list to get
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if not (project_name and board_name):
|
||||||
|
raise Exception("Please provide project and board names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)
|
||||||
|
lists = board["included"]["lists"]
|
||||||
|
list_names = [lst["name"] for lst in lists]
|
||||||
|
if list_name == None:
|
||||||
|
return lists
|
||||||
|
if list_name not in list_names:
|
||||||
|
raise Exception(f"List `{list_name}` not found")
|
||||||
|
return [lst for lst in lists if lst["name"] == list_name][0]
|
||||||
|
|
||||||
|
def create(self, project_name:str=None, board_name:str=None, data:dict=None):
|
||||||
|
"""Creates a new list
|
||||||
|
@project_name: Name of project to create list in
|
||||||
|
@board_name: Name of board to create list in
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
if not (project_name and board_name):
|
||||||
|
raise Exception("Please provide project and board name")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board_id = board_con.get(project_name, board_name)['item']['id']
|
||||||
|
return super().create(f"/api/boards/{board_id}/lists")
|
||||||
|
|
||||||
|
def update(self, project_name:str=None, board_name:str=None, list_name:str=None, data:dict=None, oid:str=None):
|
||||||
|
"""Updates a list
|
||||||
|
@oid: ID of list to update (optional)
|
||||||
|
@project_name: Name of project to update list in
|
||||||
|
@board_name: Name of board to update list in
|
||||||
|
@list_name: Name of list to update
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before updating")
|
||||||
|
if oid:
|
||||||
|
return super().update(f"/api/lists/{oid}", data=data)
|
||||||
|
if not (project_name and board_name and list_name):
|
||||||
|
raise Exception("Please provide project, board, and list names")
|
||||||
|
lst = self.get(project_name, board_name, list_name)
|
||||||
|
return super().update(f"/api/lists/{lst['id']}", data=data)
|
||||||
|
|
||||||
|
def delete(self, project_name:str=None, board_name:str=None, list_name:str=None, oid:str=None):
|
||||||
|
"""Deletes a list
|
||||||
|
@oid: ID of list to delete (optional)
|
||||||
|
@project_name: Name of project to delete list in
|
||||||
|
@board_name: Name of board to delete list in
|
||||||
|
@list_name: Name of list to delete
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
if oid != None:
|
||||||
|
return super().delete(f"/api/lists/{oid}")
|
||||||
|
if not (project_name and board_name and list_name):
|
||||||
|
raise Exception("Please provide a project, board, and list names")
|
||||||
|
lst = self.get(project_name, board_name, list_name)
|
||||||
|
return super().delete(f"/api/lists/{lst['id']}")
|
||||||
|
|
||||||
|
class Card(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("card")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def get(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, oid:str=None):
|
||||||
|
"""Gets a card by name
|
||||||
|
@oid: ID of card to get (optional)
|
||||||
|
@project_name: Name of project to get card from
|
||||||
|
@board_name: Name of board to get card from
|
||||||
|
@list_name: Name of list to get card from
|
||||||
|
@card_name: Name of card to get
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if oid != None:
|
||||||
|
return super().get(f"/api/cards/{oid}")
|
||||||
|
if not (project_name and board_name and list_name):
|
||||||
|
raise Exception("Please provide project, board, and list names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)
|
||||||
|
lst_id = [ls for ls in board["included"]["lists"] if ls["name"] == list_name][0]["id"]
|
||||||
|
cards = [card for card in board["included"]["cards"] if card["listId"] == lst_id]
|
||||||
|
card_names = [card["name"] for card in cards]
|
||||||
|
if card_name == None:
|
||||||
|
return [self.get(oid=card["id"]) for card in cards]
|
||||||
|
if card_name not in card_names:
|
||||||
|
raise Exception(f"Card `{card_name}` not found")
|
||||||
|
card_id = [card for card in cards if card["name"] == card_name][0]['id']
|
||||||
|
return super().get(f"/api/cards/{card_id}")
|
||||||
|
|
||||||
|
def create(self, project_name:str=None, board_name:str=None, list_name:str=None, data:dict=None):
|
||||||
|
"""Creates a new card
|
||||||
|
@project_name: Name of project to create card in
|
||||||
|
@board_name: Name of board to create card in
|
||||||
|
@list_name: Name of list to create card in
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if data == None:
|
||||||
|
data = self.data
|
||||||
|
if data == None:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
if not (project_name and board_name and list_name):
|
||||||
|
raise Exception("Please provide a project, board and list names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)
|
||||||
|
lst_id = [ls for ls in board["included"]["lists"] if ls["name"] == list_name][0]["id"]
|
||||||
|
return super().create(f"/api/lists/{lst_id}/cards")
|
||||||
|
|
||||||
|
def delete(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, oid:str=None):
|
||||||
|
"""Deletes a card
|
||||||
|
@oid: ID of card to delete (optional)
|
||||||
|
@project_name: Name of project to delete card in
|
||||||
|
@board_name: Name of board to delete card in
|
||||||
|
@list_name: Name of list to delete card in
|
||||||
|
@card_name: Name of card to delete
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
if oid != None:
|
||||||
|
return super().delete(f"/api/cards/{oid}")
|
||||||
|
if not (project_name and board_name and list_name and card_name):
|
||||||
|
raise Exception("Please provide a project, board, list, and card name")
|
||||||
|
card = self.get(project_name, board_name, list_name, card_name)
|
||||||
|
return super().delete(f"/api/cards/{card['id']}")
|
||||||
|
|
||||||
|
def update(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, data:dict=None, oid:str=None):
|
||||||
|
"""Updates a card
|
||||||
|
@oid: ID of card to update (optional)
|
||||||
|
@project_name: Name of project to update card in
|
||||||
|
@board_name: Name of board to update card in
|
||||||
|
@list_name: Name of list to update card in
|
||||||
|
@card_name: Name of card to update
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before updating")
|
||||||
|
if oid:
|
||||||
|
return super().update(f"/api/cards/{oid}", data=data)
|
||||||
|
if not (project_name and board_name and list_name and card_name):
|
||||||
|
raise Exception("Please provide a project, board, list, and card name")
|
||||||
|
card = self.get(project_name, board_name, list_name, card_name)
|
||||||
|
return super().update(f"/api/cards/{card['id']}", data=data)
|
||||||
|
|
||||||
|
def get_labels(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, oid:str=None):
|
||||||
|
"""Gets labels for a card
|
||||||
|
@oid: ID of card to get labels from (optional)
|
||||||
|
@project_name: Name of project to get card from
|
||||||
|
@board_name: Name of board to get card from
|
||||||
|
@list_name: Name of list to get card from
|
||||||
|
@card_name: Name of card to get
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if oid:
|
||||||
|
return self.get(oid=oid)['included']['cardLabels']
|
||||||
|
if not (project_name and board_name and list_name and card_name):
|
||||||
|
raise Exception("Please provide project, board, list, and card names")
|
||||||
|
card_id = self.get(project_name, board_name, list_name, card_name)['item']['id']
|
||||||
|
return self.get(oid=card_id)['included']['cardLabels']
|
||||||
|
|
||||||
|
class Label(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("label")
|
||||||
|
self.options = instance.get_template("colors")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def colors(self) -> list:
|
||||||
|
return self.options
|
||||||
|
|
||||||
|
def get(self, project_name:str=None, board_name:str=None, label_name:str=None) -> dict:
|
||||||
|
"""Gets a label by name
|
||||||
|
@project_name: Name of project to get label from
|
||||||
|
@board_name: Name of board to get label from
|
||||||
|
@label_name: Name of label to get
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if not (project_name and board_name):
|
||||||
|
raise Exception("Please provide project and board names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)
|
||||||
|
labels = board["included"]["labels"]
|
||||||
|
label_names = [label["name"] for label in labels]
|
||||||
|
if not label_name:
|
||||||
|
return labels
|
||||||
|
if label_name not in label_names:
|
||||||
|
raise Exception(f"Label `{label_name}` not found")
|
||||||
|
return [label for label in labels if label["name"] == label_name][0]
|
||||||
|
|
||||||
|
def create(self, project_name:str=None, board_name:str=None, data:dict=None):
|
||||||
|
"""Creates a new label
|
||||||
|
@project_name: Name of project to create label in
|
||||||
|
@board_name: Name of board to create label in
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
if not (project_name and board_name):
|
||||||
|
raise Exception("Please provide project and board names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)['item']
|
||||||
|
return super().create(f"/api/boards/{board['id']}/labels")
|
||||||
|
|
||||||
|
def delete(self, project_name:str=None, board_name:str=None, label_name:str=None, oid:str=None):
|
||||||
|
"""Deletes a label
|
||||||
|
@oid: ID of label to delete (optional)
|
||||||
|
@project_name: Name of project to delete label from
|
||||||
|
@board_name: Name of board to delete label from
|
||||||
|
@label_name: Name of label to delete
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
if oid:
|
||||||
|
return super().delete(f"/api/labels/{oid}")
|
||||||
|
if not (project_name and board_name and label_name):
|
||||||
|
raise Exception("Please provide project, board, and label names")
|
||||||
|
label = self.get(project_name, board_name, label_name)
|
||||||
|
return super().delete(f"/api/labels/{label['id']}")
|
||||||
|
|
||||||
|
def add(self, project_name:str=None, board_name:str=None, list_name:str=None ,card_name:str=None, label_name:str=None, card_id:str=None, label_id:str=None):
|
||||||
|
"""Adds a label to a card
|
||||||
|
@project_name: Name of project to add label to card in
|
||||||
|
@board_name: Name of board to add label to card in
|
||||||
|
@label_name: Name of label to add to card
|
||||||
|
@card_name: Name of card to add label to
|
||||||
|
@list_name: Name of list to add label to card in
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if label_id and card_id:
|
||||||
|
return super().create(f"/api/cards/{card_id}/labels", data={"labelId":label_id})
|
||||||
|
if not (project_name and board_name and label_name):
|
||||||
|
raise Exception("Please provide a project, board, label name")
|
||||||
|
if card_id and label_name:
|
||||||
|
label = self.get(project_name, board_name, label_name)
|
||||||
|
return super().create(f"/api/cards/{card_id}/labels", data={"labelId":label['item']['id']})
|
||||||
|
if not (card_name and list_name):
|
||||||
|
raise Exception("Please provide a card and list name")
|
||||||
|
card_con = Card(self.instance)
|
||||||
|
card = card_con.get(project_name, board_name, list_name, card_name)
|
||||||
|
label = self.get(project_name, board_name, label_name)
|
||||||
|
return super().create(f"/api/cards/{card['item']['id']}/labels", {"labelId":label['item']['id']})
|
||||||
|
|
||||||
|
def remove(self, project_name:str=None, board_name:str=None, list_name:str=None ,card_name:str=None, label_name:str=None, card_id:str=None, label_id:str=None):
|
||||||
|
"""Removes a label from a card
|
||||||
|
@project_name: Name of project to remove label from card in
|
||||||
|
@board_name: Name of board to remove label from card in
|
||||||
|
@label_name: Name of label to remove from card
|
||||||
|
@card_name: Name of card to remove label from
|
||||||
|
@list_name: Name of list to remove label from card in
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
if label_id and card_id:
|
||||||
|
return super().delete(f"/api/cards/{card_id}/labels/{label_id}")
|
||||||
|
if not (project_name and board_name and label_name):
|
||||||
|
raise Exception("Please provide a project, board, label name")
|
||||||
|
if card_id and label_name:
|
||||||
|
label_id = [label['id'] for label in Card(self.instance).get_labels(oid=card_id) if label['name'] == label_name][0]
|
||||||
|
return super().delete(f"/api/cards/{card_id}/labels/{label['item']['id']}")
|
||||||
|
if not (card_name and list_name):
|
||||||
|
raise Exception("Please provide a card and list name")
|
||||||
|
card_con = Card(self.instance)
|
||||||
|
card = card_con.get(project_name, board_name, list_name, card_name)
|
||||||
|
label = self.get(project_name, board_name, label_name)
|
||||||
|
return super().delete(f"/api/cards/{card['item']['id']}/labels/{label['item']['id']}")
|
||||||
|
|
||||||
|
class Task(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("task")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def get(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, task_name:str=None) -> dict:
|
||||||
|
"""Gets a task by name
|
||||||
|
NOTE: No GET route for tasks by OID
|
||||||
|
@project_name: Name of project to get task from
|
||||||
|
@board_name: Name of board to get task from
|
||||||
|
@list_name: Name of list to get task from
|
||||||
|
@card_name: Name of card to get task from
|
||||||
|
@task_name: Name of task to get
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
if not (project_name and board_name and list_name and card_name):
|
||||||
|
raise Exception("Please provide project, board, list, and card names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)
|
||||||
|
list_id = [ls for ls in board["included"]["lists"] if ls["name"] == list_name][0]["id"]
|
||||||
|
cards = [card for card in board["included"]["cards"] if card["name"] == card_name and card["listId"] == list_id]
|
||||||
|
card_id = [card for card in cards if card["name"] == card_name][0]["id"]
|
||||||
|
tasks = [task for task in board["included"]["tasks"] if task["cardId"] == card_id]
|
||||||
|
task_names = [task["name"] for task in tasks]
|
||||||
|
if task_name == None:
|
||||||
|
return tasks
|
||||||
|
if task_name not in task_names:
|
||||||
|
raise Exception(f"Task `{task_name}` not found")
|
||||||
|
return [task for task in tasks if task["name"] == task_name][0]
|
||||||
|
|
||||||
|
def create(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, data:dict=None, card_id:str=None):
|
||||||
|
"""Creates a new task
|
||||||
|
@card_id: ID of card to create task in (optional)
|
||||||
|
@project_name: Name of project to create task in
|
||||||
|
@board_name: Name of board to create task in
|
||||||
|
@list_name: Name of list to create task in
|
||||||
|
@card_name: Name of card to create task in
|
||||||
|
@return: POST response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before creating")
|
||||||
|
if card_id:
|
||||||
|
return super().create(f"/api/cards/{card_id}/tasks")
|
||||||
|
if not (project_name and board_name and list_name and card_name):
|
||||||
|
raise Exception("Please provide project, board, list, and card names")
|
||||||
|
board_con = Board(self.instance)
|
||||||
|
board = board_con.get(project_name, board_name)
|
||||||
|
list_id = [ls for ls in board["included"]["lists"] if ls["name"] == list_name][0]["id"]
|
||||||
|
cards = [card for card in board["included"]["cards"] if card["name"] == card_name and card["listId"] == list_id]
|
||||||
|
card_id = [card for card in cards if card["name"] == card_name][0]["id"]
|
||||||
|
return super().create(f"/api/cards/{card_id}/tasks")
|
||||||
|
|
||||||
|
def update(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, task_name:str=None, data:dict=None, oid:str=None):
|
||||||
|
"""Updates a task
|
||||||
|
@oid: Object ID of task to update (optional)
|
||||||
|
@project_name: Name of project to update task in
|
||||||
|
@board_name: Name of board to update task in
|
||||||
|
@list_name: Name of list to update task in
|
||||||
|
@card_name: Name of card to update task in
|
||||||
|
@task_name: Name of task to update
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
if not data:
|
||||||
|
data = self.data
|
||||||
|
if not data:
|
||||||
|
raise Exception(f"Please Build a {type(self).__name__} before updating")
|
||||||
|
if oid:
|
||||||
|
return super().update(f"/api/tasks/{oid}")
|
||||||
|
if not (project_name and board_name and list_name and card_name and task_name):
|
||||||
|
raise Exception("Please provide project, board, list, card, and task names")
|
||||||
|
task = self.get(project_name, board_name, list_name, card_name, task_name)
|
||||||
|
return super().update(f"/api/tasks/{task['id']}")
|
||||||
|
|
||||||
|
def delete(self, project_name:str=None, board_name:str=None, list_name:str=None, card_name:str=None, task_name:str=None, oid:str=None):
|
||||||
|
"""Deletes a task
|
||||||
|
@oid: ID of task to delete (Use this if you already have the ID)
|
||||||
|
@project_name: Name of project to delete task from
|
||||||
|
@board_name: Name of board to delete task from
|
||||||
|
@list_name: Name of list to delete task from
|
||||||
|
@card_name: Name of card to delete task from
|
||||||
|
@task_name: Name of task to delete
|
||||||
|
@return: DELETE response dictionary
|
||||||
|
"""
|
||||||
|
if oid:
|
||||||
|
return super().delete(f"/api/tasks/{id}")
|
||||||
|
if not (project_name and board_name and list_name and card_name and task_name):
|
||||||
|
raise Exception("Please provide project, board, list, card, and task names")
|
||||||
|
task = self.get(project_name, board_name, list_name, card_name, task_name)
|
||||||
|
return super().delete(f"/api/tasks/{task['id']}")
|
||||||
|
|
||||||
|
class Attachment(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("attachment")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
class Stopwatch(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("stopwatch")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
class Background(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("background")
|
||||||
|
self.options = instance.get_template("gradients")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def gradients(self) -> dict:
|
||||||
|
"""Gets all gradients
|
||||||
|
@return: GET response dictionary
|
||||||
|
"""
|
||||||
|
return self.options
|
||||||
|
|
||||||
|
def apply(self, prj_name:str):
|
||||||
|
"""Applies a gradient to a project
|
||||||
|
@project: Name of project to apply gradient to
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
project = Project(self.instance)
|
||||||
|
prj_id = project.get(prj_name)["item"]["id"]
|
||||||
|
if "type" not in self.data.keys():
|
||||||
|
raise Exception("Please specify a background type: `gradient` | `image`")
|
||||||
|
if self.data["type"] == "gradient" and self.data["name"] not in self.options:
|
||||||
|
raise Exception(f"Gradient {self.data['name']} not found: please choose from\n{self.options}")
|
||||||
|
return super().update(f"/api/projects/{prj_id}", data={"background": self.data})
|
||||||
|
|
||||||
|
def clear(self, prj_name:str):
|
||||||
|
"""Clears a gradient from a project
|
||||||
|
@project: Name of project to clear gradient from
|
||||||
|
@return: PATCH response dictionary
|
||||||
|
"""
|
||||||
|
project = Project(self.instance)
|
||||||
|
prj_id = project.get(prj_name)["item"]["id"]
|
||||||
|
return super().update(f"/api/projects/{prj_id}", data={"background": None})
|
||||||
|
|
||||||
|
class Comment(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("comment-action")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
class User(Controller):
|
||||||
|
def __init__(self, instance:Planka, **kwargs) -> None:
|
||||||
|
self.instance = instance
|
||||||
|
self.template = instance.get_template("user")
|
||||||
|
self.data = self.build(**kwargs)
|
||||||
|
|
||||||
|
def test_planka():
|
||||||
|
import random
|
||||||
|
planka = Planka(API_URL, API_USER, API_PASS)
|
||||||
|
project = Project(planka)
|
||||||
|
board = Board(planka)
|
||||||
|
lst = List(planka)
|
||||||
|
card = Card(planka)
|
||||||
|
label = Label(planka)
|
||||||
|
task = Task(planka)
|
||||||
|
attachment = Attachment(planka)
|
||||||
|
stopwatch = Stopwatch(planka)
|
||||||
|
background = Background(planka)
|
||||||
|
comment = Comment(planka)
|
||||||
|
user = User(planka)
|
||||||
|
|
||||||
|
if "Plankapy Test Project" in [prj["name"] for prj in project.get()["items"]]:
|
||||||
|
project.delete("Plankapy Test Project")
|
||||||
|
|
||||||
|
|
||||||
|
project.build(name="Plankapy Test Project")
|
||||||
|
project.create()
|
||||||
|
print("Created Test Project")
|
||||||
|
|
||||||
|
board.build(name="Test Board", type="kanban", position=OFFSET)
|
||||||
|
board.create("Plankapy Test Project")
|
||||||
|
print("Created Test Board")
|
||||||
|
|
||||||
|
next_pos = OFFSET
|
||||||
|
new_labels = []
|
||||||
|
for color in label.colors():
|
||||||
|
label.build(name=f"{color} label", color=color, position=next_pos)
|
||||||
|
new_labels.append(label.create("Plankapy Test Project", "Test Board")["item"])
|
||||||
|
next_pos += OFFSET
|
||||||
|
print(f"Created {color} Label")
|
||||||
|
lst.build(name="Test List", position=0)
|
||||||
|
lst.create("Plankapy Test Project", "Test Board")
|
||||||
|
print("Created Test List")
|
||||||
|
|
||||||
|
new_cards=[]
|
||||||
|
next_pos = OFFSET
|
||||||
|
for i in range(1, 11):
|
||||||
|
card.build(name=f"Test Card {i}", description=f"CHANGE ME {i}", position=next_pos)
|
||||||
|
next_pos += OFFSET
|
||||||
|
new_cards.append(card.create("Plankapy Test Project", "Test Board", "Test List")["item"])
|
||||||
|
print(f"Created Test Card {i}")
|
||||||
|
|
||||||
|
for cd in new_cards:
|
||||||
|
lb = random.choice(new_labels)
|
||||||
|
label.add(label_id=lb["id"], card_id=cd["id"])
|
||||||
|
print("added random labels to cards")
|
||||||
|
|
||||||
|
for i in range(int(len(new_cards)/2)):
|
||||||
|
cd = random.choice(new_cards)
|
||||||
|
lbs = card.get_labels("Plankapy Test Project", "Test Board", oid=cd["id"])
|
||||||
|
for lb in lbs:
|
||||||
|
print(lb)
|
||||||
|
label.remove(label_id=lb["labelId"], card_id=lb["cardId"])
|
||||||
|
print(f"removed label from {cd['name']}")
|
||||||
|
print("removed random labels from half the cards")
|
||||||
|
|
||||||
|
new_tasks=[]
|
||||||
|
for cd in new_cards:
|
||||||
|
next_pos=OFFSET
|
||||||
|
for i in range(1,5):
|
||||||
|
task.build(name=f"Test Task {i}", position=next_pos)
|
||||||
|
next_pos += OFFSET
|
||||||
|
print(cd)
|
||||||
|
new_tasks.append(task.create(card_id=cd["id"])["item"])
|
||||||
|
print(f"Created 4 tasks on {cd['name']}")
|
||||||
|
|
||||||
|
for tsk in new_tasks:
|
||||||
|
print(tsk)
|
||||||
|
task.build(name=f"Updated Task: {tsk['name']}", isCompleted=True)
|
||||||
|
task.update(oid=tsk["id"])
|
||||||
|
print("Updated task all tasks")
|
||||||
|
|
||||||
|
for grad in background.gradients():
|
||||||
|
grad = grad
|
||||||
|
background.build(name=grad, type="gradient")
|
||||||
|
background.apply("Plankapy Test Project")
|
||||||
|
print(f"Applied gradient {grad} to Test Project")
|
||||||
|
|
||||||
|
background.clear("Plankapy Test Project")
|
||||||
|
print("Cleared gradient from Test Project")
|
||||||
|
print("Tests complete")
|
41
tests/plankapy_tests.py
Normal file
41
tests/plankapy_tests.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from plankapy import Planka
|
||||||
|
from controllers import Project, Board, Card, List, Stopwatch, Label, Task, CommentAction, Attachment, User, CardMembership, BoardMembership, CardLabel, ProjectManager, Background
|
||||||
|
|
||||||
|
API_URL = "http://planka.corp.finelines-engineering.com"
|
||||||
|
API_USER = "hwelch"
|
||||||
|
API_PASS = "Fiber4u!"
|
||||||
|
|
||||||
|
planka = Planka(API_URL, API_USER, API_PASS)
|
||||||
|
|
||||||
|
ProjectController = Project(instance=planka, name="Test Project 2", description="Test Project Description")
|
||||||
|
BoardController = Board(instance=planka)
|
||||||
|
CardController = Card(instance=planka)
|
||||||
|
ListController = List(instance=planka)
|
||||||
|
StopwatchController = Stopwatch(instance=planka)
|
||||||
|
LabelController = Label(instance=planka)
|
||||||
|
TaskController = Task(instance=planka)
|
||||||
|
CommentActionController = CommentAction(instance=planka)
|
||||||
|
AttachmentController = Attachment(instance=planka)
|
||||||
|
UserController = User(instance=planka)
|
||||||
|
CardMembershipController = CardMembership(instance=planka)
|
||||||
|
BoardMembershipController = BoardMembership(instance=planka)
|
||||||
|
CardLabelController = CardLabel(instance=planka)
|
||||||
|
ProjectManagerController = ProjectManager(instance=planka)
|
||||||
|
BackgroundController = Background(instance=planka, name = "sky-change", type="gradient")
|
||||||
|
|
||||||
|
print(f"Project:\n\t{ProjectController.build()}")
|
||||||
|
print(f"Board:\n\t{BoardController.build()}")
|
||||||
|
print(f"Card:\n\t{CardController.build()}")
|
||||||
|
print(f"List:\n\t{ListController.build()}")
|
||||||
|
print(f"Stopwatch:\n\t{StopwatchController.build()}")
|
||||||
|
print(f"Label:\n\t{LabelController.build()}")
|
||||||
|
print(f"Task:\n\t{TaskController.build()}")
|
||||||
|
print(f"CommentAction:\n\t{CommentActionController.build()}")
|
||||||
|
print(f"Attachment:\n\t{AttachmentController.build()}")
|
||||||
|
print(f"User:\n\t{UserController.build()}")
|
||||||
|
print(f"CardMembership:\n\t{CardMembershipController.build()}")
|
||||||
|
print(f"BoardMembership:\n\t{BoardMembershipController.build()}")
|
||||||
|
print(f"CardLabel:\n\t{CardLabelController.build()}")
|
||||||
|
print(f"ProjectManager:\n\t{ProjectManagerController.build()}")
|
||||||
|
print(f"Background:\n\t{BackgroundController.build()}")
|
Loading…
Reference in a new issue