project.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. # encoding=utf-8
  2. import datetime
  3. import logging
  4. import time
  5. from sqlalchemy.exc import IntegrityError
  6. from tornado.web import HTTPError
  7. import tornado.web
  8. from terroroftinytown.tracker.base import BaseHandler
  9. from terroroftinytown.tracker.form import AddProjectForm, ProjectSettingsForm, \
  10. QueueSettingsForm, ConfirmForm, \
  11. AddItemsForm, ReleaseClaimForm, ItemActionForm, QueueEnableForm
  12. from terroroftinytown.tracker.model import Project, Item, Budget
  13. from terroroftinytown.tracker.stats import Stats
  14. logger = logging.getLogger(__name__)
  15. class AllProjectsHandler(BaseHandler):
  16. @tornado.web.authenticated
  17. def get(self):
  18. add_project_form = AddProjectForm()
  19. projects = Project.all_project_infos()
  20. self.render(
  21. 'admin/project/all.html',
  22. projects=projects,
  23. add_project_form=add_project_form,
  24. project_budgets=Budget.projects,
  25. project_stats=Stats.instance.get_project(),
  26. )
  27. @tornado.web.authenticated
  28. def post(self):
  29. action = self.get_argument('action')
  30. message = None
  31. if action != 'add_project':
  32. raise HTTPError(400, 'Unknown action')
  33. add_project_form = AddProjectForm(self.request.arguments)
  34. if add_project_form.validate():
  35. name = add_project_form.name.data
  36. try:
  37. Project.new_project(name)
  38. except IntegrityError:
  39. message = 'Project already exists.'
  40. else:
  41. logger.info(self.user_audit_text('Created project %s'), name)
  42. self.redirect(self.reverse_url('project.overview', name))
  43. return
  44. else:
  45. message = 'Error'
  46. self.render(
  47. 'admin/project/all.html',
  48. add_project_form=add_project_form,
  49. projects=Project.all_project_infos(),
  50. message=message,
  51. project_budgets=Budget.projects,
  52. )
  53. class ProjectHandler(BaseHandler):
  54. @tornado.web.authenticated
  55. def get(self, project_id):
  56. # Nothing useful to show for now
  57. self.redirect(self.reverse_url('project.claims', project_id))
  58. # self.render('admin/project/overview.html', project_id=name)
  59. class QueueHandler(BaseHandler):
  60. @tornado.web.authenticated
  61. def get(self, project_id):
  62. project = Project.get_plain(project_id)
  63. enable_form = QueueEnableForm(data=self.get_enable_form(project))
  64. form = QueueSettingsForm(data=self.get_queue_settings_form(project))
  65. self.render(
  66. 'admin/project/queue_settings.html',
  67. project_id=project_id,
  68. lower_shortcode=project.lower_shortcode(),
  69. form=form,
  70. enable_form=enable_form
  71. )
  72. @tornado.web.authenticated
  73. def post(self, project_id):
  74. project = Project.get_plain(project_id)
  75. enable_form = QueueEnableForm(data=self.get_enable_form(project))
  76. form = QueueSettingsForm(data=self.get_queue_settings_form(project))
  77. lower_shortcode = project.lower_shortcode()
  78. message = None
  79. action = self.get_argument('action', None)
  80. if action == 'enable':
  81. enable_form = QueueEnableForm(self.request.arguments)
  82. if enable_form.validate():
  83. with Project.get_session_object(project_id) as project:
  84. project.enabled = enable_form.enabled.data
  85. logger.info(self.user_audit_text('Project %s enabled=%s'),
  86. project_id, project.enabled)
  87. message = ('Enabled' if project.enabled else 'Disabled')
  88. else:
  89. message = 'Error in Queue Enable Form.'
  90. elif action == 'autoqueue':
  91. form = QueueSettingsForm(self.request.arguments)
  92. if form.validate():
  93. with Project.get_session_object(project_id) as project:
  94. form.populate_obj(project)
  95. project.lower_sequence_num = form.lower_sequence_num.data or 0
  96. project.autorelease_time = form.autorelease_time.data * 60 or 0
  97. lower_shortcode = project.lower_shortcode()
  98. logger.debug('Project %s queue settings changed.', project_id)
  99. message = 'Settings saved.'
  100. else:
  101. message = 'Error in Auto Queue Form.'
  102. else:
  103. message = 'Error: unrecognized action argument.'
  104. Budget.calculate_budgets()
  105. self.render(
  106. 'admin/project/queue_settings.html',
  107. project_id=project_id,
  108. lower_shortcode=lower_shortcode,
  109. form=form,
  110. enable_form=enable_form,
  111. message=message
  112. )
  113. def get_enable_form(self, project):
  114. return {
  115. 'enabled': project.enabled,
  116. }
  117. def get_queue_settings_form(self, project):
  118. return {
  119. 'autoqueue': project.autoqueue,
  120. 'num_count_per_item': project.num_count_per_item,
  121. 'max_num_items': project.max_num_items,
  122. 'lower_sequence_num': project.lower_sequence_num,
  123. 'autorelease_time': project.autorelease_time // 60
  124. }
  125. class ClaimsHandler(BaseHandler):
  126. @tornado.web.authenticated
  127. def get(self, project_id):
  128. delete_form = ConfirmForm()
  129. manual_add_form = AddItemsForm()
  130. release_form = ReleaseClaimForm()
  131. item_action_form = ItemActionForm()
  132. items = Item.get_items(project_id)
  133. self.render(
  134. 'admin/project/claims.html', project_id=project_id,
  135. delete_form=delete_form,
  136. manual_add_form=manual_add_form,
  137. release_form=release_form,
  138. item_action_form=item_action_form,
  139. items=items,
  140. )
  141. @tornado.web.authenticated
  142. def post(self, project_id):
  143. delete_form = ConfirmForm(self.request.arguments)
  144. manual_add_form = AddItemsForm(self.request.arguments)
  145. release_form = ReleaseClaimForm(self.request.arguments)
  146. item_action_form = ItemActionForm(self.request.arguments)
  147. items = Item.get_items(project_id)
  148. action = self.get_argument('action')
  149. if action == 'manual_add' and manual_add_form.validate():
  150. self._add_items(project_id)
  151. self.redirect(self.reverse_url('project.claims', project_id))
  152. return
  153. elif action == 'delete_one' and item_action_form.validate():
  154. self._delete_one()
  155. self.redirect(self.reverse_url('project.claims', project_id))
  156. return
  157. elif action == 'release_one' and item_action_form.validate():
  158. self._release_one()
  159. self.redirect(self.reverse_url('project.claims', project_id))
  160. return
  161. elif action == 'release' and release_form.validate():
  162. self._release_all(project_id, release_form)
  163. self.redirect(self.reverse_url('project.claims', project_id))
  164. elif action == 'delete' and delete_form.validate():
  165. self._delete_all(project_id)
  166. self.redirect(self.reverse_url('project.claims', project_id))
  167. return
  168. self.render(
  169. 'admin/project/claims.html', project_id=project_id,
  170. delete_form=delete_form,
  171. manual_add_form=manual_add_form,
  172. release_form=release_form,
  173. item_action_form=item_action_form,
  174. items=items,
  175. )
  176. def _add_items(self, project_id):
  177. items = self.get_argument('items').split()
  178. seq_list = []
  179. for item in items:
  180. logger.info(self.user_audit_text('Adding to project %s item'),
  181. project_id)
  182. lower_seq_num, upper_seq_num = item.split('-')
  183. lower_seq_num = int(lower_seq_num)
  184. upper_seq_num = int(upper_seq_num)
  185. seq_list.append((lower_seq_num, upper_seq_num))
  186. Item.add_items(project_id, seq_list)
  187. Budget.calculate_budgets()
  188. def _delete_one(self):
  189. item_id = int(self.get_argument('id'))
  190. Item.delete(item_id)
  191. Budget.calculate_budgets()
  192. logger.info(self.user_audit_text('Deleted item %s'), item_id)
  193. def _release_one(self):
  194. item_id = int(self.get_argument('id'))
  195. Item.release(item_id)
  196. Budget.calculate_budgets()
  197. logger.info(self.user_audit_text('Released item %s'), item_id)
  198. def _release_all(self, project_id, release_form):
  199. time_ago = time.time() - release_form.hours.data * 60
  200. Item.release_all(project_id, datetime.datetime.utcfromtimestamp(time_ago))
  201. Budget.calculate_budgets()
  202. logger.info(self.user_audit_text('Released items for %s'), project_id)
  203. def _delete_all(self, project_id):
  204. Item.delete_all(project_id)
  205. Budget.calculate_budgets()
  206. logger.info(self.user_audit_text('Delete all items for %s'), project_id)
  207. class SettingsHandler(BaseHandler):
  208. @tornado.web.authenticated
  209. def get(self, project_id):
  210. project = Project.get_plain(project_id)
  211. form = ProjectSettingsForm(**project.to_dict())
  212. self.render(
  213. 'admin/project/shortener_settings.html',
  214. project_id=project_id, form=form,
  215. )
  216. @tornado.web.authenticated
  217. def post(self, project_id):
  218. form = ProjectSettingsForm(self.request.arguments)
  219. message = None
  220. if form.validate():
  221. with Project.get_session_object(project_id) as project:
  222. form.populate_obj(project)
  223. logger.info(
  224. self.user_audit_text('Changed project %s shortener settings'),
  225. project_id)
  226. message = 'Settings saved.'
  227. else:
  228. message = 'Error.'
  229. self.render(
  230. 'admin/project/shortener_settings.html',
  231. project_id=project_id, form=form,
  232. message=message
  233. )
  234. class DeleteHandler(BaseHandler):
  235. @tornado.web.authenticated
  236. def get(self, project_id):
  237. form = ConfirmForm()
  238. self.render('admin/project/delete.html', project_id=project_id, form=form)
  239. @tornado.web.authenticated
  240. def post(self, project_id):
  241. form = ConfirmForm(self.request.arguments)
  242. if form.validate():
  243. Project.delete_project(project_id)
  244. Budget.calculate_budgets()
  245. logger.info(self.user_audit_text('Deleted project %s'), project_id)
  246. self.redirect(self.reverse_url('admin.overview'))
  247. else:
  248. self.render('admin/project/delete.html', project_id=project_id, form=form)