You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
6.5 KiB

10 years ago
8 years ago
5 years ago
6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
5 years ago
  1. from django.contrib import admin
  2. from django.contrib.auth.admin import UserAdmin
  3. from django.contrib.auth.models import User
  4. from django.db.models import Count, F
  5. from django.template.loader import render_to_string
  6. from django.urls import reverse
  7. from django.utils.html import escape
  8. from django.utils.safestring import mark_safe
  9. from hc.accounts.models import Credential, Profile, Project
  10. @mark_safe
  11. def _format_usage(num_checks, num_channels):
  12. result = ""
  13. if num_checks == 0:
  14. result += "0 checks, "
  15. elif num_checks == 1:
  16. result += "1 check, "
  17. else:
  18. result += f"<strong>{num_checks} checks</strong>, "
  19. if num_channels == 0:
  20. result += "0 channels"
  21. elif num_channels == 1:
  22. result += "1 channel"
  23. else:
  24. result += f"<strong>{num_channels} channels</strong>"
  25. return result
  26. class Fieldset:
  27. name = None
  28. fields = []
  29. @classmethod
  30. def tuple(cls):
  31. return (cls.name, {"fields": cls.fields})
  32. class ProfileFieldset(Fieldset):
  33. name = "User Profile"
  34. fields = (
  35. "email",
  36. "reports",
  37. "tz",
  38. "theme",
  39. "next_report_date",
  40. "nag_period",
  41. "next_nag_date",
  42. "deletion_notice_date",
  43. "token",
  44. "sort",
  45. )
  46. class TeamFieldset(Fieldset):
  47. name = "Team"
  48. fields = (
  49. "team_limit",
  50. "check_limit",
  51. "ping_log_limit",
  52. "sms_limit",
  53. "sms_sent",
  54. "last_sms_date",
  55. "call_limit",
  56. "calls_sent",
  57. "last_call_date",
  58. )
  59. class NumChecksFilter(admin.SimpleListFilter):
  60. title = "check count"
  61. parameter_name = "num_checks"
  62. def lookups(self, request, model_admin):
  63. return (
  64. ("10", "more than 10"),
  65. ("20", "more than 20"),
  66. ("50", "more than 50"),
  67. ("100", "more than 100"),
  68. ("500", "more than 500"),
  69. ("1000", "more than 1000"),
  70. )
  71. def queryset(self, request, queryset):
  72. if not self.value():
  73. return
  74. value = int(self.value())
  75. return queryset.filter(num_checks__gt=value)
  76. @admin.register(Profile)
  77. class ProfileAdmin(admin.ModelAdmin):
  78. class Media:
  79. css = {"all": ("css/admin/profiles.css",)}
  80. readonly_fields = ("user", "email")
  81. search_fields = ["id", "user__email"]
  82. list_per_page = 30
  83. list_select_related = ("user",)
  84. list_display = (
  85. "id",
  86. "email",
  87. "checks",
  88. "date_joined",
  89. "last_active_date",
  90. "projects",
  91. "invited",
  92. "sms",
  93. "reports",
  94. )
  95. list_filter = (
  96. "user__date_joined",
  97. "last_active_date",
  98. "reports",
  99. "check_limit",
  100. NumChecksFilter,
  101. "theme",
  102. )
  103. fieldsets = (ProfileFieldset.tuple(), TeamFieldset.tuple())
  104. def get_queryset(self, request):
  105. qs = super(ProfileAdmin, self).get_queryset(request)
  106. qs = qs.prefetch_related("user__project_set")
  107. qs = qs.annotate(num_members=Count("user__project__member", distinct=True))
  108. qs = qs.annotate(num_checks=Count("user__project__check", distinct=True))
  109. qs = qs.annotate(plan=F("user__subscription__plan_name"))
  110. return qs
  111. @mark_safe
  112. def email(self, obj):
  113. s = escape(obj.user.email)
  114. if obj.plan:
  115. s = "%s <span>%s</span>" % (s, obj.plan)
  116. return s
  117. def date_joined(self, obj):
  118. return obj.user.date_joined
  119. @mark_safe
  120. def projects(self, obj):
  121. return render_to_string("admin/profile_list_projects.html", {"profile": obj})
  122. @mark_safe
  123. def checks(self, obj):
  124. s = "%d of %d" % (obj.num_checks, obj.check_limit)
  125. if obj.num_checks > 1:
  126. s = "<b>%s</b>" % s
  127. return s
  128. def invited(self, obj):
  129. return "%d of %d" % (obj.num_members, obj.team_limit)
  130. def sms(self, obj):
  131. return "%d of %d" % (obj.sms_sent, obj.sms_limit)
  132. @admin.register(Project)
  133. class ProjectAdmin(admin.ModelAdmin):
  134. readonly_fields = ("code", "owner")
  135. list_select_related = ("owner",)
  136. list_display = ("id", "name_", "users", "usage", "switch")
  137. search_fields = ["id", "name", "owner__email"]
  138. class Media:
  139. css = {"all": ("css/admin/projects.css",)}
  140. def get_queryset(self, request):
  141. qs = super(ProjectAdmin, self).get_queryset(request)
  142. qs = qs.annotate(num_channels=Count("channel", distinct=True))
  143. qs = qs.annotate(num_checks=Count("check", distinct=True))
  144. qs = qs.annotate(num_members=Count("member", distinct=True))
  145. return qs
  146. def name_(self, obj):
  147. if obj.name:
  148. return obj.name
  149. return "Default Project for %s" % obj.owner.email
  150. @mark_safe
  151. def users(self, obj):
  152. if obj.num_members == 0:
  153. return obj.owner.email
  154. else:
  155. return render_to_string("admin/project_list_team.html", {"project": obj})
  156. def email(self, obj):
  157. return obj.owner.email
  158. def usage(self, obj):
  159. return _format_usage(obj.num_checks, obj.num_channels)
  160. @mark_safe
  161. def switch(self, obj):
  162. url = reverse("hc-checks", args=[obj.code])
  163. return "<a href='%s'>Show Checks</a>" % url
  164. class HcUserAdmin(UserAdmin):
  165. actions = ["send_report", "send_nag"]
  166. list_display = (
  167. "id",
  168. "email",
  169. "usage",
  170. "date_joined",
  171. "last_login",
  172. "is_staff",
  173. )
  174. list_display_links = ("id", "email")
  175. list_filter = ("last_login", "date_joined", "is_staff", "is_active")
  176. ordering = ["-id"]
  177. def get_queryset(self, request):
  178. qs = super().get_queryset(request)
  179. qs = qs.annotate(num_checks=Count("project__check", distinct=True))
  180. qs = qs.annotate(num_channels=Count("project__channel", distinct=True))
  181. return qs
  182. @mark_safe
  183. def usage(self, user):
  184. return _format_usage(user.num_checks, user.num_channels)
  185. def send_report(self, request, qs):
  186. for user in qs:
  187. user.profile.send_report()
  188. self.message_user(request, "%d email(s) sent" % qs.count())
  189. def send_nag(self, request, qs):
  190. for user in qs:
  191. user.profile.send_report(nag=True)
  192. self.message_user(request, "%d email(s) sent" % qs.count())
  193. admin.site.unregister(User)
  194. admin.site.register(User, HcUserAdmin)
  195. @admin.register(Credential)
  196. class CredentialAdmin(admin.ModelAdmin):
  197. list_display = ("id", "created", "email", "name")
  198. search_fields = ["id", "code", "name", "user__email"]
  199. list_filter = ["created"]
  200. def email(self, obj):
  201. return obj.user.email