1from functools import cached_property
2
3from plain.admin.cards import Card
4from plain.admin.views import (
5 AdminModelDetailView,
6 AdminModelListView,
7 AdminModelUpdateView,
8 AdminViewset,
9 register_viewset,
10)
11from plain.models import QuerySet
12from plain.models.forms import ModelForm
13from plain.preflight import PreflightResult
14
15from .models import Flag, FlagResult
16
17
18class UnusedFlagsCard(Card):
19 title = "Unused Flags"
20
21 @cached_property
22 def flag_errors(self) -> list[PreflightResult]:
23 return Flag.preflight()
24
25 def get_number(self) -> int:
26 return len(self.flag_errors)
27
28 def get_text(self) -> str:
29 return "\n".join(str(e.fix) for e in self.flag_errors)
30
31
32@register_viewset
33class FlagAdmin(AdminViewset):
34 class ListView(AdminModelListView):
35 model = Flag
36 fields = ["name", "enabled", "created_at__date", "used_at__date"]
37 search_fields = ["name", "description"]
38 cards = [UnusedFlagsCard]
39 nav_section = "Feature flags"
40 nav_icon = "flag"
41
42 class DetailView(AdminModelDetailView):
43 model = Flag
44
45
46class FlagResultForm(ModelForm):
47 class Meta:
48 model = FlagResult
49 fields = ["key", "value"]
50
51
52@register_viewset
53class FlagResultAdmin(AdminViewset):
54 class ListView(AdminModelListView):
55 model = FlagResult
56 title = "Flag results"
57 fields = [
58 "flag",
59 "key",
60 "value",
61 "created_at__date",
62 "updated_at__date",
63 ]
64 search_fields = ["flag__name", "key"]
65 nav_section = "Feature flags"
66 nav_icon = "flag"
67
68 def get_initial_queryset(self) -> QuerySet:
69 return self.model.query.all().select_related("flag")
70
71 class DetailView(AdminModelDetailView):
72 model = FlagResult
73 title = "Flag result"
74
75 class UpdateView(AdminModelUpdateView):
76 model = FlagResult
77 title = "Update flag result"
78 form_class = FlagResultForm