diff --git a/project/backend/database/admin.py b/project/backend/database/admin.py index f06b355a..07facd1f 100644 --- a/project/backend/database/admin.py +++ b/project/backend/database/admin.py @@ -4,6 +4,7 @@ # Register your models here. admin.site.register(Workspace) +admin.site.register(Entry) admin.site.register(BasicUser) admin.site.register(Contributor) admin.site.register(Reviewer) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index b0415da3..e8adab8c 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -5,13 +5,75 @@ from datetime import datetime import enum -# Create your models here. -class Workspace(models.Model): + +class SemanticTag(models.Model): + created_at = models.DateTimeField(auto_now_add=True) + label = models.CharField(max_length=50, unique=True) + desc = models.CharField(max_length=100) + parent_tag = models.ForeignKey("SemanticTag", on_delete=models.CASCADE, null=True, blank=True, + related_name="sub_tags") + + @property + def count(self): + return self.node_set.all().count() + + @property + def nodes(self): + return self.node_set.all() + + @property + def recursive_nodes(self): + nodes = list(self.nodes) + + for sub in self.sub_tags.all(): + nodes.extend(sub.recursive_nodes) + + return nodes + + @property + def recursive_count(self): + return len(self.recursive_nodes) + + class Meta: + constraints = [ + models.UniqueConstraint(fields=['label', 'parent_tag'], + name='semantictag_label_parenttag_unique_constraint') + ] + +class WikiTag(models.Model): + pass +class Request(models.Model): """ - This class definition is written beforehand (to be implemented afterwards) + This class definition is written beforehand (to be implemented afterwards) + in order to be referred from other classes. e.g. ReviewRequest + """ + pass +class Entry(models.Model): + """ + This class definition is written beforehand (to be implemented afterwards) in order to be referred from other classes. e.g. Contributor + This class definition is written beforehand (to be implemented afterwards) + in order to be referred from other classes. e.g. Workspace """ pass +# Create your models here. +class Workspace(models.Model): #Node and Review Requests may be added later + workspace_id = models.AutoField(primary_key=True) + workspace_title = models.CharField(max_length=100) + semantic_tags = models.ManyToManyField(SemanticTag, blank=True,related_name = 'WorkspaceSemanticTags') + wiki_tags = models.ManyToManyField(WikiTag,blank=True,related_name = 'WorkspaceWikiTags') + is_finalized = models.BooleanField(null = True) + is_published = models.BooleanField(null = True) + is_in_review = models.BooleanField(null = True) + is_rejected = models.BooleanField(null = True) + theorem_posted = models.BooleanField(null = True) + num_approvals = models.IntegerField(null = True) + theorem_entry = models.ManyToManyField(Entry,related_name='TheoremEntry') + final_entry = models.ForeignKey(Entry,null=True, on_delete=models.CASCADE,related_name='FinalEntry') + def finalize_workspace(self): + self.is_finalized = True + self.is_in_review = False + return True class BasicUser(models.Model): @@ -32,32 +94,46 @@ class Contributor(BasicUser): def __str__(self): return self.user.first_name + " " + self.user.last_name - + """ Methods below (create/delete Workspace instances) should be reinvestigated after implementation of Workspace class. """ def create_workspace(self): - new_workspace = Workspace.objects.create() + new_workspace = Workspace.objects.create( + workspace_id=1, + workspace_title="Test Workspace", + is_finalized=False, + is_published=False, + is_in_review=False, + is_rejected=False, + theorem_posted=False, + num_approvals=0, + final_entry=None + ) self. workspaces.add(new_workspace) return new_workspace - + def delete_workspace(self, workspace_to_delete): # Note that this function doesn't delete the - if workspace_to_delete in self.workspaces.all(): # Workspace but pops from the list to prevent + if workspace_to_delete in self.workspaces.all(): # Workspace but pops from the list to prevent self.workspaces.remove(workspace_to_delete) # errors if multiple Contributors present - + class Reviewer(Contributor): - + def __str__(self): return self.user.first_name + " " + self.user.last_name - + def get_review_requests(self): return ReviewRequest.objects.filter(receiver=self) + + + class Admin(BasicUser): def __str__(self): return self.user.first_name + " " + self.user.last_name + class Request(models.Model): request_status_choices = [ ("P", "Pending"), @@ -79,6 +155,7 @@ def reject(self): self.status = "R" self.save() + class ReviewRequest(Request): """ This class definition is written beforehand (to be implemented afterwards) @@ -97,43 +174,6 @@ class Theorem(models.Model): publish_date = models.DateField() -class SemanticTag(models.Model): - created_at = models.DateTimeField(auto_now_add=True) - label = models.CharField(max_length=50, unique=True) - desc = models.CharField(max_length=100) - parent_tag = models.ForeignKey("SemanticTag", on_delete=models.CASCADE, null=True, blank=True, related_name="sub_tags") - - @property - def count(self): - return self.node_set.all().count() - - @property - def nodes(self): - return self.node_set.all() - - @property - def recursive_nodes(self): - nodes = list(self.nodes) - - for sub in self.sub_tags.all(): - nodes.extend(sub.recursive_nodes) - - return nodes - - @property - def recursive_count(self): - return len(self.recursive_nodes) - - class Meta: - constraints = [ - models.UniqueConstraint(fields=['label', 'parent_tag'], name='semantictag_label_parenttag_unique_constraint') - ] - - -class WikiTag(models.Model): - pass - - class Annotation(models.Model): # ReviewRequest has annotations, must be handled. pass @@ -161,7 +201,6 @@ class Node(models.Model): def increment_num_visits(self): self.num_visits += 1 - class Proof(models.Model): proof_id = models.AutoField(primary_key=True) proof_title = models.CharField(max_length=100, null=False) diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index 48d06bdb..3a2a10e7 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -82,7 +82,17 @@ def test_create_workspace(self): def test_delete_workspace(self): # Create a workspace and add it to the contributor contributor = Contributor.objects.create(user=User.objects.create()) - workspace = Workspace.objects.create() + workspace = Workspace.objects.create( + workspace_id=1, + workspace_title="Test Workspace", + is_finalized=False, + is_published=False, + is_in_review=False, + is_rejected=False, + theorem_posted=False, + num_approvals=0, + final_entry=None + ) contributor.workspaces.add(workspace) # Test the delete_workspace method @@ -97,7 +107,17 @@ def test_delete_workspace(self): def test_delete_nonexistent_workspace(self): # Create a workspace, but don't add it to the contributor contributor = Contributor.objects.create(user=User.objects.create()) - workspace = Workspace.objects.create() + workspace = Workspace.objects.create( + workspace_id=1, + workspace_title="Test Workspace", + is_finalized=False, + is_published=False, + is_in_review=False, + is_rejected=False, + theorem_posted=False, + num_approvals=0, + final_entry=None + ) # Test the delete_workspace method with a non-existent workspace contributor.delete_workspace(workspace) # This should not raise an error @@ -210,6 +230,51 @@ def test_admin_create(self): self.assertFalse(admin.email_notification_preference) self.assertTrue(admin.show_activity_preference) +class WorkspaceModelTestCase(TestCase): + def tearDown(self): + Workspace.objects.all().delete() + print("All tests for the Workspace Model are completed!") + + def test_workspace_model(self): #Testing workspace model creation + workspace = Workspace.objects.create( + workspace_id = 1, + workspace_title = "Test Workspace", + is_finalized = False, + is_published= False, + is_in_review = False, + is_rejected = False, + theorem_posted = False, + num_approvals = 0, + final_entry = None + ) + + self.assertEqual(workspace.workspace_id, 1) + self.assertEqual(workspace.workspace_title, "Test Workspace") + self.assertEqual(workspace.is_finalized, False) + self.assertEqual(workspace.is_published, False) + self.assertEqual(workspace.is_in_review, False) + self.assertEqual(workspace.is_rejected, False) + self.assertEqual(workspace.theorem_posted, False) + self.assertEqual(workspace.num_approvals, 0) + self.assertIsNone(workspace.final_entry) + + def test_finalize_workspace(self): #Testing finalize workspace function + workspace = Workspace.objects.create( + workspace_id=1, + workspace_title="Test Workspace", + is_finalized=False, + is_published=False, + is_in_review=False, + is_rejected=False, + theorem_posted=False, + num_approvals=0, + final_entry=None + ) + Workspace.finalize_workspace(workspace) + self.assertEqual(workspace.is_finalized, True) + self.assertEqual(workspace.is_in_review, False) + + class NodeModelTestCase(TestCase): def tearDown(self):