diff --git a/main/admin.py b/main/admin.py index fc76b9e4..57e7fe2c 100644 --- a/main/admin.py +++ b/main/admin.py @@ -23,6 +23,8 @@ Provider, Skill, SkillLevel, + Team, + TeamMembership, ToolLanguageMethodology, User, UserSkill, @@ -210,3 +212,13 @@ def has_delete_permission( ) -> bool: """Do not allow deleting users from this view.""" return False + + +@admin.register(Team) +class TeamAdmin(admin.ModelAdmin[Team]): + """Admin class for the Team model.""" + + +@admin.register(TeamMembership) +class TeamMembershipAdmin(admin.ModelAdmin[TeamMembership]): + """Admin class for the TeamMembership model.""" diff --git a/main/forms.py b/main/forms.py index 22488df4..37f0b409 100644 --- a/main/forms.py +++ b/main/forms.py @@ -16,6 +16,8 @@ RegistrationFormUniqueEmail, ) +from main import models + from .models import Skill, SkillLevel, UserSkill if TYPE_CHECKING: # pragma: no cover @@ -267,3 +269,13 @@ def save(self, user: "UserType") -> tuple[list[UserSkill], list[UserSkill]]: created_skills.append(user_skill) return created_skills, updated_skills + + +class CreateTeamForm(forms.Form): + """Form for creating a new team.""" + + class Meta: + """Meta options for CreateTeamForm.""" + + model = models.Team + fields = "__all__" diff --git a/main/migrations/0029_alter_userproxy_options.py b/main/migrations/0029_alter_userproxy_options.py new file mode 100644 index 00000000..e8c749ce --- /dev/null +++ b/main/migrations/0029_alter_userproxy_options.py @@ -0,0 +1,17 @@ +# Generated by Django 6.0.3 on 2026-04-30 11:04 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0028_alter_toollanguagemethodology_options_and_more'), + ] + + operations = [ + migrations.AlterModelOptions( + name='userproxy', + options={'verbose_name': 'User skills profile'}, + ), + ] diff --git a/main/migrations/0030_team_teammembership.py b/main/migrations/0030_team_teammembership.py new file mode 100644 index 00000000..01cc77b7 --- /dev/null +++ b/main/migrations/0030_team_teammembership.py @@ -0,0 +1,36 @@ +# Generated by Django 6.0.3 on 2026-04-30 11:08 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0029_alter_userproxy_options'), + ] + + operations = [ + migrations.CreateModel( + name='Team', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200, unique=True)), + ('description', models.TextField()), + ('slug', models.SlugField(max_length=200, unique=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TeamMembership', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('manager', models.BooleanField(blank=True, default=False)), + ('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.team')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/main/models/__init__.py b/main/models/__init__.py index 2d6dc0a2..0b00643d 100644 --- a/main/models/__init__.py +++ b/main/models/__init__.py @@ -1,4 +1,5 @@ """Init in models.""" from .framework_models import * # noqa: F403 +from .team_models import * # noqa: F403 from .user_models import * # noqa: F403 diff --git a/main/models/team_models.py b/main/models/team_models.py new file mode 100644 index 00000000..67e80114 --- /dev/null +++ b/main/models/team_models.py @@ -0,0 +1,14 @@ +from django.conf import settings +from django.db import models + +from .framework_models import SluggedModel + + +class Team(SluggedModel): + pass + + +class TeamMembership(models.Model): + user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) + team = models.ForeignKey(Team, on_delete=models.CASCADE) + manager = models.BooleanField(blank=True, default=False) diff --git a/main/models/user_models.py b/main/models/user_models.py index 1b23295e..9fe20054 100644 --- a/main/models/user_models.py +++ b/main/models/user_models.py @@ -30,3 +30,17 @@ class Meta: constraints = ( models.UniqueConstraint(fields=["user", "skill"], name="unique_user_skill"), ) + + +class Team(models.Model): + """Model for representing a team of users working together.""" + + name = models.CharField(max_length=255) + manager = models.ForeignKey( + settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="managed_teams" + ) + members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="teams") + + def __str__(self) -> str: + """Return the string representation of the team.""" + return self.name diff --git a/main/templates/main/pages/create-team.html b/main/templates/main/pages/create-team.html new file mode 100644 index 00000000..463d4f8e --- /dev/null +++ b/main/templates/main/pages/create-team.html @@ -0,0 +1,14 @@ +{% extends "main/base.account.html" %} +{% load crispy_forms_tags %} +{% block content %} +
+

+ Create Team +

+
+ {% csrf_token %} + {{ form|crispy }} + +
+
+{% endblock content %} diff --git a/main/templates/main/pages/my-teams.html b/main/templates/main/pages/my-teams.html new file mode 100644 index 00000000..7b600f56 --- /dev/null +++ b/main/templates/main/pages/my-teams.html @@ -0,0 +1,66 @@ +{% extends "main/base.page.html" %} +{% load static %} +{% block title %} + DIRECT Framework - My Teams +{% endblock title %} +{% block breadcrumb_items %} + + +{% endblock breadcrumb_items %} +{% block content %} +
+
+
+

My Teams

+ Create Team +

+ This page presents the teams you are in in the Digital Research + Competencies Framework. +

+ + + + + + + + + + + {% for team in teams %} + + + + + + + {% endfor %} + +
Team NameDescriptionManagerMembers
+ {{ team.name }} + {{ team.description }}{{ team.manager }} +
    + {% for member in team.members %}
  • {{ member }}
  • {% endfor %} +
+
+
+ +
+
+{% endblock content %} diff --git a/main/templates/main/snippets/navbar.html b/main/templates/main/snippets/navbar.html index ba313b63..1054170b 100644 --- a/main/templates/main/snippets/navbar.html +++ b/main/templates/main/snippets/navbar.html @@ -38,6 +38,10 @@