Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions backend/apps/mentorship/api/internal/queries/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
import logging

import strawberry
from django.db.models import Q
from django.db.models import Prefetch, Q
from django.db.models.functions import Lower

from apps.mentorship.api.internal.graphql_errors import (
AuthenticationRequiredError,
ManagementProgramAccessDeniedError,
)
from apps.mentorship.api.internal.nodes.module import ModuleNode
from apps.mentorship.models import Module, Program
from apps.mentorship.models import Mentor, Module, Program

logger = logging.getLogger(__name__)

Expand All @@ -35,7 +36,14 @@ def get_program_modules(self, info: strawberry.Info, program_key: str) -> list[M
return (
Module.objects.filter(program=program)
.select_related("program", "project")
.prefetch_related("mentors__github_user")
.prefetch_related(
Prefetch(
"mentors",
queryset=Mentor.objects.select_related("github_user").order_by(
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Lower("github_user__login")
),
)
)
.order_by("order", "started_at")
)

Expand Down Expand Up @@ -66,7 +74,14 @@ def get_management_program_modules(

return (
modules.select_related("program", "project")
.prefetch_related("mentors__github_user")
.prefetch_related(
Prefetch(
"mentors",
queryset=Mentor.objects.select_related("github_user").order_by(
Lower("github_user__login")
),
)
)
.distinct()
.order_by("order", "started_at")
)
Expand All @@ -77,7 +92,14 @@ def get_project_modules(self, project_key: str) -> list[ModuleNode]:
return (
Module.objects.filter(project__key=project_key)
.select_related("program", "project")
.prefetch_related("mentors__github_user")
.prefetch_related(
Prefetch(
"mentors",
queryset=Mentor.objects.select_related("github_user").order_by(
Lower("github_user__login")
),
)
)
.order_by("order", "started_at")
)

Expand All @@ -89,7 +111,14 @@ def get_module(
try:
module = (
Module.objects.select_related("program", "project")
.prefetch_related("mentors__github_user")
.prefetch_related(
Prefetch(
"mentors",
queryset=Mentor.objects.select_related("github_user").order_by(
Lower("github_user__login")
),
)
)
.get(key=module_key, program__key=program_key)
)
except Module.DoesNotExist:
Expand All @@ -116,7 +145,14 @@ def get_management_module(
try:
module = (
Module.objects.select_related("program", "project")
.prefetch_related("mentors__github_user")
.prefetch_related(
Prefetch(
"mentors",
queryset=Mentor.objects.select_related("github_user").order_by(
Lower("github_user__login")
),
)
)
.get(key=module_key, program__key=program_key)
)
except Module.DoesNotExist:
Expand Down
26 changes: 14 additions & 12 deletions frontend/__tests__/unit/components/ModuleForm.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -325,12 +325,21 @@ describe('ModuleForm', () => {
expect(screen.getByTestId('text-input-module-labels')).toBeInTheDocument()
})

it('renders mentor logins field only when isEdit is true (line 312)', () => {
renderModuleForm({ isEdit: false })
expect(screen.queryByTestId('text-input-module-mentor-logins')).not.toBeInTheDocument()

renderModuleForm({ isEdit: true })
it('renders and updates mentor logins field', () => {
renderModuleForm()
expect(screen.getByTestId('text-input-module-mentor-logins')).toBeInTheDocument()
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

const input = screen.getByTestId('input-module-mentor-logins')
fireEvent.change(input, { target: { value: 'johndoe, Kateryna' } })
expect(mockSetFormData).toHaveBeenCalled()
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const setterFn = mockSetFormData.mock.calls[mockSetFormData.mock.calls.length - 1][0]
const result = setterFn(defaultFormData)
expect(result).toEqual(
expect.objectContaining({
mentorLogins: 'johndoe, Kateryna',
})
)
})
})

Expand Down Expand Up @@ -375,13 +384,6 @@ describe('ModuleForm', () => {
expect(mockSetFormData).toHaveBeenCalled()
})

it('updates mentor logins field when in edit mode (line 312)', () => {
renderModuleForm({ isEdit: true })
const mentorInput = screen.getByTestId('input-module-mentor-logins')
fireEvent.change(mentorInput, { target: { value: 'johndoe, Kateryna' } })

expect(mockSetFormData).toHaveBeenCalled()
})

it('updates start date field', () => {
renderModuleForm()
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,32 @@ select:disabled,
.chapter-map .leaflet-marker-shadow {
cursor: pointer !important;
}

/* MarkdownWrapper CSS */

.md-wrapper p {
margin: 0 0 16px;
}

.md-wrapper ul {
margin: 16px 0;
padding-left: 24px;
}

.md-wrapper ol {
margin: 16px 0;
padding-left: 24px;
}

.md-wrapper li {
margin-bottom: 8px;
}

.md-wrapper h1,
.md-wrapper h2,
.md-wrapper h3,
.md-wrapper h4,
.md-wrapper h5,
.md-wrapper h6 {
margin: 24px 0 16px;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,6 @@ const EditModulePage = () => {
onSubmit={handleSubmit}
loading={mutationLoading}
submitText="Save"
isEdit
validationErrors={validationErrors}
minDate={
data?.managementProgram?.startedAt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ const CreateModulePage = () => {
setFormData={setFormData}
onSubmit={handleSubmit}
loading={mutationLoading}
isEdit={false}
validationErrors={validationErrors}
minDate={
programData?.managementProgram?.startedAt
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ModuleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ const ModuleItem = ({
<div className="flex items-center justify-between">
<Link
href={`${pathname}/modules/${module.key}`}
className="text-start font-semibold text-gray-600 hover:underline dark:text-gray-300"
className="mr-2 min-w-0 flex-1 text-start font-semibold text-gray-600 hover:underline dark:text-gray-300"
>
<TruncatedText text={module?.name} />
</Link>
Expand Down
20 changes: 8 additions & 12 deletions frontend/src/components/ModuleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ interface ModuleFormProps {
setFormData: React.Dispatch<React.SetStateAction<ModuleFormProps['formData']>>
onSubmit: (e: React.FormEvent) => void
loading: boolean
isEdit?: boolean
title: string
submitText?: string
minDate?: string
Expand All @@ -60,7 +59,6 @@ const ModuleForm = ({
onSubmit,
loading,
title,
isEdit,
submitText = 'Save',
minDate,
maxDate,
Expand Down Expand Up @@ -308,16 +306,14 @@ const ModuleForm = ({
errorMessage={touched.projectId ? errors.projectId : undefined}
/>
</div>
{isEdit && (
<FormTextInput
id="module-mentor-logins"
label="Mentor GitHub Usernames"
placeholder="johndoe, jane-doe"
value={formData.mentorLogins}
onValueChange={(value) => handleInputChange('mentorLogins', value)}
className="w-full min-w-0 lg:col-span-2"
/>
)}
<FormTextInput
id="module-mentor-logins"
label="Mentor GitHub Usernames"
placeholder="johndoe, jane-doe"
value={formData.mentorLogins}
onValueChange={(value) => handleInputChange('mentorLogins', value)}
className="w-full min-w-0 lg:col-span-2"
/>
</div>
</section>

Expand Down