diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9903a07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +# Django # +*.log +*.pot +*.pyc +__pycache__ +db.sqlite3 +media + +# Backup files # +*.bak + +# Python # +*.py[cod] +*$py.class + +# Distribution / packaging +.Python build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +.pytest_cache/ +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Visual Studio Code # +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history diff --git a/db.sqlite3 b/db.sqlite3 deleted file mode 100644 index 4b81901..0000000 Binary files a/db.sqlite3 and /dev/null differ diff --git a/myapp/__pycache__/__init__.cpython-37.pyc b/myapp/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index 85b3d18..0000000 Binary files a/myapp/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/myapp/__pycache__/admin.cpython-37.pyc b/myapp/__pycache__/admin.cpython-37.pyc deleted file mode 100644 index 4963cc4..0000000 Binary files a/myapp/__pycache__/admin.cpython-37.pyc and /dev/null differ diff --git a/myapp/__pycache__/forms.cpython-37.pyc b/myapp/__pycache__/forms.cpython-37.pyc deleted file mode 100644 index c8eb798..0000000 Binary files a/myapp/__pycache__/forms.cpython-37.pyc and /dev/null differ diff --git a/myapp/__pycache__/models.cpython-37.pyc b/myapp/__pycache__/models.cpython-37.pyc deleted file mode 100644 index a074bf0..0000000 Binary files a/myapp/__pycache__/models.cpython-37.pyc and /dev/null differ diff --git a/myapp/__pycache__/urls.cpython-37.pyc b/myapp/__pycache__/urls.cpython-37.pyc deleted file mode 100644 index 659d7a6..0000000 Binary files a/myapp/__pycache__/urls.cpython-37.pyc and /dev/null differ diff --git a/myapp/__pycache__/views.cpython-37.pyc b/myapp/__pycache__/views.cpython-37.pyc deleted file mode 100644 index 71246c0..0000000 Binary files a/myapp/__pycache__/views.cpython-37.pyc and /dev/null differ diff --git a/myapp/forms.py b/myapp/forms.py index 03666ab..f21dba5 100644 --- a/myapp/forms.py +++ b/myapp/forms.py @@ -6,11 +6,31 @@ from . import models # validator to ensure email addresses are unique -def must_be_unique(value): +def must_be_unique_email(value): user = User.objects.filter(email=value) if len(user) > 0: raise forms.ValidationError("A user with that email already exists.") +# validator to ensure usernames are unique +def must_be_unique_user(value): + user = User.objects.filter(username=value) + if len(user) > 0: + raise forms.ValidationError("A user with that username already exists.") + +ISSUE_CHOICES = [ + ('Desktop', 'Desktop'), + ('Laptop', 'Laptop'), + ('Tablet', 'Tablet'), + ('Phone', 'Phone'), + ('Server', 'Server'), + ('Networking', 'Networking'), + ('Application', 'Application'), + ('Operating System', 'Operating System'), + ('Email', 'Email'), + ('Account Management', 'Account Management'), + ('Lost Password', 'Lost Password'), + ('Other', 'Other') +] class IssueForm(forms.Form): title = forms.CharField( widget = forms.TextInput( @@ -30,65 +50,17 @@ class IssueForm(forms.Form): max_length=240 ) - issue_type = forms.IntegerField( - widget = forms.TextInput( - attrs={'class': 'form-control'} - ), + issue_type = forms.CharField( label='Issue Type', + widget=forms.Select(choices=ISSUE_CHOICES), required=True ) - """ - date_created = forms.CharField( - widget = forms.TextInput( - attrs={'class': 'form-control'} - ), - label='Date Created', - required=True, - ) - """ - - """ - assigned_user = forms.CharField( - widget = forms.TextInput( - attrs={'class': 'form-control'} - ), - label='Assigned User', - required=False, - max_length=50 - ) - """ - - # this field will eventually be removed as the affected user will - # be automatically set to the user who is logged in - """ - affected_user = forms.CharField( - widget = forms.TextInput( - attrs={'class': 'form-control'} - ), - label='Affected User', - required=True, - max_length=50, - ) - """ - # it's now been removed :D - - """ - is_solved = forms.BooleanField( - widget = forms.CheckboxInput( - attrs={'class':'form-check'} - ), - label='Is this issue solved?' - ) - """ - def save(self, this_user): issues_instance = models.Issue_Model() issues_instance.title = self.cleaned_data["title"] issues_instance.description = self.cleaned_data["description"] issues_instance.issue_type = self.cleaned_data["issue_type"] - #issues_instance.date_created = self.cleaned_data["date_created"] - #issues_instance.assigned_user = self.cleaned_data["assigned_user"] issues_instance.affected_user = this_user issues_instance.is_solved = 0 issues_instance.save() @@ -107,7 +79,7 @@ class IssueFilter(forms.Form): max_length=100 ) - issue_type = forms.IntegerField( + issue_type = forms.CharField( widget = forms.TextInput( attrs={ 'class': 'form-control', @@ -122,7 +94,7 @@ class RegistrationForm(UserCreationForm): email = forms.EmailField( label="Email", required=True, - validators=[must_be_unique] + validators=[must_be_unique_email] ) class Meta: @@ -148,18 +120,22 @@ def save(self, commit=True): return user class ProfileForm(forms.Form): + """ user_name = forms.CharField( widget = forms.TextInput( attrs={'class': 'form-control'} ), label='User Name', required=False, + validators=[must_be_unique_user], max_length=150 ) - + """ + email = forms.EmailField( label="Email", required=False + #validators=[must_be_unique_email] ) bio = forms.CharField( @@ -171,29 +147,44 @@ class ProfileForm(forms.Form): max_length=720 ) + location = forms.CharField( + widget = forms.TextInput( + attrs={'class': 'form-control'} + ), + label='Location', + required=False, + max_length=100 + ) + def save(self,id): this_user = User.objects.get(id__exact=id) if self.cleaned_data["email"] and self.cleaned_data["email"] != this_user.email: this_user.email = self.cleaned_data["email"] - if self.cleaned_data['user_name']: - this_user.username = self.cleaned_data["user_name"] + #if self.cleaned_data['user_name']: + # this_user.username = self.cleaned_data["user_name"] if self.cleaned_data['bio']: this_user.profile.bio = self.cleaned_data["bio"] + if self.cleaned_data['location']: + this_user.profile.location = self.cleaned_data["location"] this_user.save() return this_user class ProfileFormNontech(forms.Form): + """ user_name = forms.CharField( widget = forms.TextInput( attrs={'class': 'form-control'} ), label='User Name', required=False, + validators=[must_be_unique_user], max_length=150 ) - + """ + email = forms.EmailField( label="Email", + #validators=[must_be_unique_email], required=False ) @@ -201,8 +192,8 @@ def save(self,id): this_user = User.objects.get(id__exact=id) if self.cleaned_data["email"] and self.cleaned_data["email"] != this_user.email: this_user.email = self.cleaned_data["email"] - if self.cleaned_data['user_name']: - this_user.username = self.cleaned_data["user_name"] + #if self.cleaned_data['user_name']: + # this_user.username = self.cleaned_data["user_name"] this_user.save() return this_user @@ -230,3 +221,141 @@ class ProfileFilter(forms.Form): required=False, max_length=100 ) + + location = forms.CharField( + widget = forms.TextInput( + attrs={ + 'class': 'form-control font-weight-normal', + 'id': 'issue_type' + } + ), + label='Filter by Location', + required=False, + max_length=100 + ) + +STARS = [ + ('5','5'), + ('4','4'), + ('3','3'), + ('2','2'), + ('1','1'), + ('0','0'), +] +class AddReviewForm(forms.Form): + rating = forms.CharField( + widget = forms.Select( + choices=STARS, + attrs={'class': 'form-control'} + ), + label='Rating', + required=True + ) + + review = forms.CharField( + label='Review', + widget=forms.Textarea( + attrs={'class': 'form-control'} + ), + required=False, + max_length=240 + ) + + def save(self, writer, subject): + review_instance = models.Review() + review_instance.rating = int(self.cleaned_data["rating"]) + review_instance.review = self.cleaned_data["review"] + review_instance.writer = User.objects.get(id__exact=writer) + review_instance.subject = User.objects.get(id__exact=subject) + review_instance.save() + subject_instance = models.Profile.objects.get(user=review_instance.subject) + subject_instance.rating_count = subject_instance.rating_count + 1 + subject_instance.rating_sum = subject_instance.rating_sum + review_instance.rating + subject_instance.rating_avg = round(subject_instance.rating_sum / subject_instance.rating_count,1) + subject_instance.save() + return review_instance + +class EditReviewForm(forms.Form): + rating = forms.CharField( + widget = forms.Select( + choices=STARS, + attrs={'class': 'form-control'} + ), + label='Rating', + required=True + ) + + review = forms.CharField( + label='Review', + widget=forms.Textarea( + attrs={'class': 'form-control'} + ), + required=False, + max_length=240 + ) + + def save(self, id): + review_instance = models.Review.objects.get(id__exact=id) + subject_instance = models.Profile.objects.get(user=review_instance.subject) + subject_instance.rating_sum = subject_instance.rating_sum - review_instance.rating + review_instance.rating = int(self.cleaned_data["rating"]) + subject_instance.rating_sum = subject_instance.rating_sum + review_instance.rating + review_instance.review = self.cleaned_data["review"] + subject_instance.rating_avg = round(subject_instance.rating_sum / subject_instance.rating_count,1) + subject_instance.save() + review_instance.save() + return review_instance + +class ResolveIssueForm(forms.Form): + resolution = forms.CharField( + widget=forms.Textarea( + attrs={'class': 'form-control'} + ), + label='Resolution', + required=False, + max_length=720 + ) + + def save(self, id): + this_ticket = models.Issue_Model.objects.get(id__exact=id) + this_ticket.is_solved = 1 + if self.cleaned_data['resolution']: + this_ticket.resolution = self.cleaned_data["resolution"] + this_ticket.save() + return this_ticket + +class EditIssueForm(forms.Form): + title = forms.CharField( + widget = forms.TextInput( + attrs={'class': 'form-control'} + ), + label='Title', + required=True, + max_length=100 + ) + + description = forms.CharField( + label='Description', + widget=forms.Textarea( + attrs={'class': 'form-control'} + ), + required=False, + max_length=240 + ) + + issue_type = forms.CharField( + label='Issue Type', + widget=forms.Select(choices=ISSUE_CHOICES), + required=True + ) + + def save(self, id): + this_ticket = models.Issue_Model.objects.get(id__exact=id) + if self.cleaned_data['title']: + this_ticket.title = self.cleaned_data["title"] + if self.cleaned_data['description']: + this_ticket.description = self.cleaned_data["description"] + if self.cleaned_data['issue_type']: + this_ticket.issue_type = self.cleaned_data["issue_type"] + this_ticket.save() + return this_ticket diff --git a/myapp/migrations/__pycache__/0001_initial.cpython-37.pyc b/myapp/migrations/__pycache__/0001_initial.cpython-37.pyc deleted file mode 100644 index 02ce77d..0000000 Binary files a/myapp/migrations/__pycache__/0001_initial.cpython-37.pyc and /dev/null differ diff --git a/myapp/migrations/__pycache__/__init__.cpython-37.pyc b/myapp/migrations/__pycache__/__init__.cpython-37.pyc deleted file mode 100644 index abd2b75..0000000 Binary files a/myapp/migrations/__pycache__/__init__.cpython-37.pyc and /dev/null differ diff --git a/myapp/models.py b/myapp/models.py index ea21d20..600a393 100644 --- a/myapp/models.py +++ b/myapp/models.py @@ -2,29 +2,41 @@ from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver +from django.core.validators import MinValueValidator, MaxValueValidator # Create your models here. class Issue_Model(models.Model): - title = models.CharField(max_length=100) - description = models.CharField(max_length=240, null=True) - issue_type = models.IntegerField() - date_created = models.DateField(auto_now_add=True) - assigned_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='assigned_user') - affected_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='affected_user') - is_solved = models.BooleanField(null=True) # 0 for unsolved, 1 for solved + title = models.CharField(max_length=100) + description = models.CharField(max_length=240, null=True) + issue_type = models.CharField(max_length=240) + date_created = models.DateField(auto_now_add=True) + assigned_user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='assigned_user') + affected_user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='affected_user') + is_solved = models.BooleanField(null=True) # 0 for unsolved, 1 for solved + resolution = models.CharField(max_length=240, null=True) class Profile(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) - bio = models.TextField(null=True, max_length=500, blank=True) - location = models.CharField(null=True, max_length=200) - user_type = models.BooleanField(null=True) # 0 for user, 1 for ODITer - birth_date = models.DateField(null=True, blank=True) + user = models.OneToOneField(User, on_delete=models.CASCADE) + bio = models.TextField(null=True, max_length=500, blank=True) + location = models.CharField(null=True, max_length=200) + user_type = models.BooleanField(null=True) # 0 for user, 1 for ODITer + birth_date = models.DateField(null=True, blank=True) + rating_sum = models.IntegerField(default=0) + rating_count = models.IntegerField(default=0) + rating_avg = models.FloatField(default=0) @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): - if created: - Profile.objects.create(user=instance) + if created: + Profile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): - instance.profile.save() + instance.profile.save() + +class Review(models.Model): + writer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='writer') + subject = models.ForeignKey(User, on_delete=models.CASCADE, related_name='subject') + date_created = models.DateField(auto_now_add=True) + rating = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(5)]) + review = models.CharField(max_length=240, null=True) diff --git a/myapp/templates/base.html b/myapp/templates/base.html index 9bb8ded..e912a15 100644 --- a/myapp/templates/base.html +++ b/myapp/templates/base.html @@ -15,11 +15,11 @@ {% if user.is_authenticated %}
{{ bio }}
+{{ location }}
{% else %} - Sign Up to be a Technician! + Sign Up to be a Technician!