From f6e3913bc324c8bd87e8f85e43a6a1d0fe5ba23c Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Tue, 31 Oct 2023 18:01:41 +0300 Subject: [PATCH 1/5] Update models.py --- project/backend/database/models.py | 34 ++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index a349223c..5965e7e7 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -7,12 +7,16 @@ # Create your models here. class Workspace(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. Contributor """ +class Entry(models.Model): + """ + This class definition is written beforehand (to be implemented afterwards) + in order to be referred from other classes. e.g. Workspace + """ pass - class BasicUser(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.CharField( @@ -53,6 +57,8 @@ def __str__(self): def get_review_requests(self): return ReviewRequest.objects.filter(reviewer=self) + + class Admin(BasicUser): def __str__(self): return self.user.first_name + " " + self.user.last_name @@ -145,6 +151,30 @@ class Node(models.Model): def increment_num_visits(self): self.num_visits += 1 +class Workspace: + workspace_id = models.AutoField(primary_key=True) + node = models.ForeignKey(Node, on_delete=models.SET_NULL, related_name="Workspaces") #? + workspace_title = models.CharField(max_length=100) + contributors = models.ManyToManyField(Contributor, related_name='WorkspaceContributors') + collab_requests = models.ManyToManyField(Request, related_name='CollaborationRequests') + references = models.ManyToManyField(Node, related_name = 'WorkspaceReferences') + reviews = models.ManyToManyField(ReviewRequest,related_name = 'WorkspaceReviews') #? + semantic_tags = models.ManyToManyField(SemanticTagrelated_name = 'WorkspaceSemanticTags') + wiki_tags = models.ManyToManyField(WikiTag,related_name = 'WorkspaceWikiTags') + is_finalized = models.BooleanField() + is_published = models.BooleanField() + is_in_review = models.BooleanField() + is_rejected = models.BooleanField() + theorem_posted = models.BooleanField() #??? + num_approvals = models.IntegerField() + theorem_entry = models.ForeignKey(Entry,on_delete=models.SET_NULL) + final_entry = models.ForeignKey(Entry,on_delete=models.SET_NULL) + entries = models.ManyToManyField(Entry, related_name='WorkspaceEntries') + def finalize_workspace(self): + self.is_finalized = True + self.is_in_review = False + return True + class Proof(models.Model): proof_id = models.AutoField(primary_key=True) From 542c53a161786b706868bbea8f053c12b91af9e3 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Tue, 7 Nov 2023 19:57:00 +0300 Subject: [PATCH 2/5] Implemented Workspace class and unit tests --- project/backend/database/models.py | 3 +- project/backend/database/tests.py | 49 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 5965e7e7..0b581095 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -10,6 +10,7 @@ class Workspace(models.Model): This class definition is written beforehand (to be implemented afterwards) in order to be referred from other classes. e.g. Contributor """ + pass class Entry(models.Model): """ This class definition is written beforehand (to be implemented afterwards) @@ -165,7 +166,7 @@ class Workspace: is_published = models.BooleanField() is_in_review = models.BooleanField() is_rejected = models.BooleanField() - theorem_posted = models.BooleanField() #??? + theorem_posted = models.BooleanField() num_approvals = models.IntegerField() theorem_entry = models.ForeignKey(Entry,on_delete=models.SET_NULL) final_entry = models.ForeignKey(Entry,on_delete=models.SET_NULL) diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index 92add15f..eb64a4d6 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -207,6 +207,55 @@ 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", + node = None, + is_finalized = False, + is_published= False, + is_in_review = False, + is_rejected = False, + theorem_posted = False, + num_approvals = 0, + theorem_entry = None, + 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.theorem_entry) + 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", + node=None, + is_finalized=False, + is_published=False, + is_in_review=False, + is_rejected=False, + theorem_posted=False, + num_approvals=0, + theorem_entry=None, + 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): From a5d1c2e5536a64fc07cbfa4aef2470c1495d360d Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Tue, 7 Nov 2023 21:15:35 +0300 Subject: [PATCH 3/5] Added User class to Admin --- project/backend/database/admin.py | 1 + project/backend/database/models.py | 38 +++++++++++++++--------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/project/backend/database/admin.py b/project/backend/database/admin.py index c7db2380..9389ba9a 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 0b581095..697c57cd 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -11,6 +11,7 @@ class Workspace(models.Model): in order to be referred from other classes. e.g. Contributor """ pass + class Entry(models.Model): """ This class definition is written beforehand (to be implemented afterwards) @@ -36,7 +37,7 @@ 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. @@ -45,17 +46,17 @@ def create_workspace(self): new_workspace = Workspace.objects.create() 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): + + def get_review_requests(self): return ReviewRequest.objects.filter(reviewer=self) @@ -152,25 +153,24 @@ class Node(models.Model): def increment_num_visits(self): self.num_visits += 1 -class Workspace: +class Workspace(models.Model): workspace_id = models.AutoField(primary_key=True) - node = models.ForeignKey(Node, on_delete=models.SET_NULL, related_name="Workspaces") #? + node = models.ForeignKey(Node, on_delete=models.CASCADE, related_name="Workspaces") #? workspace_title = models.CharField(max_length=100) - contributors = models.ManyToManyField(Contributor, related_name='WorkspaceContributors') - collab_requests = models.ManyToManyField(Request, related_name='CollaborationRequests') - references = models.ManyToManyField(Node, related_name = 'WorkspaceReferences') - reviews = models.ManyToManyField(ReviewRequest,related_name = 'WorkspaceReviews') #? - semantic_tags = models.ManyToManyField(SemanticTagrelated_name = 'WorkspaceSemanticTags') - wiki_tags = models.ManyToManyField(WikiTag,related_name = 'WorkspaceWikiTags') + contributors = models.ForeignKey(Contributor, on_delete=models.PROTECT, related_name='WorkspaceContributors') + collab_requests = models.ForeignKey(Request, on_delete=models.PROTECT,null=True, blank=True,related_name='CollaborationRequests') + references = models.ForeignKey(Node, on_delete=models.PROTECT,related_name = 'WorkspaceReferences') + reviews = models.ForeignKey(ReviewRequest,on_delete=models.PROTECT,null=True, blank=True,related_name = 'WorkspaceReviews') #? + semantic_tags = models.ForeignKey(SemanticTag,on_delete=models.PROTECT,null=True, blank=True,related_name = 'WorkspaceSemanticTags') + wiki_tags = models.ForeignKey(WikiTag,on_delete=models.PROTECT,null=True, blank=True,related_name = 'WorkspaceWikiTags') is_finalized = models.BooleanField() is_published = models.BooleanField() is_in_review = models.BooleanField() is_rejected = models.BooleanField() - theorem_posted = models.BooleanField() + theorem_posted = models.BooleanField() num_approvals = models.IntegerField() - theorem_entry = models.ForeignKey(Entry,on_delete=models.SET_NULL) - final_entry = models.ForeignKey(Entry,on_delete=models.SET_NULL) - entries = models.ManyToManyField(Entry, related_name='WorkspaceEntries') + theorem_entry = models.ForeignKey(Entry,on_delete=models.CASCADE,related_name='TheoremEntry') + final_entry = models.ForeignKey(Entry,on_delete=models.CASCADE,related_name='FinalEntry') def finalize_workspace(self): self.is_finalized = True self.is_in_review = False From 181503811df03994524847adb58cf6c7948d0b27 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Tue, 7 Nov 2023 21:49:39 +0300 Subject: [PATCH 4/5] Changed relations between classes --- project/backend/database/models.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 697c57cd..47b0877f 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -9,11 +9,15 @@ class Workspace(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 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 """ @@ -157,19 +161,19 @@ class Workspace(models.Model): workspace_id = models.AutoField(primary_key=True) node = models.ForeignKey(Node, on_delete=models.CASCADE, related_name="Workspaces") #? workspace_title = models.CharField(max_length=100) - contributors = models.ForeignKey(Contributor, on_delete=models.PROTECT, related_name='WorkspaceContributors') - collab_requests = models.ForeignKey(Request, on_delete=models.PROTECT,null=True, blank=True,related_name='CollaborationRequests') - references = models.ForeignKey(Node, on_delete=models.PROTECT,related_name = 'WorkspaceReferences') - reviews = models.ForeignKey(ReviewRequest,on_delete=models.PROTECT,null=True, blank=True,related_name = 'WorkspaceReviews') #? - semantic_tags = models.ForeignKey(SemanticTag,on_delete=models.PROTECT,null=True, blank=True,related_name = 'WorkspaceSemanticTags') - wiki_tags = models.ForeignKey(WikiTag,on_delete=models.PROTECT,null=True, blank=True,related_name = 'WorkspaceWikiTags') + contributors = models.ManyToManyField(Contributor, related_name='WorkspaceContributors') + collab_requests = models.ManyToManyField(Request, blank=True,related_name='CollaborationRequests') + references = models.ManyToManyField(Node,related_name = 'WorkspaceReferences') + reviews = models.ManyToManyField(ReviewRequest,blank=True,related_name = 'WorkspaceReviews') #? + semantic_tags = models.ManyToManyField(SemanticTag, blank=True,related_name = 'WorkspaceSemanticTags') + wiki_tags = models.ManyToManyField(WikiTag,blank=True,related_name = 'WorkspaceWikiTags') is_finalized = models.BooleanField() is_published = models.BooleanField() is_in_review = models.BooleanField() is_rejected = models.BooleanField() theorem_posted = models.BooleanField() num_approvals = models.IntegerField() - theorem_entry = models.ForeignKey(Entry,on_delete=models.CASCADE,related_name='TheoremEntry') + theorem_entry = models.ManyToManyField(Entry,related_name='TheoremEntry') final_entry = models.ForeignKey(Entry,on_delete=models.CASCADE,related_name='FinalEntry') def finalize_workspace(self): self.is_finalized = True From bda5137930c25f15d461b27c3b8abe0765e77319 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Wed, 8 Nov 2023 21:35:26 +0300 Subject: [PATCH 5/5] Finalized tests and workspace model --- project/backend/database/models.py | 145 ++++++++++++++--------------- project/backend/database/tests.py | 32 +++++-- 2 files changed, 95 insertions(+), 82 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 47b0877f..2a53c77a 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -4,16 +4,49 @@ import copy from datetime import datetime -# 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) - 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 + 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) @@ -22,6 +55,26 @@ class Entry(models.Model): 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) + collab_requests = models.ManyToManyField(Request, blank=True,related_name='CollaborationRequests') + 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): user = models.OneToOneField(User, on_delete=models.CASCADE) @@ -47,7 +100,17 @@ def __str__(self): 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 @@ -69,12 +132,7 @@ class Admin(BasicUser): def __str__(self): return self.user.first_name + " " + self.user.last_name -class Request(models.Model): - """ - This class definition is written beforehand (to be implemented afterwards) - in order to be referred from other classes. e.g. ReviewRequest - """ - pass + class ReviewRequest(Request): """ This class definition is written beforehand (to be implemented afterwards) @@ -96,43 +154,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): pass @@ -157,30 +178,6 @@ class Node(models.Model): def increment_num_visits(self): self.num_visits += 1 -class Workspace(models.Model): - workspace_id = models.AutoField(primary_key=True) - node = models.ForeignKey(Node, on_delete=models.CASCADE, related_name="Workspaces") #? - workspace_title = models.CharField(max_length=100) - contributors = models.ManyToManyField(Contributor, related_name='WorkspaceContributors') - collab_requests = models.ManyToManyField(Request, blank=True,related_name='CollaborationRequests') - references = models.ManyToManyField(Node,related_name = 'WorkspaceReferences') - reviews = models.ManyToManyField(ReviewRequest,blank=True,related_name = 'WorkspaceReviews') #? - semantic_tags = models.ManyToManyField(SemanticTag, blank=True,related_name = 'WorkspaceSemanticTags') - wiki_tags = models.ManyToManyField(WikiTag,blank=True,related_name = 'WorkspaceWikiTags') - is_finalized = models.BooleanField() - is_published = models.BooleanField() - is_in_review = models.BooleanField() - is_rejected = models.BooleanField() - theorem_posted = models.BooleanField() - num_approvals = models.IntegerField() - theorem_entry = models.ManyToManyField(Entry,related_name='TheoremEntry') - final_entry = models.ForeignKey(Entry,on_delete=models.CASCADE,related_name='FinalEntry') - def finalize_workspace(self): - self.is_finalized = True - self.is_in_review = False - return True - - 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 eb64a4d6..d0c70f44 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 @@ -216,14 +236,12 @@ def test_workspace_model(self): #Testing workspace model creation workspace = Workspace.objects.create( workspace_id = 1, workspace_title = "Test Workspace", - node = None, is_finalized = False, is_published= False, is_in_review = False, is_rejected = False, theorem_posted = False, num_approvals = 0, - theorem_entry = None, final_entry = None ) @@ -235,21 +253,18 @@ def test_workspace_model(self): #Testing workspace model creation self.assertEqual(workspace.is_rejected, False) self.assertEqual(workspace.theorem_posted, False) self.assertEqual(workspace.num_approvals, 0) - self.assertIsNone(workspace.theorem_entry) self.assertIsNone(workspace.final_entry) - def test_finalize_workspace(self): #Testing finalize workspace function + def test_finalize_workspace(self): #Testing finalize workspace function workspace = Workspace.objects.create( workspace_id=1, workspace_title="Test Workspace", - node=None, is_finalized=False, is_published=False, is_in_review=False, is_rejected=False, theorem_posted=False, num_approvals=0, - theorem_entry=None, final_entry=None ) Workspace.finalize_workspace(workspace) @@ -257,6 +272,7 @@ def test_finalize_workspace(self): #Testing finalize workspace function self.assertEqual(workspace.is_in_review, False) + class NodeModelTestCase(TestCase): def tearDown(self): Node.objects.all().delete()