Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
4 changes: 2 additions & 2 deletions app/[locale]/account/profile/__tests__/page.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const mockUserData = {
me: {
givenName: 'John',
surName: 'Doe',
affiliation: { name: 'Test Institution', uri: 'test-uri' },
affiliation: { name: 'Test Institution', uri: 'test-uri', displayName: 'Test Institution' },
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the affiliationName.displayName to the MeQuery for the QuestionPreview so that we could be explicit about which Org added the guidance, therefore I was required to add it to some unit test mocks.

emails: [{ id: '1', email: 'test@example.com', isPrimary: true, isConfirmed: true }],
languageId: 'en',
},
Expand Down Expand Up @@ -222,7 +222,7 @@ describe('ProfilePage', () => {
me: {
givenName: 'John',
surName: 'Doe',
affiliation: { name: '', uri: '' },
affiliation: { name: '', uri: '', displayName: '' },
emails: [{ id: '1', email: 'test@example.com', isPrimary: true, isConfirmed: true }],
languageId: 'en',
},
Expand Down
6 changes: 6 additions & 0 deletions app/[locale]/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Loading from '@/components/Loading';
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this new component just in case, so page loads can fall back to this if it takes longer than 300ms

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. This is a good idea


{/** Next.js only shows this if it takes longer than ~300ms to load */ }
export default function LocaleLoading() {
return <Loading />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"affiliation": {
"id": 1,
"name": "California Digital Library",
"displayName": "California Digital Library",
"searchName": "California Digital Library | cdlib.org | CDL ",
"uri": "https://ror.org/03yrm5c26",
"__typename": "Affiliation"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe("CommentList", () => {
role: UserRole.Admin,
emails: [],
errors: {},
affiliation: { id: 1, name: "Test Org", searchName: "test-org", uri: "https://test.org" }
affiliation: { id: 1, name: "Test Org", searchName: "test-org", uri: "https://test.org", displayName: "Test Org" }
}
},
planOwners: [1, 7], // Current user and admin are plan owners
Expand Down Expand Up @@ -178,7 +178,7 @@ describe("CommentList", () => {
role: UserRole.Admin,
emails: [],
errors: {},
affiliation: { id: 1, name: "Test Org", searchName: "test-org", uri: "https://test.org" }
affiliation: { id: 1, name: "Test Org", searchName: "test-org", uri: "https://test.org", displayName: "Test Org" }
};

const props = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const createMockMeQuery = (overrides = {}) => ({
affiliation: {
id: 1,
name: "Test Organization",
displayName: "Test Organization",
searchName: "test-organization",
uri: "https://test.org"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ describe('useComments', () => {
id: 1,
name: "Test Organization",
searchName: "test-organization",
uri: "https://test.org"
uri: "https://test.org",
displayName: "Test Organization"
},
}
};
Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/template/[templateId]/q/[q_slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ import {
import {
isOptionsType,
getOverrides,
} from './hooks/useEditQuestion';
} from '@/app/hooks/useEditQuestion';
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the useEditQuestion to a shared location since the new Custom Question pages use it too

import styles from './questionEdit.module.scss';

const QuestionEdit = () => {
Expand Down
27 changes: 26 additions & 1 deletion app/[locale]/template/[templateId]/q/new/__tests__/page.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,17 @@ import { useParams, useRouter, useSearchParams } from 'next/navigation';
import { useQueryStep } from '@/app/[locale]/template/[templateId]/q/new/utils';
import QuestionTypeSelectPage from "../page";
import { mockScrollIntoView, mockScrollTo } from "@/__mocks__/common";

import { useMutation, useQuery } from '@apollo/client/react';
expect.extend(toHaveNoViolations);

jest.mock('@apollo/client/react', () => ({
useQuery: jest.fn(),
useMutation: jest.fn(),
}));

const mockUseQuery = jest.mocked(useQuery);
const mockUseMutation = jest.mocked(useMutation);

jest.mock('next/navigation', () => ({
useParams: jest.fn(),
useRouter: jest.fn(),
Expand Down Expand Up @@ -76,6 +84,23 @@ describe("QuestionTypeSelectPage", () => {
} as unknown as ReturnType<typeof useSearchParams>;
});

mockUseMutation.mockImplementation(() => [
jest.fn().mockResolvedValue({ data: {} }),
{ loading: false, error: undefined }
// eslint-disable-next-line @typescript-eslint/no-explicit-any
] as any);

mockUseQuery.mockImplementation(() => ({
data: {
questions: [
{ displayOrder: 1 },
{ displayOrder: 2 },
]
},
loading: false,
error: undefined,
/* eslint-disable @typescript-eslint/no-explicit-any */
}) as any);

});

Expand Down
64 changes: 64 additions & 0 deletions app/[locale]/template/[templateId]/q/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ import {
Text
} from "react-aria-components";


Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page was updated to pass in new props to the shared QuestionAdd, because it is now shared with the Custom Question pages

// GraphQL
import { useMutation, useQuery } from '@apollo/client/react';
import {
AddQuestionDocument,
QuestionsDisplayOrderDocument,
} from '@/generated/graphql';


// Components
import PageHeader from "@/components/PageHeader";
import { ContentContainer, LayoutContainer, } from '@/components/Container';
Expand All @@ -30,6 +39,17 @@ import { QuestionFormatInterface } from '@/app/types';
import styles from './newQuestion.module.scss';
import { getQuestionTypes } from "@/utils/questionTypeHandlers";

const TemplateQuestionBreadcrumbs = ({ templateId, sectionId, Global }: { templateId: string; sectionId: string; Global: (key: string, values?: Record<string, string | number>) => string }) => {
return (
<Breadcrumbs>
<Breadcrumb><Link href={routePath('projects.index')}>{Global('breadcrumbs.home')}</Link></Breadcrumb>
<Breadcrumb><Link href={routePath('template.index', { templateId })}>{Global('breadcrumbs.templates')}</Link></Breadcrumb>
<Breadcrumb><Link href={routePath('template.show', { templateId })}>{Global('breadcrumbs.editTemplate')}</Link></Breadcrumb>
<Breadcrumb><Link href={routePath('template.q.new', { templateId }, { section_id: sectionId, step: 1 })}>{Global('breadcrumbs.selectQuestionType')}</Link></Breadcrumb>
<Breadcrumb>{Global('breadcrumbs.question')}</Breadcrumb>
</Breadcrumbs >
)
}

const QuestionTypeSelectPage: React.FC = () => {
// Get templateId param
Expand Down Expand Up @@ -58,6 +78,37 @@ const QuestionTypeSelectPage: React.FC = () => {
const Global = useTranslations('Global');
const QuestionTypeSelect = useTranslations('QuestionTypeSelectPage');

// Initialize add and update question mutations
const [addQuestionMutation] = useMutation(AddQuestionDocument);

// Query request for questions to calculate max displayOrder
const { data: questionDisplayOrders } = useQuery(QuestionsDisplayOrderDocument, {
variables: {
sectionId: Number(sectionId)
},
skip: !sectionId
})

// Calculate the display order of the new question based on the last displayOrder number
const getDisplayOrder = useCallback(() => {
if (!questionDisplayOrders?.questions?.length) {
return 1;
}

// Filter out null/undefined questions and handle missing displayOrder
const validDisplayOrders = questionDisplayOrders.questions
.map(q => q?.displayOrder)
.filter((order): order is number => typeof order === 'number');

if (validDisplayOrders.length === 0) {
return 1;
}

const maxDisplayOrder = Math.max(...validDisplayOrders);
return maxDisplayOrder + 1;
}, [questionDisplayOrders]);


// Handle the selection of a question type
const handleSelect = (
{
Expand Down Expand Up @@ -247,6 +298,19 @@ const QuestionTypeSelectPage: React.FC = () => {
questionName={selectedQuestionType?.questionName ?? null}
questionJSON={selectedQuestionType?.questionJSON ?? ''}
sectionId={sectionId ? sectionId : ''}
breadcrumbs={<TemplateQuestionBreadcrumbs templateId={templateId} sectionId={sectionId} Global={Global} />}
backUrl={routePath('template.q.new', { templateId }, { section_id: sectionId, step: 1 })}
successUrl={routePath('template.show', { templateId })}
onSave={async (commonFields) => {
const input = {
templateId: Number(templateId),
sectionId: Number(sectionId),
displayOrder: getDisplayOrder(),
isDirty: true,
...commonFields,
};
await addQuestionMutation({ variables: { input } });
}}
/>
</>
)}
Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/template/create/__tests__/page.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('TemplateCreatePage', () => {
(useQueryStep as jest.Mock).mockReturnValue(null); // No step in query initially

render(<TemplateCreatePage />);
expect(screen.getByText('...messaging.loading')).toBeInTheDocument();
expect(screen.getByText('messaging.loading')).toBeInTheDocument();
});

it('should render step 1 form when step is 1', () => {
Expand Down
3 changes: 2 additions & 1 deletion app/[locale]/template/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import FormInput from '@/components/Form/FormInput';

import { debounce } from '@/hooks/debounce';
import { useQueryStep } from '@/app/[locale]/template/create/useQueryStep';
import Loading from '@/components/Loading';

const TemplateCreatePage: React.FC = () => {
const router = useRouter();
Expand Down Expand Up @@ -68,7 +69,7 @@ const TemplateCreatePage: React.FC = () => {

// TODO: Need to implement a shared loading component
if (step === null) {
return <div>...{Global('messaging.loading')}</div>
return <Loading />;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Loading component here

}

return (
Expand Down
Loading