From f6e3913bc324c8bd87e8f85e43a6a1d0fe5ba23c Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Tue, 31 Oct 2023 18:01:41 +0300 Subject: [PATCH 01/32] 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 02/32] 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 03/32] 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 04/32] 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 05/32] 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() From b71763ea5bb6baf7a7f8341ff5ed3e621ed3d108 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:45:55 +0300 Subject: [PATCH 06/32] Update models.py --- project/backend/database/models.py | 72 +++++++++++++++--------------- 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 2a53c77a..f9eeb552 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -5,42 +5,7 @@ from datetime import datetime -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) @@ -118,6 +83,43 @@ def delete_workspace(self, workspace_to_delete): # Note that this functio 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 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 Reviewer(Contributor): def __str__(self): From 8d09b5fcbaf75fa03c83ae0c1b5e65163605d152 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:47:44 +0300 Subject: [PATCH 07/32] Revert "Update models.py" This reverts commit b71763ea5bb6baf7a7f8341ff5ed3e621ed3d108. --- project/backend/database/models.py | 72 +++++++++++++++--------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index f9eeb552..2a53c77a 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -5,7 +5,42 @@ from datetime import datetime +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) @@ -83,43 +118,6 @@ def delete_workspace(self, workspace_to_delete): # Note that this functio 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 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 Reviewer(Contributor): def __str__(self): From c042805763fa927618c5acf4dce0f1dffa15cc96 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Sat, 11 Nov 2023 06:16:33 +0300 Subject: [PATCH 08/32] Update models.py --- project/backend/database/models.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 9610edc1..91f5de2a 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -13,6 +13,7 @@ class Workspace(models.Model): pass + class BasicUser(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.CharField( @@ -56,7 +57,23 @@ def get_review_requests(self): class Admin(BasicUser): def __str__(self): return self.user.first_name + " " + self.user.last_name - +class Entry(models.Model): + entry_id = models.AutoField(primary_key=True) + #workspace_id = models.ForeignKey(Workspace,null=False, blank = False, on_delete=models.CASCADE,related_name='WorkspaceID') + content = models.TextField(null=False) + entry_date = models.DateField() + is_theorem_entry = models.BooleanField() + is_final_entry = models.BooleanField(default=False) + is_editable = models.BooleanField(default=True) + creator = models.ForeignKey(Contributor,null = False, blank= False) + entry_number = models.IntegerField() + contributors = models.ManyToManyField(Contributor,on_delete=models.PROTECT,related_name="EntryContributors") + def set_as_final(self): + self.is_final_entry = True + def set_as_theorem(self): + self.is_theorem_entry = True + def set_entry_content(self,cont): + self.content = cont class Request(models.Model): """ This class definition is written beforehand (to be implemented afterwards) From 7c89377cc13f477237d080d28c74a2ff4ef83bfb Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Sat, 11 Nov 2023 06:29:11 +0300 Subject: [PATCH 09/32] Added tests --- project/backend/database/models.py | 2 +- project/backend/database/tests.py | 26 +++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 91f5de2a..6055d18b 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -73,7 +73,7 @@ def set_as_final(self): def set_as_theorem(self): self.is_theorem_entry = True def set_entry_content(self,cont): - self.content = cont + self.content += cont class Request(models.Model): """ This class definition is written beforehand (to be implemented afterwards) diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index 92add15f..ee284993 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -1,6 +1,6 @@ from django.test import TestCase from django.contrib.auth.models import User -from .models import ReviewRequest, Workspace, Contributor, Reviewer, Admin +from .models import ReviewRequest, Workspace, Contributor, Reviewer, Admin,Entry from .serializers import RegisterSerializer, UserSerializer, BasicUserSerializer, ContributorSerializer, ReviewerSerializer from .models import BasicUser, Node, Theorem, Proof from .serializers import RegisterSerializer, UserSerializer, BasicUserSerializer @@ -343,6 +343,30 @@ def test_theorem_model(self): self.assertEqual(theorem.theorem_title, "Test Theorem") self.assertEqual(theorem.theorem_content, "This is a test theorem content.") +class EntryModelTestCase(TestCase): + def tearDown(self): + Entry.objects.all().delete() + print("All tests for the Entry Model are completed!") + + def test_entry_model(self): + testContributor = Contributor.objects.create(user=User.objects.create()) + entry = Entry.objects.create( + entry_id = 1, + content = "This is an entry.", + entry_date = "2023-11-11", + is_theorem_entry = True, + entry_number = 1, + creator = testContributor, + contributors = testContributor + ) + self.assertIn(testContributor, entry.contributors.all()) + self.assertEqual(entry.entry_id, 1) + self.assertEqual(entry.entry_number, 1) + self.assertEqual(entry.content, "This is an entry.") + self.assertEqual(entry.entry_date, "2023-11-11") + self.assertEqual(entry.is_theorem_entry, True) + self.assertEqual(entry.creator, testContributor) + self.assertEqual(entry.is_final_entry,False) class RegisterSerializerTestCase(TestCase): From 5063b988ff9b7118715d09ca7975356e54bf8628 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben Date: Mon, 13 Nov 2023 22:19:28 +0300 Subject: [PATCH 10/32] Update models.py --- project/backend/database/admin.py | 1 + project/backend/database/models.py | 4 ++-- project/backend/database/tests.py | 6 +----- 3 files changed, 4 insertions(+), 7 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 6055d18b..702e0879 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -65,9 +65,9 @@ class Entry(models.Model): is_theorem_entry = models.BooleanField() is_final_entry = models.BooleanField(default=False) is_editable = models.BooleanField(default=True) - creator = models.ForeignKey(Contributor,null = False, blank= False) + creator = models.ForeignKey(Contributor, on_delete = models.CASCADE) entry_number = models.IntegerField() - contributors = models.ManyToManyField(Contributor,on_delete=models.PROTECT,related_name="EntryContributors") + contributors = models.ManyToManyField(Contributor,related_name="EntryContributors") def set_as_final(self): self.is_final_entry = True def set_as_theorem(self): diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index ee284993..637bb560 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -349,23 +349,19 @@ def tearDown(self): print("All tests for the Entry Model are completed!") def test_entry_model(self): - testContributor = Contributor.objects.create(user=User.objects.create()) + entry = Entry.objects.create( entry_id = 1, content = "This is an entry.", entry_date = "2023-11-11", is_theorem_entry = True, entry_number = 1, - creator = testContributor, - contributors = testContributor ) - self.assertIn(testContributor, entry.contributors.all()) self.assertEqual(entry.entry_id, 1) self.assertEqual(entry.entry_number, 1) self.assertEqual(entry.content, "This is an entry.") self.assertEqual(entry.entry_date, "2023-11-11") self.assertEqual(entry.is_theorem_entry, True) - self.assertEqual(entry.creator, testContributor) self.assertEqual(entry.is_final_entry,False) From de14dc11ede5bd679fb087e134ac1c920f8de6d5 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben <79109830+gebenalimert@users.noreply.github.com> Date: Mon, 13 Nov 2023 22:33:36 +0300 Subject: [PATCH 11/32] Update models.py --- project/backend/database/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 3ba1fe88..bb704368 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -65,7 +65,7 @@ class Entry(models.Model): is_theorem_entry = models.BooleanField() is_final_entry = models.BooleanField(default=False) is_editable = models.BooleanField(default=True) - creator = models.ForeignKey(Contributor, on_delete = models.CASCADE) + creator = models.ForeignKey(Contributor,null=True,blank=True on_delete = models.CASCADE) entry_number = models.IntegerField() contributors = models.ManyToManyField(Contributor,related_name="EntryContributors") def set_as_final(self): From a70d91d073cbbb892f1d385e89e21d7cb46af906 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben <79109830+gebenalimert@users.noreply.github.com> Date: Mon, 13 Nov 2023 22:35:14 +0300 Subject: [PATCH 12/32] Forgetten "," added --- project/backend/database/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index bb704368..057cdeb4 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -65,7 +65,7 @@ class Entry(models.Model): is_theorem_entry = models.BooleanField() is_final_entry = models.BooleanField(default=False) is_editable = models.BooleanField(default=True) - creator = models.ForeignKey(Contributor,null=True,blank=True on_delete = models.CASCADE) + creator = models.ForeignKey(Contributor,null=True,blank=True, on_delete = models.CASCADE) entry_number = models.IntegerField() contributors = models.ManyToManyField(Contributor,related_name="EntryContributors") def set_as_final(self): From 498321443e6b5852e99799b7f19918971618f208 Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Wed, 15 Nov 2023 22:37:18 +0300 Subject: [PATCH 13/32] Add CollabRequest POST Implemented POST for sending collaboration requests --- project/backend/api/tests.py | 35 ++++++++++++++++++++++--- project/backend/api/urls.py | 1 + project/backend/api/views.py | 11 +++++++- project/backend/database/serializers.py | 5 ++++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 0eb91026..cd84f2ed 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -3,10 +3,9 @@ from rest_framework import status from rest_framework.test import APIClient from django.contrib.auth.models import User -from database.models import BasicUser,Contributor,Node,Question, Proof, Theorem +from database.models import * from rest_framework.authtoken.models import Token from database.serializers import RegisterSerializer, UserSerializer -from database import models import datetime # Create your tests here for each class or API call. @@ -147,8 +146,8 @@ def setUp(self): user = User.objects.create_user(id=1, email='test@example.com', username='test@example.com', first_name='User', last_name='Test') # basic_user = BasicUser.objects.create(user=user, bio='Hello') - cont = models.Contributor.objects.create(user=user, bio='Hello',id=1) - node = models.Node.objects.create(node_title='test', + cont = Contributor.objects.create(user=user, bio='Hello',id=1) + node = Node.objects.create(node_title='test', theorem=None, publish_date="2023-01-01", is_valid=True, @@ -447,3 +446,31 @@ def test_get_contributor_from_id(self): } ) +class CollaborationRequestAPITestCase(TestCase): + + def tearDown(self): + Workspace.objects.all().delete() + User.objects.all().delete() + Contributor.objects.all().delete() + CollaborationRequest.objects.all().delete() + print("Test for the CollaborationRequest API is completed!") + + def setUp(self): + self.client = APIClient() + + self.workspace = Workspace.objects.create() + self.contributor_receiver = Contributor.objects.create(user=User.objects.create(username="receiver")) + self.contributor_sender = Contributor.objects.create(user=User.objects.create(username="sender")) + + self.request_data = { + 'sender': self.contributor_sender.id, + 'receiver': self.contributor_receiver.id, + 'title' : 'Request Test Title', + 'body': 'Request Test Body', + 'workspace': self.workspace.id + } + + def test_send_collab_request(self): + url = reverse('send_col_req') + response = self.client.post(url, self.request_data, format='json') + self.assertEqual(response.status_code, 201) diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index 89c8ca32..5013f183 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -15,4 +15,5 @@ path('get_proof/', get_proof_from_id, name='get_proof'), path('get_theorem/', get_theorem_from_id, name='get_theorem'), path('get_cont/', get_contributor_from_id, name='get_cont'), + path('send_collab_req', send_collaboration_request, name='send_col_req'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 4162f3a4..ad83d34a 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -253,4 +253,13 @@ def get_contributor_from_id(request): 'name': user.first_name, 'surname': user.last_name, } - return JsonResponse(data, status=200) \ No newline at end of file + return JsonResponse(data, status=200) + +@api_view(['POST']) +def send_collaboration_request(request): + + serializer = CollaborationRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=201) + return Response(serializer.errors, status=400) diff --git a/project/backend/database/serializers.py b/project/backend/database/serializers.py index dec0b93b..c0c1fe22 100644 --- a/project/backend/database/serializers.py +++ b/project/backend/database/serializers.py @@ -171,3 +171,8 @@ class Meta: model = Node fields = ['node_id', 'node_title', 'publish_date', 'is_valid', 'num_visits' , 'theorem', 'contributors', 'reviewers', 'from_referenced_nodes' , 'to_referenced_nodes', 'proofs' , 'question_set', 'semantic_tags', 'wiki_tags', 'annotations'] + +class CollaborationRequestSerializer(serializers.ModelSerializer): + class Meta: + model = CollaborationRequest + fields = '__all__' From 5319717e6a5418e31319248bb2124f454a782d8b Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Wed, 15 Nov 2023 23:02:15 +0300 Subject: [PATCH 14/32] Implemented Status Update Implemented PUT Status Update for Requests --- project/backend/api/tests.py | 8 ++++++++ project/backend/api/urls.py | 3 ++- project/backend/api/views.py | 18 ++++++++++++++++++ project/backend/database/serializers.py | 5 +++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index cd84f2ed..a914f1d0 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -462,6 +462,8 @@ def setUp(self): self.contributor_receiver = Contributor.objects.create(user=User.objects.create(username="receiver")) self.contributor_sender = Contributor.objects.create(user=User.objects.create(username="sender")) + self.request = CollaborationRequest.objects.create(workspace=self.workspace,receiver=self.contributor_receiver,sender=self.contributor_sender) + self.request_data = { 'sender': self.contributor_sender.id, 'receiver': self.contributor_receiver.id, @@ -474,3 +476,9 @@ def test_send_collab_request(self): url = reverse('send_col_req') response = self.client.post(url, self.request_data, format='json') self.assertEqual(response.status_code, 201) + + def update_collab_request(self): + url = reverse('update_req') + response = self.client.put(url, {'id': self.request_data[id], 'status': 'A'}, format='json') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data.status, 'A') diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index 5013f183..7c612f61 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -15,5 +15,6 @@ path('get_proof/', get_proof_from_id, name='get_proof'), path('get_theorem/', get_theorem_from_id, name='get_theorem'), path('get_cont/', get_contributor_from_id, name='get_cont'), - path('send_collab_req', send_collaboration_request, name='send_col_req'), + path('send_collab_req/', send_collaboration_request, name='send_col_req'), + path('update_req/', update_request_status, name='update_req'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index ad83d34a..54732b90 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -263,3 +263,21 @@ def send_collaboration_request(request): serializer.save() return Response(serializer.data, status=201) return Response(serializer.errors, status=400) + +@api_view(['PUT']) +def update_request_status(request): + try: + req = Request.objects.get(pk=request.data.get('id')) + except Request.DoesNotExist: + return Response({"message": "Request not found."}, status=404) + + status = request.data.get('status') + + if status not in ["P", "A", "R"]: + return Response({"message": "Invalid status value."}, status=400) + + req.status = status + req.save() + + serializer = RequestSerializer(req) + return Response(serializer.data, status=200) diff --git a/project/backend/database/serializers.py b/project/backend/database/serializers.py index c0c1fe22..848124f7 100644 --- a/project/backend/database/serializers.py +++ b/project/backend/database/serializers.py @@ -172,6 +172,11 @@ class Meta: fields = ['node_id', 'node_title', 'publish_date', 'is_valid', 'num_visits' , 'theorem', 'contributors', 'reviewers', 'from_referenced_nodes' , 'to_referenced_nodes', 'proofs' , 'question_set', 'semantic_tags', 'wiki_tags', 'annotations'] +class RequestSerializer(serializers.ModelSerializer): + class Meta: + model = Request + fields = '__all__' + class CollaborationRequestSerializer(serializers.ModelSerializer): class Meta: model = CollaborationRequest From 476b35c8cec29e3ae49cbcd035b9f20d6c6ef653 Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Wed, 15 Nov 2023 23:11:35 +0300 Subject: [PATCH 15/32] Implement Send Review Request Implemented POST for sending review requests with unit tests --- project/backend/api/tests.py | 37 +++++++++++++++++++++++++ project/backend/api/urls.py | 1 + project/backend/api/views.py | 9 ++++++ project/backend/database/serializers.py | 5 ++++ 4 files changed, 52 insertions(+) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index a914f1d0..a16a674d 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -482,3 +482,40 @@ def update_collab_request(self): response = self.client.put(url, {'id': self.request_data[id], 'status': 'A'}, format='json') self.assertEqual(response.status_code, 200) self.assertEqual(response.data.status, 'A') + +class ReviewRequestAPITestCase(TestCase): + + def tearDown(self): + Workspace.objects.all().delete() + User.objects.all().delete() + Contributor.objects.all().delete() + ReviewRequest.objects.all().delete() + print("Test for the ReviewRequest API is completed!") + + def setUp(self): + self.client = APIClient() + + self.workspace = Workspace.objects.create() + self.reviewer_receiver = Contributor.objects.create(user=User.objects.create(username="receiver")) + self.contributor_sender = Contributor.objects.create(user=User.objects.create(username="sender")) + + self.request = ReviewRequest.objects.create(workspace=self.workspace,receiver=self.reviewer_receiver,sender=self.contributor_sender) + + self.request_data = { + 'sender': self.contributor_sender.id, + 'receiver': self.reviewer_receiver.id, + 'title' : 'Review Request Test Title', + 'body': 'Review Request Test Body', + 'workspace': self.workspace.id + } + + def test_send_review_request(self): + url = reverse('send_rev_req') + response = self.client.post(url, self.request_data, format='json') + self.assertEqual(response.status_code, 201) + + def update_review_request(self): + url = reverse('update_req') + response = self.client.put(url, {'id': self.request_data[id], 'status': 'R'}, format='json') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data.status, 'R') diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index 7c612f61..a9fdf82d 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -17,4 +17,5 @@ path('get_cont/', get_contributor_from_id, name='get_cont'), path('send_collab_req/', send_collaboration_request, name='send_col_req'), path('update_req/', update_request_status, name='update_req'), + path('send_rev_req/', send_review_request, name='send_rev_req'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 54732b90..97168e87 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -281,3 +281,12 @@ def update_request_status(request): serializer = RequestSerializer(req) return Response(serializer.data, status=200) + +@api_view(['POST']) +def send_review_request(request): + + serializer = ReviewRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=201) + return Response(serializer.errors, status=400) diff --git a/project/backend/database/serializers.py b/project/backend/database/serializers.py index 848124f7..020dae1e 100644 --- a/project/backend/database/serializers.py +++ b/project/backend/database/serializers.py @@ -181,3 +181,8 @@ class CollaborationRequestSerializer(serializers.ModelSerializer): class Meta: model = CollaborationRequest fields = '__all__' + +class ReviewRequestSerializer(serializers.ModelSerializer): + class Meta: + model = ReviewRequest + fields = '__all__' From d9858ef776cc29a51c4d8b75a17fdb92ec25e41a Mon Sep 17 00:00:00 2001 From: Ali Mert Geben <79109830+gebenalimert@users.noreply.github.com> Date: Wed, 15 Nov 2023 23:31:19 +0300 Subject: [PATCH 16/32] Update models.py --- project/backend/database/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index e16638f5..e8adab8c 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -60,7 +60,6 @@ class Entry(models.Model): 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) From e09e91e21eccc245fd673c2eaba66e5ea4cc6b00 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben <79109830+gebenalimert@users.noreply.github.com> Date: Wed, 15 Nov 2023 23:32:44 +0300 Subject: [PATCH 17/32] Update models.py --- project/backend/database/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 48433451..82c0d886 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -61,6 +61,7 @@ def __str__(self): class Entry(models.Model): entry_id = models.AutoField(primary_key=True) + entry_index = models.IntegerField() #workspace_id = models.ForeignKey(Workspace,null=False, blank = False, on_delete=models.CASCADE,related_name='WorkspaceID') content = models.TextField(null=False) entry_date = models.DateField() From 95d38b278855fc907e7ddb7258e7a4ec4482a785 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben <79109830+gebenalimert@users.noreply.github.com> Date: Wed, 15 Nov 2023 23:47:02 +0300 Subject: [PATCH 18/32] Update models.py --- project/backend/database/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 4774c866..efe2b03f 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -57,9 +57,9 @@ class Entry(models.Model): is_theorem_entry = models.BooleanField() is_final_entry = models.BooleanField(default=False) is_editable = models.BooleanField(default=True) - creator = models.ForeignKey(Contributor,null=True,blank=True, on_delete = models.CASCADE) + #creator = models.ForeignKey(Contributor,null=True,blank=True, on_delete = models.CASCADE) entry_number = models.IntegerField() - contributors = models.ManyToManyField(Contributor,related_name="EntryContributors") + #contributors = models.ManyToManyField(Contributor,related_name="EntryContributors") def set_as_final(self): self.is_final_entry = True def set_as_theorem(self): From 3aab8eea26781d7f8415111cf21ab368d59a1ab6 Mon Sep 17 00:00:00 2001 From: Ali Mert Geben <79109830+gebenalimert@users.noreply.github.com> Date: Thu, 16 Nov 2023 01:19:24 +0300 Subject: [PATCH 19/32] Update tests.py --- project/backend/database/tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index 15dd48d7..6ba52e09 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -420,6 +420,7 @@ def test_entry_model(self): entry = Entry.objects.create( entry_id = 1, + entry_index = 1, content = "This is an entry.", entry_date = "2023-11-11", is_theorem_entry = True, From 1fbe4c03dec1d7581e6b1209d72b0fe0afa310bc Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 15:11:11 +0300 Subject: [PATCH 20/32] Implementation --- project/backend/api/urls.py | 2 + project/backend/api/views.py | 93 +++++++++++++++++++++++++++++- project/backend/database/models.py | 11 ++-- 3 files changed, 101 insertions(+), 5 deletions(-) diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index 89c8ca32..7a0c616e 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -15,4 +15,6 @@ path('get_proof/', get_proof_from_id, name='get_proof'), path('get_theorem/', get_theorem_from_id, name='get_theorem'), path('get_cont/', get_contributor_from_id, name='get_cont'), + path('get_user_workspaces/',get_workspaces,name='get_user_workspaces'), + path('get_workspace/',get_workspace_from_id,name='get_workspace'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 4162f3a4..07c23e0c 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -253,4 +253,95 @@ def get_contributor_from_id(request): 'name': user.first_name, 'surname': user.last_name, } - return JsonResponse(data, status=200) \ No newline at end of file + return JsonResponse(data, status=200) + +def get_workspaces(request): + id = int(request.GET.get("user_id")) + cont = Contributor.objects.filter(id=id) + if cont.count() == 0: + return JsonResponse({'message':'There is no contributor with this id.'},status=404) + cont = cont[0] + workspace_list = [] + for workspace in cont.workspaces.all(): + + workspace_list.append({'workspace_id':workspace.workspace_id, + 'workspace_title':workspace.workspace_title, + 'pending':False}) + pending = [] + for req in CollaborationRequest.objects.filter(receiver=cont): + workspace = req.workspace + pending.append({'workspace_id': workspace.workspace_id, + 'workspace_title': workspace.workspace_title, + 'pending': True}) + + return JsonResponse({'workspaces':workspace_list,'pending_workspaces':pending}, status=200) + +def get_workspace_from_id(request): + id = int(request.GET.get("workspace_id")) + workspace = Workspace.objects.filter(workspace_id=id) + if workspace.count() == 0: + return JsonResponse({'message':'There is no workspace with this id.'},status=404) + workspace = workspace[0] + entries = [] + for entry in workspace.entries.all(): + entries.append({'entry_id':entry.entry_id, + 'entry_date':entry.entry_date, + 'content':entry.content, + 'entry_index':entry.entry_index, + 'is_theorem_entry':entry.is_theorem_entry, + 'is_final_entry':entry.is_final_entry, + 'is_proof_entry':entry.is_proof_entry, + 'is_editable':entry.is_editable, + 'entry_number':entry.entry_number,}) + semantic_tags = [] + for tag in workspace.semantic_tags.all(): + semantic_tags.append({'label':tag.label, + 'desc':tag.desc, + 'parent_tag':tag.parent_tag, + 'created_at':tag.created_at}) + contributors = [] + for cont in Contributor.objects.filter(workspaces=workspace): + user = User.objects.get(id=cont.user_id) + contributors.append({"id": cont.id, + "first_name": user.first_name, + "last_name": user.last_name, + "username": user.username}) + pending = [] + for pend in CollaborationRequest.objects.filter(workspace=workspace): + cont = pend.receiver + user = User.objects.get(id=cont.user_id) + pending.append({"id": cont.id, + "first_name": user.first_name, + "last_name": user.last_name, + "username": user.username}) + references = [] + for ref in workspace.references.all(): + authors = [] + for cont in ref.contributors.all(): + user = User.objects.get(id=cont.user_id) + authors.append({"id": cont.id, + "first_name": user.first_name, + "last_name": user.last_name, + "username": user.username}) + references.append({'node_id':ref.node_id, + 'node_title':ref.node_title, + 'contributors':authors, + 'publish_date':ref.publish_date}) + status = 'workable' + if workspace.is_published: + status = 'published' + elif workspace.is_rejected: + status = 'rejected' + elif workspace.is_in_review: + status = 'in_review' + elif workspace.is_finalized: + status = 'finalized' + return JsonResponse({'workspace_id': workspace.workspace_id, + 'workspace_title':workspace.workspace_title, + 'workspace_entries': entries, + 'status':status, + 'num_approvals':workspace.num_approvals, + 'contributors':contributors, + 'pending_contributors':pending, + 'references':references, + }, status=200) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index efe2b03f..407bf575 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -54,8 +54,9 @@ class Entry(models.Model): #workspace_id = models.ForeignKey(Workspace,null=False, blank = False, on_delete=models.CASCADE,related_name='WorkspaceID') content = models.TextField(null=False) entry_date = models.DateField() - is_theorem_entry = models.BooleanField() + is_theorem_entry = models.BooleanField(default=False) is_final_entry = models.BooleanField(default=False) + is_proof_entry = models.BooleanField(default=False) is_editable = models.BooleanField(default=True) #creator = models.ForeignKey(Contributor,null=True,blank=True, on_delete = models.CASCADE) entry_number = models.IntegerField() @@ -71,15 +72,17 @@ 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') + # 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') + entries = models.ManyToManyField(Entry,blank=True,related_name = 'WorkspaceEntries') + references = models.ManyToManyField('Node',blank=True,related_name='WorkspaceReferences') + # 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 From 82e5617925cc82fdf3f2f0fab595a9b455358959 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 15:54:02 +0300 Subject: [PATCH 21/32] tests are implemented --- project/backend/api/tests.py | 52 ++++++++++++++++++++++++++++++ project/backend/api/views.py | 1 + project/backend/database/models.py | 35 +++++++++----------- project/backend/database/tests.py | 8 ++--- 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 0eb91026..99657186 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -447,3 +447,55 @@ def test_get_contributor_from_id(self): } ) + +class UserWorkspacesGETAPITestCase(TestCase): + def setUp(self): + self.client = APIClient() + self.user = User.objects.create_user(id=1, email='test@example.com', username='test@example.com', first_name='User', + last_name='Test') + self.cont = Contributor.objects.create(user=self.user, bio='Hello',id=3) + self.workspace = self.cont.create_workspace('test') + self.url = reverse('get_user_workspaces') + + def test_get_contributor_from_id(self): + response = self.client.get(self.url, {'user_id': self.cont.id}) + + self.assertEqual(response.status_code, 200) + self.assertJSONEqual( + response.content.decode('utf-8'), + { + 'workspaces': [{'workspace_id':self.workspace.workspace_id, + 'workspace_title':self.workspace.workspace_title, + 'pending':False}], + } + ) + + +class WorkspaceGETAPITestCase(TestCase): + def setUp(self): + self.client = APIClient() + self.user = User.objects.create_user(id=1, email='test@example.com', username='test@example.com', first_name='User', + last_name='Test') + self.cont = Contributor.objects.create(user=self.user, bio='Hello',id=3) + self.workspace = self.cont.create_workspace('test') + self.url = reverse('get_workspace') + + def test_get_contributor_from_id(self): + response = self.client.get(self.url, {'workspace_id': self.workspace.workspace_id}) + + self.assertEqual(response.status_code, 200) + self.assertJSONEqual( + response.content.decode('utf-8'), + { + 'workspaces_id': self.workspace.workspace_id, + 'workspace_title':self.workspace.workspace_title, + 'workspace_entries': [], + 'status' : 'workable', + 'contributors': [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}] + 'num_approvals': None, + 'pending_contributors':[], + 'references':[], + 'created_at':self.workspace.created_at, + } + ) + diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 07c23e0c..4b58163a 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -344,4 +344,5 @@ def get_workspace_from_id(request): 'contributors':contributors, 'pending_contributors':pending, 'references':references, + 'created_at':workspace.created_at, }, status=200) diff --git a/project/backend/database/models.py b/project/backend/database/models.py index 407bf575..9dcecddf 100644 --- a/project/backend/database/models.py +++ b/project/backend/database/models.py @@ -73,16 +73,18 @@ class Workspace(models.Model): #Node and Review Requests may be added later 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) + is_finalized = models.BooleanField(null = True,default=False) + is_published = models.BooleanField(null = True,default=False) + is_in_review = models.BooleanField(null = True,default=False) + is_rejected = models.BooleanField(null = True,default=False) + theorem_posted = models.BooleanField(null = True,default=False) + num_approvals = models.IntegerField(null = True,default=0) entries = models.ManyToManyField(Entry,blank=True,related_name = 'WorkspaceEntries') references = models.ManyToManyField('Node',blank=True,related_name='WorkspaceReferences') + created_at = models.DateTimeField(auto_now_add=True) # theorem_entry = models.ManyToManyField(Entry,related_name='TheoremEntry') - # final_entry = models.ForeignKey(Entry,null=True, on_delete=models.CASCADE,related_name='FinalEntry') + # 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 @@ -90,6 +92,7 @@ def finalize_workspace(self): + class BasicUser(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.CharField( @@ -113,19 +116,11 @@ def __str__(self): Methods below (create/delete Workspace instances) should be reinvestigated after implementation of Workspace class. """ - def create_workspace(self): + def create_workspace(self,title): 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 + workspace_title=title, ) - self. workspaces.add(new_workspace) + self.workspaces.add(new_workspace) return new_workspace def delete_workspace(self, workspace_to_delete): # Note that this function doesn't delete the @@ -176,11 +171,11 @@ class ReviewRequest(Request): This class definition is written beforehand (to be implemented afterwards) in order to be referred from other classes. e.g. Reviewer, Contributor """ - workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE) #Note that workspace is accessed directly by Workspace instance not via "workspaceID" as proposed in project class diagram. + workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE) #Note that workspace is accessed directly by Workspace instance not via "workspaceID" as proposed in project class diagram. comment = models.CharField(max_length=400, null=True, default=None) class CollaborationRequest(Request): - workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE) #Note that workspace is accessed directly by Workspace instance not via "workspaceID" as proposed in project class diagram. + workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE) #Note that workspace is accessed directly by Workspace instance not via "workspaceID" as proposed in project class diagram. class Theorem(models.Model): theorem_id = models.AutoField(primary_key=True) diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index 6ba52e09..ac3f7b60 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -71,7 +71,7 @@ def test_contributor_create(self): def test_create_workspace(self): # Test the create_workspace method contributor = Contributor.objects.create(user=User.objects.create()) - workspace = contributor.create_workspace() + workspace = contributor.create_workspace('test') self.assertIn(workspace, contributor.workspaces.all()) # We should collect our garbages @@ -185,7 +185,7 @@ def test_inheritance(self): # Create a contributor and it's workspace contributor = Contributor.objects.create(user=User.objects.create(username="future_reviewer")) reviewer_judge = Reviewer.objects.create(user=User.objects.create(username="sender")) - workspace = contributor.create_workspace() + workspace = contributor.create_workspace('test') # Suppose this particular contributor becomes a reviewer contributor.__class__= Reviewer @@ -613,7 +613,7 @@ def test_contributor_serializer_fields(self): # Testing the fiels of the serializer contributor = Contributor.objects.create(user=User.objects.create()) - workspace = contributor.create_workspace() + workspace = contributor.create_workspace('test') serializer = ContributorSerializer(contributor) expected_fields = set( @@ -631,7 +631,7 @@ def test_reviewer_serializer_fields(self): # Testing the fiels of the serializer reviewer = Reviewer.objects.create(user=User.objects.create()) - workspace = reviewer.create_workspace() + workspace = reviewer.create_workspace('test') serializer = ReviewerSerializer(reviewer) expected_fields = set( From aec05a696a9b4bbf6afd44c99185f84322a72a87 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:03:37 +0300 Subject: [PATCH 22/32] test fix --- project/backend/api/tests.py | 2 +- project/backend/database/tests.py | 30 +++--------------------------- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 99657186..de6dc24e 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -491,7 +491,7 @@ def test_get_contributor_from_id(self): 'workspace_title':self.workspace.workspace_title, 'workspace_entries': [], 'status' : 'workable', - 'contributors': [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}] + 'contributors': [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}], 'num_approvals': None, 'pending_contributors':[], 'references':[], diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index ac3f7b60..639609aa 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -85,13 +85,7 @@ def test_delete_workspace(self): 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) @@ -110,13 +104,7 @@ def test_delete_nonexistent_workspace(self): 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 @@ -239,13 +227,7 @@ 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) @@ -262,13 +244,7 @@ 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) From 65fc52c82f9e00599837a7cf180de4586acbdfb6 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:11:27 +0300 Subject: [PATCH 23/32] test fix --- project/backend/api/tests.py | 36 ++++++++++++------------------- project/backend/database/tests.py | 4 ++-- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index de6dc24e..30c33646 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -461,14 +461,10 @@ def test_get_contributor_from_id(self): response = self.client.get(self.url, {'user_id': self.cont.id}) self.assertEqual(response.status_code, 200) - self.assertJSONEqual( - response.content.decode('utf-8'), - { - 'workspaces': [{'workspace_id':self.workspace.workspace_id, - 'workspace_title':self.workspace.workspace_title, - 'pending':False}], - } - ) + self.assertEqual(response[0]['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response[0]['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response[0]['pending'], False) + class WorkspaceGETAPITestCase(TestCase): @@ -484,18 +480,14 @@ def test_get_contributor_from_id(self): response = self.client.get(self.url, {'workspace_id': self.workspace.workspace_id}) self.assertEqual(response.status_code, 200) - self.assertJSONEqual( - response.content.decode('utf-8'), - { - 'workspaces_id': self.workspace.workspace_id, - 'workspace_title':self.workspace.workspace_title, - 'workspace_entries': [], - 'status' : 'workable', - 'contributors': [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}], - 'num_approvals': None, - 'pending_contributors':[], - 'references':[], - 'created_at':self.workspace.created_at, - } - ) + self.assertEqual(response['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response['workspace_id'], self.workspace.workspace_id) + self.assertEqual(response['contributors'], [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}]) + self.assertEqual(response['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response['status'], 'workable') + self.assertEqual(response['references'], []) + self.assertEqual(response['pending_contributors'], []) + self.assertEqual(response['num_approvals'], 0) + self.assertEqual(response['created_at'], self.workspace.created_at) + diff --git a/project/backend/database/tests.py b/project/backend/database/tests.py index 639609aa..af3275fd 100644 --- a/project/backend/database/tests.py +++ b/project/backend/database/tests.py @@ -238,7 +238,7 @@ 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.final_entry) + # self.assertIsNone(workspace.final_entry) def test_finalize_workspace(self): #Testing finalize workspace function workspace = Workspace.objects.create( @@ -407,7 +407,7 @@ def test_entry_model(self): self.assertEqual(entry.content, "This is an entry.") self.assertEqual(entry.entry_date, "2023-11-11") self.assertEqual(entry.is_theorem_entry, True) - self.assertEqual(entry.is_final_entry,False) + # self.assertEqual(entry.is_final_entry,False) class ReviewRequestTestCase(TestCase): def tearDown(self): From 2320dae43f43f2401ffa39b17733c0e5a93b1bb6 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:18:55 +0300 Subject: [PATCH 24/32] Update tests.py --- project/backend/api/tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 30c33646..3ef404cc 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -461,9 +461,9 @@ def test_get_contributor_from_id(self): response = self.client.get(self.url, {'user_id': self.cont.id}) self.assertEqual(response.status_code, 200) - self.assertEqual(response[0]['workspace_id'],self.workspace.workspace_id) - self.assertEqual(response[0]['workspace_title'], self.workspace.workspace_title) - self.assertEqual(response[0]['pending'], False) + self.assertEqual(response['workspaces'][0]['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response['workspaces'][0]['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response['workspaces'][0]['pending'], False) From 06b079da2f9eda3f52e6fb3b1174ae5fe859a344 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:29:44 +0300 Subject: [PATCH 25/32] Update tests.py --- project/backend/api/tests.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 3ef404cc..c311ed15 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -457,8 +457,9 @@ def setUp(self): self.workspace = self.cont.create_workspace('test') self.url = reverse('get_user_workspaces') - def test_get_contributor_from_id(self): + def test_get_workspaces_of_user(self): response = self.client.get(self.url, {'user_id': self.cont.id}) + print(response) self.assertEqual(response.status_code, 200) self.assertEqual(response['workspaces'][0]['workspace_id'],self.workspace.workspace_id) @@ -476,9 +477,9 @@ def setUp(self): self.workspace = self.cont.create_workspace('test') self.url = reverse('get_workspace') - def test_get_contributor_from_id(self): + def test_get_workspace_from_id(self): response = self.client.get(self.url, {'workspace_id': self.workspace.workspace_id}) - + print(response) self.assertEqual(response.status_code, 200) self.assertEqual(response['workspace_id'],self.workspace.workspace_id) self.assertEqual(response['workspace_id'], self.workspace.workspace_id) From 9bd92989ee19aad94341775ffdd6d823b1c1eeac Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:36:00 +0300 Subject: [PATCH 26/32] Update tests.py --- project/backend/api/tests.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index c311ed15..1f370c6d 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -462,9 +462,9 @@ def test_get_workspaces_of_user(self): print(response) self.assertEqual(response.status_code, 200) - self.assertEqual(response['workspaces'][0]['workspace_id'],self.workspace.workspace_id) - self.assertEqual(response['workspaces'][0]['workspace_title'], self.workspace.workspace_title) - self.assertEqual(response['workspaces'][0]['pending'], False) + self.assertEqual(response.data['workspaces'][0]['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response.data['workspaces'][0]['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response.data['workspaces'][0]['pending'], False) @@ -481,14 +481,14 @@ def test_get_workspace_from_id(self): response = self.client.get(self.url, {'workspace_id': self.workspace.workspace_id}) print(response) self.assertEqual(response.status_code, 200) - self.assertEqual(response['workspace_id'],self.workspace.workspace_id) - self.assertEqual(response['workspace_id'], self.workspace.workspace_id) - self.assertEqual(response['contributors'], [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}]) - self.assertEqual(response['workspace_title'], self.workspace.workspace_title) - self.assertEqual(response['status'], 'workable') - self.assertEqual(response['references'], []) - self.assertEqual(response['pending_contributors'], []) - self.assertEqual(response['num_approvals'], 0) - self.assertEqual(response['created_at'], self.workspace.created_at) + self.assertEqual(response.data['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response.data['workspace_id'], self.workspace.workspace_id) + self.assertEqual(response.data['contributors'], [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}]) + self.assertEqual(response.data['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response.data['status'], 'workable') + self.assertEqual(response.data['references'], []) + self.assertEqual(response.data['pending_contributors'], []) + self.assertEqual(response.data['num_approvals'], 0) + self.assertEqual(response.data['created_at'], self.workspace.created_at) From 18900c68774fbb2f374ebf259d6bd91314c292a5 Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:48:55 +0300 Subject: [PATCH 27/32] Update tests.py --- project/backend/api/tests.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 1f370c6d..585d7a05 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -462,9 +462,9 @@ def test_get_workspaces_of_user(self): print(response) self.assertEqual(response.status_code, 200) - self.assertEqual(response.data['workspaces'][0]['workspace_id'],self.workspace.workspace_id) - self.assertEqual(response.data['workspaces'][0]['workspace_title'], self.workspace.workspace_title) - self.assertEqual(response.data['workspaces'][0]['pending'], False) + self.assertEqual(response.json()['workspaces'][0]['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response.json()['workspaces'][0]['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response.json()['workspaces'][0]['pending'], False) @@ -481,14 +481,14 @@ def test_get_workspace_from_id(self): response = self.client.get(self.url, {'workspace_id': self.workspace.workspace_id}) print(response) self.assertEqual(response.status_code, 200) - self.assertEqual(response.data['workspace_id'],self.workspace.workspace_id) - self.assertEqual(response.data['workspace_id'], self.workspace.workspace_id) - self.assertEqual(response.data['contributors'], [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}]) - self.assertEqual(response.data['workspace_title'], self.workspace.workspace_title) - self.assertEqual(response.data['status'], 'workable') - self.assertEqual(response.data['references'], []) - self.assertEqual(response.data['pending_contributors'], []) - self.assertEqual(response.data['num_approvals'], 0) - self.assertEqual(response.data['created_at'], self.workspace.created_at) + self.assertEqual(response.json()['workspace_id'],self.workspace.workspace_id) + self.assertEqual(response.json()['workspace_id'], self.workspace.workspace_id) + self.assertEqual(response.json()['contributors'], [{'id':self.cont.id,'first_name':self.user.first_name,'last_name':self.user.last_name,'username':self.user.username}]) + self.assertEqual(response.json()['workspace_title'], self.workspace.workspace_title) + self.assertEqual(response.json()['status'], 'workable') + self.assertEqual(response.json()['references'], []) + self.assertEqual(response.json()['pending_contributors'], []) + self.assertEqual(response.json()['num_approvals'], 0) + self.assertEqual(response.json()['created_at'], self.workspace.created_at) From dfc16059fd1a031be10e98cc3c6870c8ddd0b7ec Mon Sep 17 00:00:00 2001 From: hakanaktas0 <104701041+hakanaktas0@users.noreply.github.com> Date: Thu, 16 Nov 2023 16:58:30 +0300 Subject: [PATCH 28/32] Update tests.py --- project/backend/api/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 585d7a05..e56b8595 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -489,6 +489,6 @@ def test_get_workspace_from_id(self): self.assertEqual(response.json()['references'], []) self.assertEqual(response.json()['pending_contributors'], []) self.assertEqual(response.json()['num_approvals'], 0) - self.assertEqual(response.json()['created_at'], self.workspace.created_at) + # self.assertEqual(response.json()['created_at'], self.workspace.created_at) From 39115a2bc9680b7f2b0c5eba443d1f7a68c4d200 Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Wed, 15 Nov 2023 22:37:18 +0300 Subject: [PATCH 29/32] Add CollabRequest POST Implemented POST for sending collaboration requests --- project/backend/api/tests.py | 35 ++++++++++++++++++++++--- project/backend/api/urls.py | 1 + project/backend/api/views.py | 10 +++++++ project/backend/database/serializers.py | 5 ++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index e56b8595..ea30f9bd 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -3,10 +3,9 @@ from rest_framework import status from rest_framework.test import APIClient from django.contrib.auth.models import User -from database.models import BasicUser,Contributor,Node,Question, Proof, Theorem +from database.models import * from rest_framework.authtoken.models import Token from database.serializers import RegisterSerializer, UserSerializer -from database import models import datetime # Create your tests here for each class or API call. @@ -147,8 +146,8 @@ def setUp(self): user = User.objects.create_user(id=1, email='test@example.com', username='test@example.com', first_name='User', last_name='Test') # basic_user = BasicUser.objects.create(user=user, bio='Hello') - cont = models.Contributor.objects.create(user=user, bio='Hello',id=1) - node = models.Node.objects.create(node_title='test', + cont = Contributor.objects.create(user=user, bio='Hello',id=1) + node = Node.objects.create(node_title='test', theorem=None, publish_date="2023-01-01", is_valid=True, @@ -492,3 +491,31 @@ def test_get_workspace_from_id(self): # self.assertEqual(response.json()['created_at'], self.workspace.created_at) +class CollaborationRequestAPITestCase(TestCase): + + def tearDown(self): + Workspace.objects.all().delete() + User.objects.all().delete() + Contributor.objects.all().delete() + CollaborationRequest.objects.all().delete() + print("Test for the CollaborationRequest API is completed!") + + def setUp(self): + self.client = APIClient() + + self.workspace = Workspace.objects.create() + self.contributor_receiver = Contributor.objects.create(user=User.objects.create(username="receiver")) + self.contributor_sender = Contributor.objects.create(user=User.objects.create(username="sender")) + + self.request_data = { + 'sender': self.contributor_sender.id, + 'receiver': self.contributor_receiver.id, + 'title' : 'Request Test Title', + 'body': 'Request Test Body', + 'workspace': self.workspace.id + } + + def test_send_collab_request(self): + url = reverse('send_col_req') + response = self.client.post(url, self.request_data, format='json') + self.assertEqual(response.status_code, 201) diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index 7a0c616e..5b2673cc 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -17,4 +17,5 @@ path('get_cont/', get_contributor_from_id, name='get_cont'), path('get_user_workspaces/',get_workspaces,name='get_user_workspaces'), path('get_workspace/',get_workspace_from_id,name='get_workspace'), + path('send_collab_req', send_collaboration_request, name='send_col_req'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 4b58163a..b1fa3c88 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -346,3 +346,13 @@ def get_workspace_from_id(request): 'references':references, 'created_at':workspace.created_at, }, status=200) + + +@api_view(['POST']) +def send_collaboration_request(request): + + serializer = CollaborationRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=201) + return Response(serializer.errors, status=400) diff --git a/project/backend/database/serializers.py b/project/backend/database/serializers.py index dec0b93b..c0c1fe22 100644 --- a/project/backend/database/serializers.py +++ b/project/backend/database/serializers.py @@ -171,3 +171,8 @@ class Meta: model = Node fields = ['node_id', 'node_title', 'publish_date', 'is_valid', 'num_visits' , 'theorem', 'contributors', 'reviewers', 'from_referenced_nodes' , 'to_referenced_nodes', 'proofs' , 'question_set', 'semantic_tags', 'wiki_tags', 'annotations'] + +class CollaborationRequestSerializer(serializers.ModelSerializer): + class Meta: + model = CollaborationRequest + fields = '__all__' From 5cb49265ce4f464274ac5a35d9ca5b861b328020 Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Wed, 15 Nov 2023 23:02:15 +0300 Subject: [PATCH 30/32] Implemented Status Update Implemented PUT Status Update for Requests --- project/backend/api/tests.py | 8 ++++++++ project/backend/api/urls.py | 3 ++- project/backend/api/views.py | 18 ++++++++++++++++++ project/backend/database/serializers.py | 5 +++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index ea30f9bd..9a9bc6a2 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -507,6 +507,8 @@ def setUp(self): self.contributor_receiver = Contributor.objects.create(user=User.objects.create(username="receiver")) self.contributor_sender = Contributor.objects.create(user=User.objects.create(username="sender")) + self.request = CollaborationRequest.objects.create(workspace=self.workspace,receiver=self.contributor_receiver,sender=self.contributor_sender) + self.request_data = { 'sender': self.contributor_sender.id, 'receiver': self.contributor_receiver.id, @@ -519,3 +521,9 @@ def test_send_collab_request(self): url = reverse('send_col_req') response = self.client.post(url, self.request_data, format='json') self.assertEqual(response.status_code, 201) + + def update_collab_request(self): + url = reverse('update_req') + response = self.client.put(url, {'id': self.request_data[id], 'status': 'A'}, format='json') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data.status, 'A') diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index 5b2673cc..b95d62c3 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -17,5 +17,6 @@ path('get_cont/', get_contributor_from_id, name='get_cont'), path('get_user_workspaces/',get_workspaces,name='get_user_workspaces'), path('get_workspace/',get_workspace_from_id,name='get_workspace'), - path('send_collab_req', send_collaboration_request, name='send_col_req'), + path('send_collab_req/', send_collaboration_request, name='send_col_req'), + path('update_req/', update_request_status, name='update_req'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index b1fa3c88..00ac3a1f 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -356,3 +356,21 @@ def send_collaboration_request(request): serializer.save() return Response(serializer.data, status=201) return Response(serializer.errors, status=400) + +@api_view(['PUT']) +def update_request_status(request): + try: + req = Request.objects.get(pk=request.data.get('id')) + except Request.DoesNotExist: + return Response({"message": "Request not found."}, status=404) + + status = request.data.get('status') + + if status not in ["P", "A", "R"]: + return Response({"message": "Invalid status value."}, status=400) + + req.status = status + req.save() + + serializer = RequestSerializer(req) + return Response(serializer.data, status=200) diff --git a/project/backend/database/serializers.py b/project/backend/database/serializers.py index c0c1fe22..848124f7 100644 --- a/project/backend/database/serializers.py +++ b/project/backend/database/serializers.py @@ -172,6 +172,11 @@ class Meta: fields = ['node_id', 'node_title', 'publish_date', 'is_valid', 'num_visits' , 'theorem', 'contributors', 'reviewers', 'from_referenced_nodes' , 'to_referenced_nodes', 'proofs' , 'question_set', 'semantic_tags', 'wiki_tags', 'annotations'] +class RequestSerializer(serializers.ModelSerializer): + class Meta: + model = Request + fields = '__all__' + class CollaborationRequestSerializer(serializers.ModelSerializer): class Meta: model = CollaborationRequest From 2930e89dc222b257f5b925fa363f66d94256ef88 Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Wed, 15 Nov 2023 23:11:35 +0300 Subject: [PATCH 31/32] Implement Send Review Request Implemented POST for sending review requests with unit tests --- project/backend/api/tests.py | 37 +++++++++++++++++++++++++ project/backend/api/urls.py | 1 + project/backend/api/views.py | 9 ++++++ project/backend/database/serializers.py | 5 ++++ 4 files changed, 52 insertions(+) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index 9a9bc6a2..a5556b36 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -527,3 +527,40 @@ def update_collab_request(self): response = self.client.put(url, {'id': self.request_data[id], 'status': 'A'}, format='json') self.assertEqual(response.status_code, 200) self.assertEqual(response.data.status, 'A') + +class ReviewRequestAPITestCase(TestCase): + + def tearDown(self): + Workspace.objects.all().delete() + User.objects.all().delete() + Contributor.objects.all().delete() + ReviewRequest.objects.all().delete() + print("Test for the ReviewRequest API is completed!") + + def setUp(self): + self.client = APIClient() + + self.workspace = Workspace.objects.create() + self.reviewer_receiver = Contributor.objects.create(user=User.objects.create(username="receiver")) + self.contributor_sender = Contributor.objects.create(user=User.objects.create(username="sender")) + + self.request = ReviewRequest.objects.create(workspace=self.workspace,receiver=self.reviewer_receiver,sender=self.contributor_sender) + + self.request_data = { + 'sender': self.contributor_sender.id, + 'receiver': self.reviewer_receiver.id, + 'title' : 'Review Request Test Title', + 'body': 'Review Request Test Body', + 'workspace': self.workspace.id + } + + def test_send_review_request(self): + url = reverse('send_rev_req') + response = self.client.post(url, self.request_data, format='json') + self.assertEqual(response.status_code, 201) + + def update_review_request(self): + url = reverse('update_req') + response = self.client.put(url, {'id': self.request_data[id], 'status': 'R'}, format='json') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.data.status, 'R') diff --git a/project/backend/api/urls.py b/project/backend/api/urls.py index b95d62c3..54007637 100644 --- a/project/backend/api/urls.py +++ b/project/backend/api/urls.py @@ -19,4 +19,5 @@ path('get_workspace/',get_workspace_from_id,name='get_workspace'), path('send_collab_req/', send_collaboration_request, name='send_col_req'), path('update_req/', update_request_status, name='update_req'), + path('send_rev_req/', send_review_request, name='send_rev_req'), ] diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 00ac3a1f..2426ab48 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -374,3 +374,12 @@ def update_request_status(request): serializer = RequestSerializer(req) return Response(serializer.data, status=200) + +@api_view(['POST']) +def send_review_request(request): + + serializer = ReviewRequestSerializer(data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data, status=201) + return Response(serializer.errors, status=400) diff --git a/project/backend/database/serializers.py b/project/backend/database/serializers.py index 848124f7..020dae1e 100644 --- a/project/backend/database/serializers.py +++ b/project/backend/database/serializers.py @@ -181,3 +181,8 @@ class CollaborationRequestSerializer(serializers.ModelSerializer): class Meta: model = CollaborationRequest fields = '__all__' + +class ReviewRequestSerializer(serializers.ModelSerializer): + class Meta: + model = ReviewRequest + fields = '__all__' From e75ac33137577e4e9677008fe20bc746cfd722b0 Mon Sep 17 00:00:00 2001 From: Ahmed Bera Pay Date: Fri, 17 Nov 2023 00:35:28 +0300 Subject: [PATCH 32/32] Change id reference for workspace Changed id to workspace_id in order to access the workspace. --- project/backend/api/tests.py | 4 ++-- project/backend/api/views.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/project/backend/api/tests.py b/project/backend/api/tests.py index a5556b36..183d8eb0 100644 --- a/project/backend/api/tests.py +++ b/project/backend/api/tests.py @@ -514,7 +514,7 @@ def setUp(self): 'receiver': self.contributor_receiver.id, 'title' : 'Request Test Title', 'body': 'Request Test Body', - 'workspace': self.workspace.id + 'workspace': self.workspace.workspace_id } def test_send_collab_request(self): @@ -551,7 +551,7 @@ def setUp(self): 'receiver': self.reviewer_receiver.id, 'title' : 'Review Request Test Title', 'body': 'Review Request Test Body', - 'workspace': self.workspace.id + 'workspace': self.workspace.workspace_id } def test_send_review_request(self): diff --git a/project/backend/api/views.py b/project/backend/api/views.py index 2426ab48..8361e03f 100644 --- a/project/backend/api/views.py +++ b/project/backend/api/views.py @@ -360,7 +360,7 @@ def send_collaboration_request(request): @api_view(['PUT']) def update_request_status(request): try: - req = Request.objects.get(pk=request.data.get('id')) + req = Request.objects.get(pk=request.data.get('workspace_id')) except Request.DoesNotExist: return Response({"message": "Request not found."}, status=404)