|
1
|
from django.conf import settings |
|
2
|
from django.db import models |
|
3
|
|
|
4
|
from core.models import ActiveManager, BaseCoreModel, Tracking |
|
5
|
|
|
6
|
|
|
7
|
class ProjectGroup(BaseCoreModel): |
|
8
|
"""Groups related projects together (e.g., Fossil SCM source + forum + docs).""" |
|
9
|
|
|
10
|
objects = ActiveManager() |
|
11
|
all_objects = models.Manager() |
|
12
|
|
|
13
|
class Meta: |
|
14
|
ordering = ["name"] |
|
15
|
|
|
16
|
def __str__(self): |
|
17
|
return self.name |
|
18
|
|
|
19
|
|
|
20
|
class Project(BaseCoreModel): |
|
21
|
class Visibility(models.TextChoices): |
|
22
|
PUBLIC = "public", "Public" |
|
23
|
INTERNAL = "internal", "Internal" |
|
24
|
PRIVATE = "private", "Private" |
|
25
|
|
|
26
|
organization = models.ForeignKey("organization.Organization", on_delete=models.CASCADE, related_name="projects") |
|
27
|
group = models.ForeignKey( |
|
28
|
"ProjectGroup", |
|
29
|
null=True, |
|
30
|
blank=True, |
|
31
|
on_delete=models.SET_NULL, |
|
32
|
related_name="projects", |
|
33
|
help_text="Optional group for organizing related projects", |
|
34
|
) |
|
35
|
visibility = models.CharField(max_length=10, choices=Visibility.choices, default=Visibility.PRIVATE) |
|
36
|
teams = models.ManyToManyField("organization.Team", through="ProjectTeam", blank=True, related_name="projects") |
|
37
|
|
|
38
|
objects = ActiveManager() |
|
39
|
all_objects = models.Manager() |
|
40
|
|
|
41
|
class Meta: |
|
42
|
ordering = ["name"] |
|
43
|
|
|
44
|
@property |
|
45
|
def star_count(self): |
|
46
|
return self.stars.count() |
|
47
|
|
|
48
|
|
|
49
|
class ProjectStar(models.Model): |
|
50
|
"""Tracks which users have starred a project.""" |
|
51
|
|
|
52
|
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="starred_projects") |
|
53
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="stars") |
|
54
|
created_at = models.DateTimeField(auto_now_add=True) |
|
55
|
|
|
56
|
class Meta: |
|
57
|
unique_together = ("user", "project") |
|
58
|
ordering = ["-created_at"] |
|
59
|
|
|
60
|
def __str__(self): |
|
61
|
return f"{self.user} starred {self.project}" |
|
62
|
|
|
63
|
|
|
64
|
class ProjectTeam(Tracking): |
|
65
|
class Role(models.TextChoices): |
|
66
|
READ = "read", "Read" |
|
67
|
WRITE = "write", "Write" |
|
68
|
ADMIN = "admin", "Admin" |
|
69
|
|
|
70
|
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="project_teams") |
|
71
|
team = models.ForeignKey("organization.Team", on_delete=models.CASCADE, related_name="project_teams") |
|
72
|
role = models.CharField(max_length=10, choices=Role.choices, default=Role.READ) |
|
73
|
|
|
74
|
objects = ActiveManager() |
|
75
|
all_objects = models.Manager() |
|
76
|
|
|
77
|
class Meta: |
|
78
|
unique_together = ("project", "team") |
|
79
|
|
|
80
|
def __str__(self): |
|
81
|
return f"{self.project}/{self.team} ({self.role})" |
|
82
|
|