diff --git a/company/templatetags/custom_filters.py b/company/templatetags/custom_filters.py index 31a68a5f8..02386625d 100644 --- a/company/templatetags/custom_filters.py +++ b/company/templatetags/custom_filters.py @@ -7,3 +7,8 @@ def get_item(dictionary, key): """Return the value for `key` in `dictionary`.""" return dictionary.get(key) + + +@register.filter +def before_dot(value): + return str(value).split(".")[0] diff --git a/company/views.py b/company/views.py index 50be80b48..8d1257cfb 100644 --- a/company/views.py +++ b/company/views.py @@ -123,16 +123,12 @@ def post(self, request, *args, **kwargs): return redirect("/accounts/login/") user_domain = get_email_domain(user.email) - company_name = data.get("company_name", "").strip().lower() + company_name = data.get("company_name", "") if user_domain in restricted_domain: messages.error(request, "Login with company email in order to create the company.") return redirect("/") - if user_domain != company_name: - messages.error(request, "Company name doesn't match your email domain.") - return redirect("register_company") - if Company.objects.filter(name=company_name).exists(): messages.error(request, "Company already exists.") return redirect("register_company") @@ -516,7 +512,7 @@ def post(self, request, id, *args, **kwargs): response = requests.get(safe_url, timeout=5) if response.status_code != 200: raise Exception - except requests.exceptions.RequestException: + except requests.exceptions.RequestException as e: messages.error(request, "Domain does not exist.") return redirect("add_domain", id=id) except ValueError: diff --git a/website/api/views.py b/website/api/views.py index acb11b7b1..e0dc2bbff 100644 --- a/website/api/views.py +++ b/website/api/views.py @@ -1,6 +1,7 @@ import json import uuid from datetime import datetime +from urllib.parse import urlparse from django.conf import settings from django.contrib.sites.shortcuts import get_current_site @@ -846,8 +847,26 @@ class TimeLogViewSet(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] def perform_create(self, serializer): + organization_url = self.request.data.get("organization_url") + try: - serializer.save(user=self.request.user) + if organization_url: + parsed_url = urlparse(organization_url) + normalized_url = parsed_url.netloc + parsed_url.path + + # Normalize the URL in the Company model (remove the protocol if present) + try: + organization = Company.objects.get( + Q(url__iexact=normalized_url) + | Q(url__iexact=f"http://{normalized_url}") + | Q(url__iexact=f"https://{normalized_url}") + ) + except Company.DoesNotExist: + raise ParseError(detail="Organization not found for the given URL.") + + # Save the TimeLog with the user and organization (if found, or None) + serializer.save(user=self.request.user, organization=organization) + except ValidationError as e: raise ParseError(detail=str(e)) except Exception as e: diff --git a/website/migrations/0154_timelog_organization.py b/website/migrations/0154_timelog_organization.py new file mode 100644 index 000000000..b297524d4 --- /dev/null +++ b/website/migrations/0154_timelog_organization.py @@ -0,0 +1,24 @@ +# Generated by Django 5.1.3 on 2024-11-21 13:44 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0153_delete_contributorstats"), + ] + + operations = [ + migrations.AddField( + model_name="timelog", + name="organization", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="organization", + to="website.company", + ), + ), + ] diff --git a/website/migrations/0155_alter_company_url.py b/website/migrations/0155_alter_company_url.py new file mode 100644 index 000000000..729f128ca --- /dev/null +++ b/website/migrations/0155_alter_company_url.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1.3 on 2024-11-22 11:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0154_timelog_organization"), + ] + + operations = [ + migrations.AlterField( + model_name="company", + name="url", + field=models.URLField(unique=True), + ), + ] diff --git a/website/migrations/0156_merge_20241124_0329.py b/website/migrations/0156_merge_20241124_0329.py new file mode 100644 index 000000000..b35b04915 --- /dev/null +++ b/website/migrations/0156_merge_20241124_0329.py @@ -0,0 +1,12 @@ +# Generated by Django 5.1.3 on 2024-11-24 03:29 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0154_contributors_to_users_20241123_1836"), + ("website", "0155_alter_company_url"), + ] + + operations = [] diff --git a/website/migrations/0157_merge_20241124_0808.py b/website/migrations/0157_merge_20241124_0808.py new file mode 100644 index 000000000..22a501971 --- /dev/null +++ b/website/migrations/0157_merge_20241124_0808.py @@ -0,0 +1,12 @@ +# Generated by Django 5.1.3 on 2024-11-24 08:08 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0155_merge_20241124_0242"), + ("website", "0156_merge_20241124_0329"), + ] + + operations = [] diff --git a/website/migrations/0158_merge_20241125_0802.py b/website/migrations/0158_merge_20241125_0802.py new file mode 100644 index 000000000..2f811357a --- /dev/null +++ b/website/migrations/0158_merge_20241125_0802.py @@ -0,0 +1,12 @@ +# Generated by Django 5.1.3 on 2024-11-25 08:02 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0156_merge_20241124_0722"), + ("website", "0157_merge_20241124_0808"), + ] + + operations = [] diff --git a/website/models.py b/website/models.py index a32467e17..0c9e58087 100644 --- a/website/models.py +++ b/website/models.py @@ -68,7 +68,7 @@ class Company(models.Model): name = models.CharField(max_length=255) description = models.CharField(max_length=500, null=True, blank=True) logo = models.ImageField(upload_to="company_logos", null=True, blank=True) - url = models.URLField() + url = models.URLField(unique=True) email = models.EmailField(null=True, blank=True) twitter = models.CharField(max_length=30, null=True, blank=True) facebook = models.URLField(null=True, blank=True) @@ -876,6 +876,10 @@ class TimeLog(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="timelogs" ) + # associate organization with sizzle + organization = models.ForeignKey( + Company, on_delete=models.CASCADE, related_name="organization", null=True, blank=True + ) start_time = models.DateTimeField() end_time = models.DateTimeField(null=True, blank=True) duration = models.DurationField(null=True, blank=True) diff --git a/website/serializers.py b/website/serializers.py index a73857674..32042a100 100644 --- a/website/serializers.py +++ b/website/serializers.py @@ -149,7 +149,16 @@ class Meta: class TimeLogSerializer(serializers.ModelSerializer): class Meta: model = TimeLog - fields = ["id", "user", "start_time", "end_time", "duration", "github_issue_url", "created"] + fields = [ + "id", + "user", + "organization", + "start_time", + "end_time", + "duration", + "github_issue_url", + "created", + ] read_only_fields = [ "id", "user", diff --git a/website/templates/sizzle/time_logs.html b/website/templates/sizzle/time_logs.html index e73278d90..50ece086d 100644 --- a/website/templates/sizzle/time_logs.html +++ b/website/templates/sizzle/time_logs.html @@ -1,7 +1,9 @@ {% extends "base.html" %} +{% load custom_filters %} {% load static %} {% block content %} +
+ Organization: + {{ organization_url }} +
Elapsed Time: 00:00:00
@@ -67,6 +93,7 @@