From af22bde326c7c045dc39862e73278d56ba1d5d9c Mon Sep 17 00:00:00 2001 From: Anjnaimhatre Date: Fri, 24 Oct 2025 18:07:01 +0530 Subject: [PATCH] feat(ui): add register interest modal form to dashboard --- .envs/.local/.django | 8 +- .envs/.local/.postgres | 1 + codershq/api/serializers.py | 78 ++++++++- codershq/assessment/forms.py | 19 +- codershq/assessment/urls.py | 5 +- codershq/assessment/views.py | 25 ++- codershq/dashboard/urls.py | 6 +- codershq/dashboard/views.py | 24 ++- .../migrations/0009_auto_20251017_0504.py | 28 +++ codershq/templates/_dashboard.html | 164 +++++++++++++++++- codershq/templates/account/login.html | 2 +- .../templates/assessment/plural_password.html | 5 +- .../templates/assessment/profile_form.html | 7 +- codershq/templates/base.html | 3 + codershq/templates/dashboard/base.html | 2 +- codershq/templates/root.html | 86 ++++----- .../templates/users/user_interest_form.html | 14 ++ codershq/users/admin.py | 22 ++- codershq/users/forms.py | 60 +++++++ codershq/users/migrations/0005_assessment.py | 37 ++++ .../users/migrations/0006_userinterest.py | 41 +++++ .../migrations/0007_auto_20251023_1330.py | 42 +++++ codershq/users/models.py | 66 ++++++- codershq/users/templatetags/form_extras.py | 8 + config/settings/local.py | 19 ++ config/urls.py | 7 + local.yml | 28 +-- 27 files changed, 721 insertions(+), 86 deletions(-) create mode 100644 codershq/portfolio/migrations/0009_auto_20251017_0504.py create mode 100644 codershq/templates/users/user_interest_form.html create mode 100644 codershq/users/migrations/0005_assessment.py create mode 100644 codershq/users/migrations/0006_userinterest.py create mode 100644 codershq/users/migrations/0007_auto_20251023_1330.py create mode 100644 codershq/users/templatetags/form_extras.py diff --git a/.envs/.local/.django b/.envs/.local/.django index 3718eaef..0a03ceca 100644 --- a/.envs/.local/.django +++ b/.envs/.local/.django @@ -1,4 +1,6 @@ # General +DJANGO_SETTINGS_MODULE=config.settings.local + # ------------------------------------------------------------------------------ USE_DOCKER=yes IPYTHONDIR=/app/.ipython @@ -25,4 +27,8 @@ SLACK_TOKEN=xoxb-1835271736544-1830161031810-VovHkwU9mK3x8quSPkeG01iO # ASSESSMENT # ------------------------------------------------------------------------------ -ASSESSMENT_PASSWORD=test_password \ No newline at end of file +ASSESSMENT_PASSWORD=test_password + +#adding database url +DATABASE_URL=postgres://RHSQIZWBALCEoMwzlabSEAiqjgOFvLD:Ozs0ll0FqF2fHftZJ13vYWdrS1glWu3lCAA8yyHUkfJs70u6eTBcuisrGL8Ir2nA@postgres:5432/codershq +CELERY_BROKER_URL=redis://redis:6379/0 diff --git a/.envs/.local/.postgres b/.envs/.local/.postgres index 11a9f9ad..59577750 100644 --- a/.envs/.local/.postgres +++ b/.envs/.local/.postgres @@ -5,3 +5,4 @@ POSTGRES_PORT=5432 POSTGRES_DB=codershq POSTGRES_USER=RHSQIZWBALCEoMwzlabSEAiqjgOFvLD POSTGRES_PASSWORD=Ozs0ll0FqF2fHftZJ13vYWdrS1glWu3lCAA8yyHUkfJs70u6eTBcuisrGL8Ir2nA + diff --git a/codershq/api/serializers.py b/codershq/api/serializers.py index 50910554..6dd890f8 100644 --- a/codershq/api/serializers.py +++ b/codershq/api/serializers.py @@ -1,4 +1,4 @@ -from django.contrib.auth import get_user_model +"""from django.contrib.auth import get_user_model from django.contrib.auth.models import Group, User from django.contrib.auth.password_validation import validate_password from djangosaml2idp.models import ServiceProvider @@ -60,3 +60,79 @@ def create(self, validated_data): user.save() return user +""" +#new +from django.contrib.auth import get_user_model +from django.contrib.auth.password_validation import validate_password +from rest_framework import serializers +from rest_framework.validators import UniqueValidator +from codershq.users.models import User +from codershq.portfolio.models import Portfolio +from rest_framework import serializers + +User = get_user_model() # Use custom user model + +class UserSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = User + fields = ['url', 'username', 'email', 'groups','id'] + +class PortfolioSerializer(serializers.ModelSerializer): + class Meta: + model = Portfolio + fields = '__all__' + + +class RegisterSerializer(serializers.ModelSerializer): + email = serializers.EmailField( + required=True, + validators=[UniqueValidator(queryset=User.objects.all())] + ) + + password = serializers.CharField( + write_only=True, + required=True, + validators=[validate_password] + ) + + password2 = serializers.CharField( + write_only=True, + required=True, + label="Confirm Password" + ) + + class Meta: + model = User + fields = ( + 'username', + 'email', + 'first_name', + 'last_name', + 'password', + 'password2', + ) + extra_kwargs = { + 'first_name': {'required': True}, + 'last_name': {'required': True}, + } + + def validate(self, attrs): + if attrs['password'] != attrs['password2']: + raise serializers.ValidationError({ + "password": "Passwords do not match." + }) + return attrs + + def create(self, validated_data): + # Remove password2 from data before creating the user + validated_data.pop('password2') + + user = User( + username=validated_data['username'], + email=validated_data['email'], + first_name=validated_data['first_name'], + last_name=validated_data['last_name'] + ) + user.set_password(validated_data['password']) + user.save() + return user diff --git a/codershq/assessment/forms.py b/codershq/assessment/forms.py index 474903c1..5081fd84 100644 --- a/codershq/assessment/forms.py +++ b/codershq/assessment/forms.py @@ -1,4 +1,21 @@ from django import forms +from codershq.users.models import Assessment +#class PluralPasswordForm(forms.Form): + # password = forms.PasswordInput('password', max_length=255) + # adding +from django import forms class PluralPasswordForm(forms.Form): - password = forms.PasswordInput('password', max_length=255) + password = forms.CharField( + widget=forms.PasswordInput, + max_length=255, + label='Password' + ) + +from django import forms + +#adding Assesment form +class AssessmentForm(forms.ModelForm): + class Meta: + model = Assessment + exclude = ['user', 'submitted_at'] diff --git a/codershq/assessment/urls.py b/codershq/assessment/urls.py index ba319266..b6d3dc91 100644 --- a/codershq/assessment/urls.py +++ b/codershq/assessment/urls.py @@ -6,6 +6,9 @@ urlpatterns = [ path('idp/', include('djangosaml2idp.urls', namespace='djangosaml2')), path('login/', LoginView.as_view(template_name='idp/login.html'), name='login'), - path('logout/', LogoutView.as_view()), + path('logout/', LogoutView.as_view(),name='logout'), #adding name path('', views.IndexView.as_view()), + # App views + path('', views.IndexView.as_view(), name='index'), # Only one root path + path('assessment/', views.assessment_form, name='assessment_form'), ] diff --git a/codershq/assessment/views.py b/codershq/assessment/views.py index 5cecd8ce..bbd0e2ef 100755 --- a/codershq/assessment/views.py +++ b/codershq/assessment/views.py @@ -1,7 +1,9 @@ from django.conf import settings from django.views.generic import TemplateView from djangosaml2idp.models import ServiceProvider - +from .forms import AssessmentForm +from django.contrib.auth.decorators import login_required +from django.shortcuts import render, redirect class IndexView(TemplateView): template_name = "assessment/index.html" @@ -17,4 +19,25 @@ def get_context_data(self, **kwargs): "known_sp_ids": [sp for sp in ServiceProvider.objects.filter(active=True)], }) return context + #added assessment function +@login_required +def assessment_form(request): + if request.method == 'POST': + print("Form POST submitted") + profile_form = AssessmentForm(request.POST) + if profile_form.is_valid(): + print("Form is valid") + assessment = profile_form.save(commit=False) + assessment.user = request.user + assessment.save() + print("Redirecting to dashboard:home") + return redirect('dashboard:home') # or use reverse() + else: + print("Form is invalid:") + print(profile_form.errors) + else: + profile_form = AssessmentForm() + return render(request, 'assessment/plural_password.html', { + 'profile_form': profile_form + }) diff --git a/codershq/dashboard/urls.py b/codershq/dashboard/urls.py index 68dded78..50f6a1f8 100644 --- a/codershq/dashboard/urls.py +++ b/codershq/dashboard/urls.py @@ -5,8 +5,12 @@ app_name = "dashboard" urlpatterns = [ - # path('', TemplateView.as_view(template_name="dashboard/home.html"), name="home"), + # path('', TemplateView.as_view(template_name="dashboard/home.html"), name="home"), path("", views.index, name="home"), path("landing/", views.landing, name="landing"), path("news/", views.news, name="news"), + ] + + + diff --git a/codershq/dashboard/views.py b/codershq/dashboard/views.py index 7b52be64..9a298197 100644 --- a/codershq/dashboard/views.py +++ b/codershq/dashboard/views.py @@ -1,14 +1,26 @@ -import requests from django.shortcuts import redirect, render - -news_url = "https://www.reddit.com/r/programming/.json" - +from django.http import JsonResponse +from codershq.users.forms import UserInterestForm +from codershq.users.models import UserInterest def index(request): if not request.user.is_authenticated: return redirect("/accounts/login/") - return redirect("/accounts/login/") - # return render(request, "pages/dashboard.html") + + instance, created = UserInterest.objects.get_or_create(user=request.user) + + # ✅ Handle AJAX POST (inside modal) + if request.method == "POST" and request.headers.get("x-requested-with") == "XMLHttpRequest": + form = UserInterestForm(request.POST, instance=instance) + if form.is_valid(): + form.save() + message = "✅ Interests registered successfully." if created else "✅ Interests updated successfully." + return JsonResponse({"message": message}) + return JsonResponse({"errors": form.errors}, status=400) + + # GET: Render base page with button + form = UserInterestForm() + return render(request, "_dashboard.html", {"form": form}) def landing(request): diff --git a/codershq/portfolio/migrations/0009_auto_20251017_0504.py b/codershq/portfolio/migrations/0009_auto_20251017_0504.py new file mode 100644 index 00000000..eb9eb016 --- /dev/null +++ b/codershq/portfolio/migrations/0009_auto_20251017_0504.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.11 on 2025-10-17 01:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('portfolio', '0008_auto_20221010_0132'), + ] + + operations = [ + migrations.AlterField( + model_name='portfolio', + name='about', + field=models.TextField(blank=True, help_text='Tell us a bit about yourself', max_length=1500, verbose_name='Use this space to tell us about yourself'), + ), + migrations.AlterField( + model_name='portfolio', + name='academic_qualification', + field=models.CharField(help_text='e.g. MSc Sustainable Energy Technologies', max_length=30, verbose_name='Your highest academic qualification'), + ), + migrations.AlterField( + model_name='portfolio', + name='fav_language', + field=models.CharField(blank=True, help_text='This can be a language or framework', max_length=50, null=True, verbose_name='Whats your favourite programming language?'), + ), + ] diff --git a/codershq/templates/_dashboard.html b/codershq/templates/_dashboard.html index 0ea7d720..0fe5c225 100644 --- a/codershq/templates/_dashboard.html +++ b/codershq/templates/_dashboard.html @@ -1,3 +1,4 @@ +{% load form_extras %} + + + + +
@@ -340,11 +388,123 @@

- Login + Login + + {% endif %}

+ + + + + + + + - + \ No newline at end of file diff --git a/codershq/templates/account/login.html b/codershq/templates/account/login.html index a21ec866..972e88a2 100644 --- a/codershq/templates/account/login.html +++ b/codershq/templates/account/login.html @@ -1,6 +1,6 @@ {% extends "account/base.html" %} -{% load i18n static %} +{% load static i18n %} {% load account socialaccount %} {% load crispy_forms_tags %} diff --git a/codershq/templates/assessment/plural_password.html b/codershq/templates/assessment/plural_password.html index d08dda43..78128528 100644 --- a/codershq/templates/assessment/plural_password.html +++ b/codershq/templates/assessment/plural_password.html @@ -5,9 +5,10 @@ {% block head_title %}{% trans "Assessment" %}{% endblock %} {% block inner %} -
+ {% csrf_token %} - {{ form|crispy }} + {{ profile_form|crispy }} +
Logout diff --git a/codershq/templates/assessment/profile_form.html b/codershq/templates/assessment/profile_form.html index 77cddbbc..842697ed 100644 --- a/codershq/templates/assessment/profile_form.html +++ b/codershq/templates/assessment/profile_form.html @@ -5,12 +5,14 @@ {% block head_title %}{% trans "Assessment" %}{% endblock %} {% block inner %} - +

If you would like to take an assessment with us at CodersHQ then please fill the form below

{% csrf_token %} - {{ form|crispy }} + + {{ profile_form|crispy }} +

By submitting this form, you agree to sharing the data your provided and the assessment scores with potential employers

@@ -23,7 +25,6 @@
- + + +{% endblock %} diff --git a/codershq/users/admin.py b/codershq/users/admin.py index ca0b25e6..9a2472f8 100644 --- a/codershq/users/admin.py +++ b/codershq/users/admin.py @@ -3,7 +3,7 @@ from django.contrib.auth import get_user_model from django.utils.translation import gettext_lazy as _ -from codershq.users.forms import UserChangeForm, UserCreationForm +from codershq.users.forms import UserChangeForm, UserCreationForm,UserInterest User = get_user_model() @@ -36,3 +36,23 @@ class UserAdmin(auth_admin.UserAdmin): ) list_display = ["username", "email","date_joined", "is_superuser"] search_fields = ["name"] + +from django.contrib import admin +from .models import UserInterest + +@admin.register(UserInterest) +class UserInterestAdmin(admin.ModelAdmin): + list_display = ( + "user", + "learn", "assessment", "meetups", "challenges", + "hackathons", "conferences", "get_inspired", "internship", + "open_source", "jobs", "golden_visa", "host_hackathon", "workstation_access", + "web_dev", "data_science", "app_dev", "cloud", "devops", + "blockchain", "cybersecurity", "embedded_systems", + ) + list_filter = ( + "learn", "assessment", "meetups", "hackathons", + "jobs", "web_dev", "data_science", "cybersecurity" + ) + search_fields = ("user__username", "user__email") + ordering = ("user__username",) diff --git a/codershq/users/forms.py b/codershq/users/forms.py index bee9c1b4..8de258f8 100644 --- a/codershq/users/forms.py +++ b/codershq/users/forms.py @@ -3,6 +3,7 @@ from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from django import forms +from codershq.users.models import UserInterest User = get_user_model() @@ -33,3 +34,62 @@ def clean_username(self): class PluralPasswordForm(forms.Form): password = forms.CharField(widget=forms.PasswordInput) + +#User Interest form for register page in the home +# codershq/users/forms.py + +from django import forms +from codershq.users.models import UserInterest + +class UserInterestForm(forms.ModelForm): + class Meta: + model = UserInterest + exclude = ['user'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # Apply Bootstrap-like styling + for field in self.fields.values(): + field.widget.attrs.update({'class': 'form-check-input'}) + + def get_grouped_fields(self): + """Return fields organized by question groups.""" + return [ + { + "title": "1️⃣ What are you interested in?", + "fields": [ + ("learn", "HQ Learn"), + ("assessment", "HQ Assessment"), + ("meetups", "HQ Meetups"), + ("challenges", "HQ Challenges"), + ("hackathons", "HQ Hackathons"), + ("conferences", "HQ Conferences"), + ("get_inspired", "HQ Get Inspired"), + ("internship", "HQ Internship"), + ], + }, + { + "title": "2️⃣ Networking", + "fields": [ + ("open_source", "Work collaboratively on open-source projects"), + ("jobs", "Job Opportunities"), + ("golden_visa", "Golden Visa Application"), + ("host_hackathon", "Request to Conduct Hackathon"), + ("workstation_access", "Request access to a workstation in the Coders HQ"), + ], + }, + { + "title": "3️⃣ Pick Your Interests", + "fields": [ + ("web_dev", "Web Development"), + ("data_science", "Data Science"), + ("app_dev", "App Development"), + ("cloud", "Cloud Computing"), + ("devops", "DevOps"), + ("blockchain", "Blockchain Technologies"), + ("cybersecurity", "Cybersecurity"), + ("embedded_systems", "Embedded Systems"), + ], + }, + ] diff --git a/codershq/users/migrations/0005_assessment.py b/codershq/users/migrations/0005_assessment.py new file mode 100644 index 00000000..514e5371 --- /dev/null +++ b/codershq/users/migrations/0005_assessment.py @@ -0,0 +1,37 @@ +# Generated by Django 3.2.11 on 2025-10-17 01:04 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0004_auto_20220906_1612'), + ] + + operations = [ + migrations.CreateModel( + name='Assessment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('gender', models.CharField(max_length=20)), + ('nationality', models.CharField(max_length=100)), + ('country_residence', models.CharField(max_length=100)), + ('mobile_number', models.CharField(blank=True, max_length=20)), + ('seeking_employment', models.BooleanField(default=False)), + ('currently_employed', models.BooleanField(default=False)), + ('employer', models.CharField(blank=True, max_length=255)), + ('years_of_experience', models.IntegerField(default=0)), + ('work_preference', models.CharField(blank=True, max_length=20)), + ('linkedin_account', models.URLField(blank=True)), + ('personal_site', models.URLField(blank=True)), + ('favorite_language', models.CharField(blank=True, max_length=100)), + ('about_you', models.TextField(blank=True)), + ('proud_project', models.TextField(blank=True)), + ('submitted_at', models.DateTimeField(auto_now_add=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/codershq/users/migrations/0006_userinterest.py b/codershq/users/migrations/0006_userinterest.py new file mode 100644 index 00000000..c93709bb --- /dev/null +++ b/codershq/users/migrations/0006_userinterest.py @@ -0,0 +1,41 @@ +# Generated by Django 3.2.11 on 2025-10-20 19:24 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0005_assessment'), + ] + + operations = [ + migrations.CreateModel( + name='UserInterest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('learn', models.BooleanField(default=False, verbose_name='HQ Learn')), + ('meetups', models.BooleanField(default=False, verbose_name='HQ Meetups')), + ('hackathons', models.BooleanField(default=False, verbose_name='HQ Hackathons')), + ('get_inspired', models.BooleanField(default=False, verbose_name='HQ Get Inspired')), + ('networking', models.BooleanField(default=False, verbose_name='Networking')), + ('open_source', models.BooleanField(default=False, verbose_name='Open-source Collaboration')), + ('golden_visa', models.BooleanField(default=False, verbose_name='Golden Visa Application')), + ('workstation_access', models.BooleanField(default=False, verbose_name='Request CHQ Workstation')), + ('assessment', models.BooleanField(default=False, verbose_name='HQ Assessment')), + ('challenges', models.BooleanField(default=False, verbose_name='HQ Challenges')), + ('conferences', models.BooleanField(default=False, verbose_name='HQ Conferences')), + ('internship', models.BooleanField(default=False, verbose_name='Internships')), + ('jobs', models.BooleanField(default=False, verbose_name='Job Opportunities')), + ('host_hackathon', models.BooleanField(default=False, verbose_name='Request to Conduct Hackathon')), + ('web_dev', models.BooleanField(default=False, verbose_name='Web Development')), + ('data_science', models.BooleanField(default=False, verbose_name='Data Science')), + ('cloud', models.BooleanField(default=False, verbose_name='Cloud Computing')), + ('devops', models.BooleanField(default=False, verbose_name='DevOps')), + ('blockchain', models.BooleanField(default=False, verbose_name='Blockchain Technologies')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='interests', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/codershq/users/migrations/0007_auto_20251023_1330.py b/codershq/users/migrations/0007_auto_20251023_1330.py new file mode 100644 index 00000000..e91a34ca --- /dev/null +++ b/codershq/users/migrations/0007_auto_20251023_1330.py @@ -0,0 +1,42 @@ +# Generated by Django 3.2.11 on 2025-10-23 09:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0006_userinterest'), + ] + + operations = [ + migrations.RemoveField( + model_name='userinterest', + name='networking', + ), + migrations.AddField( + model_name='userinterest', + name='app_dev', + field=models.BooleanField(default=False, verbose_name='App Development'), + ), + migrations.AddField( + model_name='userinterest', + name='cybersecurity', + field=models.BooleanField(default=False, verbose_name='Cybersecurity'), + ), + migrations.AddField( + model_name='userinterest', + name='embedded_systems', + field=models.BooleanField(default=False, verbose_name='Embedded Systems'), + ), + migrations.AlterField( + model_name='userinterest', + name='internship', + field=models.BooleanField(default=False, verbose_name='HQ Internships'), + ), + migrations.AlterField( + model_name='userinterest', + name='open_source', + field=models.BooleanField(default=False, verbose_name='Work collaboratively on open-source projects'), + ), + ] diff --git a/codershq/users/models.py b/codershq/users/models.py index 6d2b73d7..631b91ac 100644 --- a/codershq/users/models.py +++ b/codershq/users/models.py @@ -2,7 +2,7 @@ from django.db import models from django.urls import reverse from django.utils.translation import gettext_lazy as _ - +from django.conf import settings #importing setting from codershq.users.validators import validate_github_profile @@ -110,3 +110,67 @@ def create_pluralSightEmail(sender, instance, created, **kwargs): User.objects.filter(pk=instance.id).update(pluralSightEmail=str(instance.id)+"@codershq.ae") User.objects.filter(pk=instance.id).update(pluralSightFirstName=str(instance.id)) User.objects.filter(pk=instance.id).update(pluralSightLastName="codershq") +# adding assesment module + +class Assessment(models.Model): + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + + gender = models.CharField(max_length=20) + nationality = models.CharField(max_length=100) + country_residence = models.CharField(max_length=100) + mobile_number = models.CharField(max_length=20, blank=True) + seeking_employment = models.BooleanField(default=False) + currently_employed = models.BooleanField(default=False) + employer = models.CharField(max_length=255, blank=True) + years_of_experience = models.IntegerField(default=0) + work_preference = models.CharField(max_length=20, blank=True) + + linkedin_account = models.URLField(blank=True) + personal_site = models.URLField(blank=True) + favorite_language = models.CharField(max_length=100, blank=True) + about_you = models.TextField(blank=True) + proud_project = models.TextField(blank=True) + + submitted_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"Assessment by {self.user.username}" + +#adding register form model + +# codershq/users/models.py + +class UserInterest(models.Model): + user = models.OneToOneField( + settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="interests" + ) + + # 1️⃣ HQ Interests + learn = models.BooleanField(_("HQ Learn"), default=False) + assessment = models.BooleanField(_("HQ Assessment"), default=False) + meetups = models.BooleanField(_("HQ Meetups"), default=False) + challenges = models.BooleanField(_("HQ Challenges"), default=False) + hackathons = models.BooleanField(_("HQ Hackathons"), default=False) + conferences = models.BooleanField(_("HQ Conferences"), default=False) + get_inspired = models.BooleanField(_("HQ Get Inspired"), default=False) + internship = models.BooleanField(_("HQ Internships"), default=False) + + # 2️⃣ Networking + open_source = models.BooleanField(_("Work collaboratively on open-source projects"), default=False) + jobs = models.BooleanField(_("Job Opportunities"), default=False) + golden_visa = models.BooleanField(_("Golden Visa Application"), default=False) + host_hackathon = models.BooleanField(_("Request to Conduct Hackathon"), default=False) + workstation_access = models.BooleanField(_("Request CHQ Workstation"), default=False) + + # 3️⃣ Pick Your Interests + web_dev = models.BooleanField(_("Web Development"), default=False) + data_science = models.BooleanField(_("Data Science"), default=False) + app_dev = models.BooleanField(_("App Development"), default=False) + cloud = models.BooleanField(_("Cloud Computing"), default=False) + devops = models.BooleanField(_("DevOps"), default=False) + blockchain = models.BooleanField(_("Blockchain Technologies"), default=False) + cybersecurity = models.BooleanField(_("Cybersecurity"), default=False) + embedded_systems = models.BooleanField(_("Embedded Systems"), default=False) + + def __str__(self): + return f"Interests of {self.user.username}" diff --git a/codershq/users/templatetags/form_extras.py b/codershq/users/templatetags/form_extras.py new file mode 100644 index 00000000..e4038a7d --- /dev/null +++ b/codershq/users/templatetags/form_extras.py @@ -0,0 +1,8 @@ +from django import template + +register = template.Library() + +@register.filter +def get_field(form, field_name): + """Return form field by variable name.""" + return form[field_name] diff --git a/config/settings/local.py b/config/settings/local.py index 230e359f..981f5995 100644 --- a/config/settings/local.py +++ b/config/settings/local.py @@ -1,5 +1,24 @@ from .base import * # noqa from .base import env +#adding static +from pathlib import Path + +# BASE_DIR points to the project root, not config +BASE_DIR = Path(__file__).resolve().parent.parent.parent # project root + +# App-level static files +STATICFILES_DIRS = [ + BASE_DIR / "codershq" / "static", # points to codershq/static +] + +# Where collectstatic gathers files +STATIC_ROOT = BASE_DIR / "staticfiles" + +STATIC_URL = "/static/" + +# Media files +MEDIA_URL = "/media/" +MEDIA_ROOT = BASE_DIR / "media" # GENERAL # ------------------------------------------------------------------------------ diff --git a/config/urls.py b/config/urls.py index 9958d864..4bf4f47d 100644 --- a/config/urls.py +++ b/config/urls.py @@ -93,3 +93,10 @@ import debug_toolbar urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +from django.conf import settings +from django.conf.urls.static import static + +if settings.DEBUG: + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATICFILES_DIRS[0]) + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/local.yml b/local.yml index c6517c64..2c8b56c6 100644 --- a/local.yml +++ b/local.yml @@ -1,11 +1,12 @@ -version: '3' +# 🚫 Remove this: version: '3' volumes: local_postgres_data: {} local_postgres_data_backups: {} + static_volume: {} # ✅ Define this here services: - django: &django + django: build: context: . dockerfile: ./compose/local/django/Dockerfile @@ -17,6 +18,7 @@ services: - mailhog volumes: - .:/app:z + - static_volume:/app/staticfiles:z # ✅ Now correctly defined env_file: - ./.envs/.local/.django - ./.envs/.local/.postgres @@ -37,6 +39,17 @@ services: env_file: - ./.envs/.local/.postgres + mailhog: + image: mailhog/mailhog:v1.0.0 + container_name: mailhog + platform: linux/amd64 + ports: + - "8025:8025" + + redis: + image: redis:6 + container_name: redis + # docs: # container_name: docs # image: peaceiris/mdbook:v0.4.12 # Minimum image @@ -58,16 +71,7 @@ services: # - '0.0.0.0' - mailhog: - image: mailhog/mailhog:v1.0.0 - container_name: mailhog - platform: linux/amd64 - ports: - - "8025:8025" - - redis: - image: redis:6 - container_name: redis + # celeryworker: # <<: *django