Skip to content

Commit

Permalink
Fetch questions query only when leaf node is expanded
Browse files Browse the repository at this point in the history
  • Loading branch information
subinasr committed Sep 13, 2023
1 parent 914d5a5 commit 4e0d25c
Show file tree
Hide file tree
Showing 6 changed files with 331 additions and 281 deletions.
2 changes: 1 addition & 1 deletion backend
Submodule backend updated 1 files
+1 −0 main/settings.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
.question-wrapper {
--input-width: 35rem;
align-items: flex-start;
background-color: var(--dui-color-background);
padding: var(--dui-spacing-extra-large);
padding-left: var(--dui-spacing-medium);
gap: var(--dui-spacing-large);
background-color: var(--dui-color-background);

.drag-icon {
> path {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {

import {
QUESTION_FRAGMENT,
} from '../queries';
} from '#views/QuestionnaireEdit/queries';

import styles from './index.module.css';

Expand Down
318 changes: 318 additions & 0 deletions src/views/QuestionnaireEdit/QuestionList/LeafNode/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
import {
useState,
useCallback,
useMemo,
} from 'react';
import {
useQuery,
useMutation,
gql,
} from '@apollo/client';
import {
isNotDefined,
} from '@togglecorp/fujs';
import {
useAlert,
} from '@the-deep/deep-ui';

import SortableList from '#components/SortableList';
import {
QuestionsForLeafGroupQuery,
QuestionsForLeafGroupQueryVariables,
UpdateQuestionsVisibilityMutation,
UpdateQuestionsVisibilityMutationVariables,
UpdateQuestionsOrderMutation,
UpdateQuestionsOrderMutationVariables,
VisibilityActionEnum,
} from '#generated/types';
import {
type ProjectScope,
} from '#utils/common';

import QuestionPreview from './QuestionPreview';
import {
QUESTION_FRAGMENT,
} from '../../queries';

type Question = NonNullable<NonNullable<ProjectScope<QuestionsForLeafGroupQuery>['questions']>['items']>[number];
const questionKeySelector = (q: Question) => q.id;

const QUESTIONS_FOR_LEAF_GROUP = gql`
${QUESTION_FRAGMENT}
query QuestionsForLeafGroup(
$projectId: ID!,
$questionnaireId: ID!,
$leafGroupId: ID!,
) {
private {
projectScope(pk: $projectId) {
id
questions(
filters: {
questionnaire: {
pk: $questionnaireId,
},
leafGroup: {
pk: $leafGroupId,
},
}
order: {
order: ASC
}
) {
count
limit
offset
items {
...QuestionResponse
}
}
}
}
}
`;

const UPDATE_QUESTIONS_ORDER = gql`
${QUESTION_FRAGMENT}
mutation UpdateQuestionsOrder(
$projectId: ID!,
$questionnaireId: ID!,
$leafGroupId: ID!,
$data: [QuestionOrderInputType!]!
) {
private {
projectScope(pk: $projectId) {
bulkUpdateQuestionsOrder(
data: $data
leafGroupId: $leafGroupId
questionnaireId: $questionnaireId
) {
errors
results {
...QuestionResponse
}
}
}
}
}
`;

const UPDATE_QUESTIONS_VISIBILITY = gql`
${QUESTION_FRAGMENT}
mutation UpdateQuestionsVisibility(
$projectId: ID!,
$questionIds: [ID!]!,
$questionnaireId: ID!,
$visibility: VisibilityActionEnum!,
){
private {
projectScope(pk: $projectId) {
updateQuestionsVisibility(
ids: $questionIds,
questionnaireId: $questionnaireId,
visibility: $visibility,
) {
errors
results {
...QuestionResponse
}
}
}
}
}
`;

interface Props {
className?: string;
projectId: string;
questionnaireId: string;
leafGroupId: string;
onEditQuestionClick: (val?: string | undefined) => void;
setSelectedQuestionType: React.Dispatch<React.SetStateAction<string | undefined>>;
setActiveQuestionId: React.Dispatch<React.SetStateAction<string | undefined>>;
setSelectedLeafGroupId: React.Dispatch<React.SetStateAction<string | undefined>>;
}

function LeafNode(props: Props) {
const {
className,
projectId,
questionnaireId,
leafGroupId,
onEditQuestionClick,
setSelectedQuestionType,
setActiveQuestionId,
setSelectedLeafGroupId,
} = props;

const alert = useAlert();

const questionsVariables = useMemo(() => {
if (isNotDefined(projectId)
|| isNotDefined(questionnaireId)
|| isNotDefined(leafGroupId)) {
return undefined;
}

return ({
projectId,
questionnaireId,
leafGroupId,
});
}, [
projectId,
questionnaireId,
leafGroupId,
]);

const [
orderedQuestions,
setOrderedQuestions,
] = useState<Question[] | undefined>();

const {
loading: questionsPending,
refetch: retriggerQuestionsFetch,
} = useQuery<QuestionsForLeafGroupQuery, QuestionsForLeafGroupQueryVariables>(
QUESTIONS_FOR_LEAF_GROUP,
{
skip: isNotDefined(questionsVariables),
variables: questionsVariables,
onCompleted: (response) => {
const questions = response?.private?.projectScope?.questions?.items;
setOrderedQuestions(questions);
},
},
);

const [
triggerQuestionsOrderUpdate,
{ loading: questionsOrderUpdatePending },
] = useMutation<UpdateQuestionsOrderMutation, UpdateQuestionsOrderMutationVariables>(
UPDATE_QUESTIONS_ORDER,
{
onCompleted: (response) => {
const questionOrderResponse = response?.private
?.projectScope?.bulkUpdateQuestionsOrder;
if (questionOrderResponse?.errors) {
alert.show(
'Failed to update questions order',
{ variant: 'error' },
);
}
},
onError: () => {
alert.show(
'Failed to update questions order',
{ variant: 'error' },
);
},
},
);

const [
triggerQuestionsVisibilityUpdate,
] = useMutation<UpdateQuestionsVisibilityMutation, UpdateQuestionsVisibilityMutationVariables>(
UPDATE_QUESTIONS_VISIBILITY,
{
onCompleted: (response) => {
const questionsResponse = response?.private
?.projectScope?.updateQuestionsVisibility;
if (questionsResponse?.errors) {
alert.show(
'Failed to update questions visibility',
);
}
},
onError: () => {
alert.show(
'Failed to update questions visibility',
);
},
},
);

const handleQuestionOrderChange = useCallback((val: Question[]) => {
if (!val || !leafGroupId) {
return;
}
const orderedQuestionsToSend = val.map(
(question, index) => ({
id: question.id,
order: index + 1,
}),
);

triggerQuestionsOrderUpdate({
variables: {
projectId,
questionnaireId,
leafGroupId,
data: orderedQuestionsToSend,
},
});
setOrderedQuestions(val);
}, [
projectId,
questionnaireId,
leafGroupId,
triggerQuestionsOrderUpdate,
]);

const handleSelectedQuestionsChange = useCallback((val: boolean, id: string) => {
triggerQuestionsVisibilityUpdate({
variables: {
projectId,
questionnaireId,
questionIds: [id],
visibility: val
? 'SHOW' as VisibilityActionEnum
: 'HIDE' as VisibilityActionEnum,
},
});
}, [
triggerQuestionsVisibilityUpdate,
projectId,
questionnaireId,
]);

const questionRendererParams = useCallback((_: string, datum: Question) => ({
question: datum,
showAddQuestionPane: onEditQuestionClick,
setSelectedQuestionType,
projectId,
setActiveQuestionId,
onSelectedQuestionsChange: handleSelectedQuestionsChange,
setSelectedLeafGroupId,
refetchQuestionList: retriggerQuestionsFetch,
}), [
onEditQuestionClick,
projectId,
setActiveQuestionId,
setSelectedQuestionType,
handleSelectedQuestionsChange,
setSelectedLeafGroupId,
retriggerQuestionsFetch,
]);

return (
<SortableList
name="questions"
className={className}
data={orderedQuestions}
direction="vertical"
keySelector={questionKeySelector}
renderer={QuestionPreview}
rendererParams={questionRendererParams}
onChange={handleQuestionOrderChange}
borderBetweenItem
emptyMessage="There are no questions in this questionnaire yet."
pending={questionsPending || questionsOrderUpdatePending}
messageShown
filtered={false}
errored={false}
/>
);
}

export default LeafNode;
2 changes: 0 additions & 2 deletions src/views/QuestionnaireEdit/QuestionList/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

.item {
border: none;
overflow-y: unset;

.header {
background-color: transparent;
Expand All @@ -31,7 +30,6 @@

.content {
background-color: var(--dui-color-white);
overflow-y: unset;
}

&.first {
Expand Down
Loading

0 comments on commit 4e0d25c

Please sign in to comment.