diff --git a/.DS_Store b/.DS_Store index 1bcaeb96..684dd60e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/osinaweb/db.sqlite3 b/osinaweb/db.sqlite3 index 1d181ab6..9c1f2332 100644 Binary files a/osinaweb/db.sqlite3 and b/osinaweb/db.sqlite3 differ diff --git a/osinaweb/osinacore/__pycache__/models.cpython-310.pyc b/osinaweb/osinacore/__pycache__/models.cpython-310.pyc index dfca4d89..ac762040 100644 Binary files a/osinaweb/osinacore/__pycache__/models.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/models.cpython-310.pyc differ diff --git a/osinaweb/osinacore/__pycache__/views.cpython-310.pyc b/osinaweb/osinacore/__pycache__/views.cpython-310.pyc index c7fd8d75..c0c1c1a4 100644 Binary files a/osinaweb/osinacore/__pycache__/views.cpython-310.pyc and b/osinaweb/osinacore/__pycache__/views.cpython-310.pyc differ diff --git a/osinaweb/osinacore/migrations/0017_alter_project_end_date_alter_project_start_date.py b/osinaweb/osinacore/migrations/0017_alter_project_end_date_alter_project_start_date.py new file mode 100644 index 00000000..b2fa2996 --- /dev/null +++ b/osinaweb/osinacore/migrations/0017_alter_project_end_date_alter_project_start_date.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.5 on 2023-09-12 18:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('osinacore', '0016_rename_projectcredentials_projectcredential'), + ] + + operations = [ + migrations.AlterField( + model_name='project', + name='end_date', + field=models.CharField(max_length=200), + ), + migrations.AlterField( + model_name='project', + name='start_date', + field=models.CharField(max_length=200), + ), + ] diff --git a/osinaweb/osinacore/migrations/0018_epic_status.py b/osinaweb/osinacore/migrations/0018_epic_status.py new file mode 100644 index 00000000..69d5eea4 --- /dev/null +++ b/osinaweb/osinacore/migrations/0018_epic_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.5 on 2023-09-12 19:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('osinacore', '0017_alter_project_end_date_alter_project_start_date'), + ] + + operations = [ + migrations.AddField( + model_name='epic', + name='status', + field=models.CharField(choices=[('Open', 'Open'), ('Closed', 'Closed')], max_length=200, null=True), + ), + ] diff --git a/osinaweb/osinacore/migrations/0019_alter_epic_end_date_alter_epic_start_date.py b/osinaweb/osinacore/migrations/0019_alter_epic_end_date_alter_epic_start_date.py new file mode 100644 index 00000000..87347491 --- /dev/null +++ b/osinaweb/osinacore/migrations/0019_alter_epic_end_date_alter_epic_start_date.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.5 on 2023-09-12 19:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('osinacore', '0018_epic_status'), + ] + + operations = [ + migrations.AlterField( + model_name='epic', + name='end_date', + field=models.CharField(max_length=200), + ), + migrations.AlterField( + model_name='epic', + name='start_date', + field=models.CharField(max_length=200), + ), + ] diff --git a/osinaweb/osinacore/migrations/__pycache__/0017_alter_project_end_date_alter_project_start_date.cpython-310.pyc b/osinaweb/osinacore/migrations/__pycache__/0017_alter_project_end_date_alter_project_start_date.cpython-310.pyc new file mode 100644 index 00000000..9096da76 Binary files /dev/null and b/osinaweb/osinacore/migrations/__pycache__/0017_alter_project_end_date_alter_project_start_date.cpython-310.pyc differ diff --git a/osinaweb/osinacore/migrations/__pycache__/0018_epic_status.cpython-310.pyc b/osinaweb/osinacore/migrations/__pycache__/0018_epic_status.cpython-310.pyc new file mode 100644 index 00000000..25b74452 Binary files /dev/null and b/osinaweb/osinacore/migrations/__pycache__/0018_epic_status.cpython-310.pyc differ diff --git a/osinaweb/osinacore/migrations/__pycache__/0019_alter_epic_end_date_alter_epic_start_date.cpython-310.pyc b/osinaweb/osinacore/migrations/__pycache__/0019_alter_epic_end_date_alter_epic_start_date.cpython-310.pyc new file mode 100644 index 00000000..0b21cfe2 Binary files /dev/null and b/osinaweb/osinacore/migrations/__pycache__/0019_alter_epic_end_date_alter_epic_start_date.cpython-310.pyc differ diff --git a/osinaweb/osinacore/models.py b/osinaweb/osinacore/models.py index 86688436..a136f81a 100644 --- a/osinaweb/osinacore/models.py +++ b/osinaweb/osinacore/models.py @@ -100,8 +100,8 @@ class Project(models.Model): ('Cancelled', 'Cancelled'), ) status = models.CharField(max_length=200, choices=STATUS_CHOICES) - start_date = models.DateField() - end_date = models.DateField() + start_date = models.CharField(max_length=200) + end_date = models.CharField(max_length=200) project_id = models.CharField(max_length=20, null=True, blank=True) # Allow null and blank for initial creation def save(self, *args, **kwargs): if not self.project_id: @@ -114,8 +114,6 @@ class Project(models.Model): super(Project, self).save(*args, **kwargs) - - class Milestone(models.Model): title = models.CharField(max_length=150) description = models.TextField() @@ -126,10 +124,15 @@ class Milestone(models.Model): class Epic(models.Model): title = models.CharField(max_length=150) + STATUS_CHOICES = ( + ('Open', 'Open'), + ('Closed', 'Closed') + ) + status = models.CharField(max_length=200, choices=STATUS_CHOICES, null=True) description = models.TextField() project = models.ForeignKey(Project, on_delete=models.CASCADE, null=True) - start_date = models.DateField() - end_date = models.DateField() + start_date = models.CharField(max_length=200) + end_date = models.CharField(max_length=200) class ProjectRequirement(models.Model): diff --git a/osinaweb/osinacore/views.py b/osinaweb/osinacore/views.py index 66fa26a5..e7581e2d 100644 --- a/osinaweb/osinacore/views.py +++ b/osinaweb/osinacore/views.py @@ -5,9 +5,11 @@ from django.contrib.auth.decorators import login_required from django.contrib import messages from .forms import * from django.utils import timezone +from django.urls import reverse -# Create your views here. + +# Pages views def signin(request): if request.user.is_authenticated: @@ -84,9 +86,12 @@ def my_tasks(request, *args, **kwargs): @login_required def detailed_project(request, project_id): project = get_object_or_404(Project, project_id=project_id) + epics = Epic.objects.filter(project=project) + context = { 'project' : project, + 'epics' : epics } @@ -106,14 +111,24 @@ def createtask_project(request, project_id): @login_required def create_project(request): + staffs = StaffProfile.objects.all().order_by('-first_name') + project_types = ProjectType.objects.all() + customers = CustomerProfile.objects.all().order_by('-first_name') context = { + 'staffs' : staffs, + 'project_types' : project_types, + 'customers' : customers, + + } return render(request, 'create-project.html', context) @login_required -def create_epic(request): +def create_epic(request, project_id): + project = get_object_or_404(Project, project_id=project_id) context = { + 'project' : project, } return render(request, 'create-epic.html', context) @@ -134,6 +149,11 @@ def createtask_epic(request): return render(request, 'createtask-epic.html', context) + + + +# Modals views + def add_note_modal(request, *args, **kwargs): context = { @@ -141,7 +161,6 @@ def add_note_modal(request, *args, **kwargs): return render(request, 'addnote-modal.html', context) - def add_status_modal(request, *args, **kwargs): context = { @@ -198,6 +217,15 @@ def update_status_modal(request, *args, **kwargs): return render(request, 'update-status-modal.html', context) + + + + + + +#Save Functions + + @login_required def save_note(request): if request.method == 'POST': @@ -215,6 +243,85 @@ def save_note(request): note.save() - # return redirect('home') # Redirect to a success page or another view + + return render(request, 'addnote-modal.html') + + +@login_required +def save_project(request): + if request.method == 'POST': + name = request.POST.get('name') + customer_username = request.POST.get('customer') + manager_username = request.POST.get('manager') + project_type = request.POST.getlist('project_type') # Use getlist for multi-select fields + details = request.POST.get('details') + members_usernames = request.POST.getlist('members') # Use getlist for multi-select fields + status = request.POST.get('status') + start_date = request.POST.get('start_date') + end_date = request.POST.get('end_date') + + # Fetch the associated profiles + try: + customer_profile = CustomerProfile.objects.get(user__username=customer_username) + manager_profile = StaffProfile.objects.get(user__username=manager_username) + members_profiles = StaffProfile.objects.filter(user__username__in=members_usernames) + except (CustomerProfile.DoesNotExist, StaffProfile.DoesNotExist): + + pass + + # Create and save the project + project = Project( + name=name, + customer=customer_profile, + manager=manager_profile, + details=details, + status=status, + start_date=start_date, + end_date=end_date, + ) + project.save() + + + project.project_type.set(project_type) + project.members.set(members_profiles) + + return redirect('my-projects') + + return render(request, 'createproject.html') + + +@login_required +def save_epic(request): + if request.method == 'POST': + title = request.POST.get('title') + status = request.POST.get('status') + description = request.POST.get('description') + project_id = request.POST.get('project') # Get project ID as a string + + # Retrieve the Project instance + try: + project = Project.objects.get(id=project_id) + except Project.DoesNotExist: + # Handle the case where the project with the provided ID doesn't exist + # You might want to display an error message or redirect to an appropriate page. + pass + + start_date = request.POST.get('start_date') + end_date = request.POST.get('end_date') + + # Create the Epic object with the Project instance + epic = Epic( + title=title, + status=status, + project=project, # Assign the Project instance + description=description, + start_date=start_date, + end_date=end_date + ) + + # Save the Epic object to the database + epic.save() - return render(request, 'addnote-modal.html') \ No newline at end of file + # Redirect to the detailed project page + redirect_url = reverse('detailed-project', args=[project.project_id]) + return redirect(redirect_url) diff --git a/osinaweb/osinaweb/__pycache__/urls.cpython-310.pyc b/osinaweb/osinaweb/__pycache__/urls.cpython-310.pyc index b314849c..9050fd04 100644 Binary files a/osinaweb/osinaweb/__pycache__/urls.cpython-310.pyc and b/osinaweb/osinaweb/__pycache__/urls.cpython-310.pyc differ diff --git a/osinaweb/osinaweb/urls.py b/osinaweb/osinaweb/urls.py index 1b8cabfd..f24600d7 100644 --- a/osinaweb/osinaweb/urls.py +++ b/osinaweb/osinaweb/urls.py @@ -19,6 +19,8 @@ from osinacore import views from django.contrib.auth.decorators import login_required urlpatterns = [ + + # Pages urls path('admin/', admin.site.urls), path('login', views.signin, name='signin'), path('logout/', views.signout, name='signout'), @@ -27,21 +29,26 @@ urlpatterns = [ path('my-tasks/', login_required(views.my_tasks), name='my-tasks'), path('detailedproject//', views.detailed_project, name='detailed-project'), path('createproject/', views.create_project, name='createproject'), - path('createepic/', views.create_epic, name='createepic'), + path('createepic//', views.create_epic, name='createepic'), path('createtask/', views.create_task, name='createtask'), path('createtask//', views.createtask_project, name='createtaskproject'), path('createtaskepic/', views.createtask_epic, name='createtaskepic'), + + # Modals urls path('addstatus/', views.add_status_modal, name='addstatus'), path('addnote/', views.add_note_modal, name='addnote'), path('addfile/', views.add_file_modal, name='addfile'), path('addcredentials/', views.add_credentials_modal, name='addcredentials'), path('updatestatus/', views.update_status_modal, name='updatestatus'), - path('save_note/', views.save_note, name='save_note'), - path('addpoint/', views.add_point_modal, name='addpoint'), path('showpoints/', views.show_points_modal, name='showpoints'), path('addtime/', views.add_time_modal, name='addtime'), path('timeline/', views.timeline_modal, name='timeline'), path('deletetask/', views.delete_task_modal, name='deletetask'), + + # Save Urls + path('save_note/', views.save_note, name='save_note'), + path('save_project/', views.save_project, name='save_project'), + path('save_epic/', views.save_epic, name='save_epic'), ] diff --git a/osinaweb/templates/create-epic.html b/osinaweb/templates/create-epic.html index 21a23448..8563bb5d 100644 --- a/osinaweb/templates/create-epic.html +++ b/osinaweb/templates/create-epic.html @@ -5,40 +5,47 @@

- Create Epic + Create Epic for {{project.name}}

-
- + {% csrf_token %} + - -
-
-
-
-
+
diff --git a/osinaweb/templates/create-project.html b/osinaweb/templates/create-project.html index 739a4996..56fb52eb 100644 --- a/osinaweb/templates/create-project.html +++ b/osinaweb/templates/create-project.html @@ -10,48 +10,53 @@ Create Project -
- + {% csrf_token %} + - - - - - + + {% for staff in staffs %} + + {% endfor %} - - + -
@@ -69,13 +74,13 @@
-
-
@@ -107,11 +112,11 @@ -->
- + Project
-
+
diff --git a/osinaweb/templates/project-details.html b/osinaweb/templates/project-details.html index fd31b1d3..23b39849 100644 --- a/osinaweb/templates/project-details.html +++ b/osinaweb/templates/project-details.html @@ -90,7 +90,7 @@ {% endif %} - {% if project.projectfile_set.all %}

Related Files:

@@ -248,10 +242,8 @@
- {%endif%} - {% if project.projectcredential_set.all %}

Credentials:

@@ -296,7 +288,6 @@
- {%endif%}
@@ -323,21 +314,20 @@
+ + +