-
-
Notifications
You must be signed in to change notification settings - Fork 254
Created Module and program pages #1717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
b6721b6
e9ac12d
b58802f
abf873b
79b6268
eb8f076
d6231c0
fbb82ea
8d571fc
468f0b8
a3c5d3b
dbed9b9
be106ca
ca3d122
ad1d76f
779df27
fb951f6
93236e4
c285a54
d2f0864
a98cd10
471d502
d0e8c7a
c96ed0b
3c1a25a
99474f3
028e6b9
53035d1
668b0ea
8844c2d
fe3ff9e
0b09822
454cd66
94cceed
4d56bcf
1579788
0468fcf
d5c4c91
3a1ee00
8d5e9fd
3cbb44c
32962c9
d1d89ab
a67a3fb
aa42c75
45fe1e0
7596754
d806214
8ba10b8
61b3725
30ff8e7
b518fc9
8eb6522
81b48aa
478d3cf
4ddf608
8b4e085
cb8665a
2e8fc2a
7197275
63ecb63
eb24e0b
4b7d5dc
8e7cb8f
b3f51ec
5689e93
b98893f
f1d3b24
27839f8
a27a4d6
ee84b4a
d2ef0ce
06bb530
80a83c0
29afecd
04e060b
0405292
f446ecf
3e4c9e4
75ae1ba
865dbac
9e28465
a9a734c
2f5e88d
3e51bec
1b6f6f4
95f824b
7fe07d4
e3b1c5b
14f5519
df539bc
9674fb0
c522b1c
f66ddde
376ccdb
dc97d9a
dd6f087
fb1f7e8
e4fa7a4
87fbdd2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| """Core Mentorship mutations.""" | ||
|
|
||
| from .module import ModuleMutation | ||
| from .program import ProgramMutation | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| """Mentorship Module GraphQL Mutations.""" | ||
|
|
||
| import strawberry | ||
|
|
||
| from apps.common.utils import slugify | ||
| from apps.github.models import User as GithubUser | ||
| from apps.mentorship.graphql.nodes.modules import ( | ||
| CreateModuleInput, | ||
| ModuleNode, | ||
| UpdateModuleInput, | ||
| ) | ||
| from apps.mentorship.models import Mentor, Module | ||
| from apps.mentorship.models.program import Program | ||
| from apps.mentorship.utils.user import get_authenticated_user | ||
| from apps.owasp.models import Project | ||
|
|
||
|
|
||
| @strawberry.type | ||
| class ModuleMutation: | ||
| """GraphQL mutations related to module.""" | ||
|
|
||
| @strawberry.mutation | ||
| def create_module(self, info: strawberry.Info, input_data: CreateModuleInput) -> ModuleNode: | ||
| """Create a new mentorship module if the user is a admin.""" | ||
| request = info.context.request | ||
| user = get_authenticated_user(request) | ||
| try: | ||
| program = Program.objects.get(key=input_data.program_key) | ||
| except Program.DoesNotExist as err: | ||
| raise Exception("Program not found") from err | ||
|
|
||
| try: | ||
| project = Project.objects.get(id=input_data.project_id) | ||
| except Project.DoesNotExist as err: | ||
| raise Exception("Project not found") from err | ||
|
|
||
| try: | ||
| admin = Mentor.objects.get(nest_user=user) | ||
| except Mentor.DoesNotExist as err: | ||
| raise Exception("Only mentors can create modules") from err | ||
|
|
||
| if admin not in program.admins.all(): | ||
| raise Exception("You must be an admin of this program to create a module") | ||
|
|
||
| if ( | ||
| input_data.ended_at is not None | ||
| and input_data.started_at is not None | ||
| and input_data.ended_at <= input_data.started_at | ||
| ): | ||
| raise Exception("End date must be after start date") | ||
Rajgupta36 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| module = Module.objects.create( | ||
| name=input_data.name, | ||
| key=slugify(input_data.name), | ||
| description=input_data.description or "", | ||
|
||
| experience_level=input_data.experience_level.value, | ||
| started_at=input_data.started_at or program.started_at, | ||
| ended_at=input_data.ended_at or program.ended_at, | ||
| domains=input_data.domains, | ||
| tags=input_data.tags, | ||
| program=program, | ||
| project=project, | ||
| ) | ||
|
|
||
| resolved_mentors = [admin] | ||
| for login in input_data.mentor_logins or []: | ||
| try: | ||
| github_user = GithubUser.objects.get(login=login) | ||
| except GithubUser.DoesNotExist as err: | ||
| raise Exception("GitHub username not found.") from err | ||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| mentor_obj, _ = Mentor.objects.get_or_create(github_user=github_user) | ||
| resolved_mentors.append(mentor_obj) | ||
|
|
||
| module.mentors.set(resolved_mentors) | ||
|
|
||
| return ModuleNode( | ||
| id=module.id, | ||
| key=module.key, | ||
| name=module.name, | ||
| description=module.description, | ||
| domains=module.domains, | ||
| ended_at=module.ended_at, | ||
| experience_level=module.experience_level, | ||
| mentors=list(module.mentors.all()), | ||
| program=module.program, | ||
| project_id=module.project.id if module.project else None, | ||
| started_at=module.started_at, | ||
| tags=module.tags, | ||
| ) | ||
Rajgupta36 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| @strawberry.mutation | ||
| def update_module(self, info: strawberry.Info, input_data: UpdateModuleInput) -> ModuleNode: | ||
| """Update an existing mentorship module. Only admins can update.""" | ||
| request = info.context.request | ||
| user = get_authenticated_user(request) | ||
|
|
||
| try: | ||
| module = Module.objects.select_related("program").get(key=input_data.key) | ||
| except Module.DoesNotExist as err: | ||
| raise Exception("Module not found") from err | ||
|
|
||
| try: | ||
| admin = Mentor.objects.get(nest_user=user) | ||
| except Mentor.DoesNotExist as err: | ||
| raise Exception("Only mentors can edit modules") from err | ||
|
|
||
| if admin not in module.program.admins.all(): | ||
| raise Exception("You must be an admin of the module's program to edit it") | ||
|
|
||
| if ( | ||
| input_data.ended_at is not None | ||
| and input_data.started_at is not None | ||
| and input_data.ended_at <= input_data.started_at | ||
| ): | ||
| raise Exception("End date must be after start date") | ||
|
|
||
| if input_data.experience_level: | ||
| module.experience_level = input_data.experience_level.value | ||
|
|
||
| if input_data.project_id: | ||
| try: | ||
| project = Project.objects.get(id=input_data.project_id) | ||
| module.project = project | ||
| except Project.DoesNotExist as err: | ||
| raise Exception("Project not found") from err | ||
|
|
||
| update_fields = { | ||
| "key": slugify(input_data.name), | ||
| "name": input_data.name, | ||
| "description": input_data.description, | ||
| "started_at": input_data.started_at, | ||
| "ended_at": input_data.ended_at, | ||
| "domains": input_data.domains, | ||
| "tags": input_data.tags, | ||
| } | ||
|
|
||
| for field, value in update_fields.items(): | ||
| if value is not None: | ||
| setattr(module, field, value) | ||
|
|
||
| module.save() | ||
|
|
||
| if input_data.mentor_logins is not None: | ||
| resolved_mentors = [] | ||
| for login in input_data.mentor_logins: | ||
| try: | ||
| github_user = GithubUser.objects.get(login__iexact=login.lower()) | ||
| except GithubUser.DoesNotExist as err: | ||
| raise Exception("GitHub user not found") from err | ||
|
|
||
| mentor_obj, _ = Mentor.objects.get_or_create(github_user=github_user) | ||
| resolved_mentors.append(mentor_obj) | ||
|
|
||
| module.mentors.set(resolved_mentors) | ||
|
|
||
| return ModuleNode( | ||
| id=module.id, | ||
| key=module.key, | ||
| name=module.name, | ||
| description=module.description, | ||
| domains=module.domains, | ||
| ended_at=module.ended_at, | ||
| experience_level=module.experience_level, | ||
| mentors=list(module.mentors.all()), | ||
| program=module.program, | ||
| project_id=module.project.id if module.project else None, | ||
| started_at=module.started_at, | ||
| tags=module.tags, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,151 @@ | ||
| """Mentorship Program GraphQL Mutations.""" | ||
|
|
||
| import strawberry | ||
|
|
||
| from apps.common.utils import slugify | ||
| from apps.github.models import User as GithubUser | ||
| from apps.mentorship.graphql.nodes.program import ( | ||
| CreateProgramInput, | ||
| ProgramNode, | ||
| UpdateProgramInput, | ||
| ) | ||
| from apps.mentorship.models import Mentor, Program | ||
| from apps.mentorship.utils.user import get_authenticated_user | ||
|
|
||
|
|
||
| @strawberry.type | ||
| class ProgramMutation: | ||
| """GraphQL mutations related to program.""" | ||
|
|
||
| @strawberry.mutation | ||
| def create_program(self, info: strawberry.Info, input_data: CreateProgramInput) -> ProgramNode: | ||
| """Create a new mentorship program if the user is a mentor.""" | ||
| request = info.context.request | ||
| user = get_authenticated_user(request) | ||
|
|
||
| if user.role != "mentor": | ||
| raise Exception("You must be a mentor to create a program") | ||
|
|
||
| if input_data.ended_at <= input_data.started_at: | ||
| raise Exception("End date must be after start date") | ||
|
|
||
| mentor, _ = Mentor.objects.get_or_create( | ||
| nest_user=user, defaults={"github_user": user.github_user} | ||
| ) | ||
|
|
||
| program = Program.objects.create( | ||
| name=input_data.name, | ||
| key=slugify(input_data.name), | ||
| description=input_data.description, | ||
| experience_levels=[lvl.value for lvl in input_data.experience_levels], | ||
| mentees_limit=input_data.mentees_limit, | ||
| started_at=input_data.started_at, | ||
| ended_at=input_data.ended_at, | ||
| domains=input_data.domains, | ||
| tags=input_data.tags, | ||
| status=input_data.status.value, | ||
| ) | ||
|
|
||
| resolved_mentors = {mentor} | ||
|
|
||
| for login in input_data.admin_logins: | ||
| try: | ||
| github_user = GithubUser.objects.get(login__iexact=login.lower()) | ||
| except GithubUser.DoesNotExist as err: | ||
| raise Exception("GitHub user with username not found.") from err | ||
| m, _ = Mentor.objects.get_or_create(github_user=github_user) | ||
| resolved_mentors.add(m) | ||
|
|
||
| program.admins.set(resolved_mentors) | ||
|
|
||
| return ProgramNode( | ||
| id=program.id, | ||
| key=program.key, | ||
| name=program.name, | ||
| description=program.description, | ||
| experience_levels=program.experience_levels, | ||
| mentees_limit=program.mentees_limit, | ||
| started_at=program.started_at, | ||
| ended_at=program.ended_at, | ||
| domains=program.domains, | ||
| tags=program.tags, | ||
| status=program.status, | ||
| admins=list(program.admins.all()), | ||
| ) | ||
Rajgupta36 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| @strawberry.mutation | ||
| def update_program(self, info: strawberry.Info, input_data: UpdateProgramInput) -> ProgramNode: | ||
| """Update an existing mentorship program. Only admins can update.""" | ||
| request = info.context.request | ||
| user = get_authenticated_user(request) | ||
|
|
||
| try: | ||
| program = Program.objects.get(key=input_data.key) | ||
| except Program.DoesNotExist as err: | ||
| raise Exception("Program not found") from err | ||
|
|
||
| try: | ||
| admin = Mentor.objects.get(nest_user=user) | ||
| except Mentor.DoesNotExist as err: | ||
| raise Exception("You must be a mentor to update a program") from err | ||
|
|
||
| if admin not in program.admins.all(): | ||
| raise Exception("You must be an admin of this program to update it") | ||
|
|
||
| if ( | ||
| input_data.ended_at is not None | ||
| and input_data.started_at is not None | ||
| and input_data.ended_at <= input_data.started_at | ||
| ): | ||
| raise Exception("End date must be after start date") | ||
|
|
||
| simple_fields = { | ||
| "key": slugify(input_data.name), | ||
| "name": input_data.name, | ||
| "description": input_data.description, | ||
| "mentees_limit": input_data.mentees_limit, | ||
| "started_at": input_data.started_at, | ||
| "ended_at": input_data.ended_at, | ||
| "domains": input_data.domains, | ||
| "tags": input_data.tags, | ||
| } | ||
|
|
||
| for field, value in simple_fields.items(): | ||
| if value is not None: | ||
| setattr(program, field, value) | ||
Rajgupta36 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if input_data.experience_levels is not None: | ||
| program.experience_levels = [lvl.value for lvl in input_data.experience_levels] | ||
|
|
||
| if input_data.status is not None: | ||
| program.status = input_data.status.value | ||
|
|
||
| program.save() | ||
|
|
||
| if input_data.admin_logins is not None: | ||
| resolved_mentors = [] | ||
| for login in input_data.admin_logins: | ||
| try: | ||
| github_user = GithubUser.objects.get(login__iexact=login.lower()) | ||
| except GithubUser.DoesNotExist as err: | ||
| raise Exception("GitHub user not found.") from err | ||
|
|
||
| mentor, _ = Mentor.objects.get_or_create(github_user=github_user) | ||
| resolved_mentors.append(mentor) | ||
|
|
||
| program.admins.set(resolved_mentors) | ||
|
|
||
| return ProgramNode( | ||
| id=program.id, | ||
| key=program.key, | ||
| name=program.name, | ||
| description=program.description, | ||
| experience_levels=program.experience_levels, | ||
| mentees_limit=program.mentees_limit, | ||
| started_at=program.started_at, | ||
| ended_at=program.ended_at, | ||
| domains=program.domains, | ||
| tags=program.tags, | ||
| status=program.status, | ||
| admins=list(program.admins.all()), | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # This file marks the directory as a Python package. |
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| """GraphQL enum for Mentorship App.""" | ||
|
|
||
| import enum | ||
|
|
||
| import strawberry | ||
|
|
||
|
|
||
| @strawberry.enum | ||
| class ExperienceLevelEnum(enum.Enum): | ||
| """experience level enum.""" | ||
|
|
||
| BEGINNER = "beginner" | ||
| INTERMEDIATE = "intermediate" | ||
| ADVANCED = "advanced" | ||
| EXPERT = "expert" | ||
|
|
||
|
|
||
| @strawberry.enum | ||
| class ProgramStatusEnum(enum.Enum): | ||
| """program status enum.""" | ||
|
|
||
| DRAFT = "draft" | ||
| PUBLISHED = "published" | ||
| COMPLETED = "completed" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| """GraphQL node for Mentor model.""" | ||
|
|
||
| import strawberry | ||
|
|
||
|
|
||
| @strawberry.type | ||
| class MentorNode: | ||
| """A GraphQL node representing a mentorship mentor.""" | ||
|
|
||
| id: strawberry.ID | ||
Rajgupta36 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| @strawberry.field | ||
| def avatar_url(self) -> str: | ||
| """Get the GitHub avatar url of the mentor.""" | ||
| if not self.github_user: | ||
| return "" | ||
| return self.github_user.avatar_url | ||
|
|
||
| @strawberry.field | ||
| def name(self) -> str: | ||
| """Get the GitHub name of the mentor.""" | ||
| if not self.github_user: | ||
| return "" | ||
| return self.github_user.name | ||
|
|
||
| @strawberry.field | ||
| def login(self) -> str: | ||
| """Get the GitHub login of the mentor.""" | ||
| if not self.github_user: | ||
| return "" | ||
| return self.github_user.login | ||
|
||
Uh oh!
There was an error while loading. Please reload this page.