Skip to content

Commit

Permalink
✨ Add search toolbar and "all questions" tab to questionnaire view pa…
Browse files Browse the repository at this point in the history
…ge, clean up layout (#1313)

Resolves #1293. We determined we don't need the filter dropdown (at
least for now), just the search bar.
* Cleans up some layout issues on the page.
* Adds an "All questions" tab above the section tabs. When viewing this
tab, the questions table has a "Section" column so you can still tell
the sections apart when they are viewed together.
* Adds the total number of questions under each tab title. When the
search bar is used, a badge appears next to this to show how many
questions match the search.
* Adds an empty state to the table if there are no questions matching
your search.

<img width="1500" alt="Screenshot 2023-08-25 at 2 24 18 PM"
src="https://github.com/konveyor/tackle2-ui/assets/811963/c655ba4e-4a18-493a-87ad-ff1e3c926da3">


![U4kHZuOvzh](https://github.com/konveyor/tackle2-ui/assets/811963/3698dc9e-5841-44e4-9fee-40752b4def86)

<img width="1501" alt="Screenshot 2023-08-25 at 2 31 19 PM"
src="https://github.com/konveyor/tackle2-ui/assets/811963/27e547c8-76dc-4398-9a2f-84cd9da64e8c">

---------

Signed-off-by: Mike Turley <mike.turley@alum.cs.umass.edu>
  • Loading branch information
mturley committed Aug 26, 2023
1 parent 36fdf4d commit ea99f09
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 86 deletions.
2 changes: 1 addition & 1 deletion client/src/app/hooks/table-controls/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface IExtraArgsForURLParamHooks<
export interface ITableControlDataDependentArgs<TItem> {
isLoading?: boolean;
idProperty: KeyWithValueType<TItem, string | number>;
forceNumRenderedColumns?: number;
}

// Derived state option args
Expand Down Expand Up @@ -112,6 +113,5 @@ export interface IUseTableControlPropsArgs<
IExpansionDerivedStateArgs<TItem, TColumnKey>,
IActiveRowDerivedStateArgs<TItem> {
currentPageItems: TItem[];
forceNumRenderedColumns?: number;
selectionState: ReturnType<typeof useSelectionState<TItem>>; // TODO make this optional? fold it in?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";
import { TabTitleText, Badge } from "@patternfly/react-core";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { CustomYamlAssessmentQuestion } from "@app/api/models";

const QuestionnaireSectionTabTitle: React.FC<{
isSearching: boolean;
sectionName: string;
unfilteredQuestions: CustomYamlAssessmentQuestion[];
filteredQuestions: CustomYamlAssessmentQuestion[];
}> = ({ isSearching, sectionName, unfilteredQuestions, filteredQuestions }) => (
<TabTitleText aria-label="vertical" role="region">
{sectionName}
<br />
<small>
{unfilteredQuestions.length} questions
{isSearching ? (
<Badge
screenReaderText="Questions matching search"
className={spacing.mlSm}
isRead={filteredQuestions.length === 0}
>
{`${filteredQuestions.length} match${
filteredQuestions.length === 1 ? "" : "es"
}`}
</Badge>
) : null}
</small>
</TabTitleText>
);

export default QuestionnaireSectionTabTitle;
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,40 @@ import {
ExpandableRowContent,
} from "@patternfly/react-table";
import {
ConditionalTableBody,
TableHeaderContentWithControls,
TableRowContentWithControls,
} from "@app/components/TableControls";
import { useTranslation } from "react-i18next";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { CustomYamlAssessmentQuestion } from "@app/api/models";
import { CustomYamlAssessmentQuestion, YamlAssessment } from "@app/api/models";
import { useLocalTableControls } from "@app/hooks/table-controls";
import { Label } from "@patternfly/react-core";
import AnswerTable from "./answer-table";
import { NoDataEmptyState } from "@app/components/NoDataEmptyState";

const QuestionsTable: React.FC<{
fetchError: boolean;
fetchError?: Error;
questions?: CustomYamlAssessmentQuestion[];
}> = ({ fetchError = false, questions }) => {
isSearching?: boolean;
assessmentData?: YamlAssessment | null;
isAllQuestionsTab?: boolean;
}> = ({
fetchError,
questions,
isSearching = false,
assessmentData,
isAllQuestionsTab = false,
}) => {
const tableControls = useLocalTableControls({
idProperty: "formulation",
items: questions || [],
columnNames: {
formulation: "Name",
section: "Section",
},
hasActionsColumn: true,
isSelectable: false,
expandableVariant: "single",
forceNumRenderedColumns: isAllQuestionsTab ? 3 : 2, // columns+1 for expand control
});

const {
Expand All @@ -54,44 +65,78 @@ const QuestionsTable: React.FC<{
<Tr>
<TableHeaderContentWithControls {...tableControls}>
<Th {...getThProps({ columnKey: "formulation" })} />
{isAllQuestionsTab ? (
<Th {...getThProps({ columnKey: "section" })} />
) : null}
</TableHeaderContentWithControls>
</Tr>
</Thead>
<Tbody>
{currentPageItems?.map((question, rowIndex) => (
<>
<Tr key={question.formulation}>
<TableRowContentWithControls
{...tableControls}
item={question}
rowIndex={rowIndex}
>
<Td width={100} {...getTdProps({ columnKey: "formulation" })}>
{(!!question?.include_if_tags_present?.length ||
!!question?.skip_if_tags_present?.length) && (
<Label className={spacing.mrSm}>Conditional</Label>
)}
{question.formulation}
</Td>
</TableRowContentWithControls>
</Tr>
{isCellExpanded(question) ? (
<Tr isExpanded>
<Td />
<Td
{...getExpandedContentTdProps({ item: question })}
className={spacing.pyLg}
>
<ExpandableRowContent>
{question.explanation}
<AnswerTable answers={question.answers} />
</ExpandableRowContent>
</Td>
</Tr>
) : null}
</>
))}
</Tbody>
<ConditionalTableBody
numRenderedColumns={numRenderedColumns}
isError={!!fetchError}
isNoData={questions?.length === 0}
noDataEmptyState={
<NoDataEmptyState
title={
isSearching
? isAllQuestionsTab
? "No questions match your search"
: "No questions in this section match your search"
: "This section is empty"
}
/>
}
>
<Tbody>
{currentPageItems?.map((question, rowIndex) => {
const sectionName =
assessmentData?.sections.find((section) =>
section.questions.includes(question)
)?.name || "";
return (
<>
<Tr key={question.formulation}>
<TableRowContentWithControls
{...tableControls}
item={question}
rowIndex={rowIndex}
>
<Td
width={isAllQuestionsTab ? 60 : 100}
{...getTdProps({ columnKey: "formulation" })}
>
{(!!question?.include_if_tags_present?.length ||
!!question?.skip_if_tags_present?.length) && (
<Label className={spacing.mrSm}>Conditional</Label>
)}
{question.formulation}
</Td>
{isAllQuestionsTab ? (
<Td width={40} {...getTdProps({ columnKey: "section" })}>
{sectionName}
</Td>
) : null}
</TableRowContentWithControls>
</Tr>
{isCellExpanded(question) ? (
<Tr isExpanded>
<Td />
<Td
{...getExpandedContentTdProps({ item: question })}
className={spacing.pyLg}
>
<ExpandableRowContent>
{question.explanation}
<AnswerTable answers={question.answers} />
</ExpandableRowContent>
</Td>
</Tr>
) : null}
</>
);
})}
</Tbody>
</ConditionalTableBody>
</Table>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
.tabs-vertical-container {
width: 20em;
display: flex;
}
.tab-content-container {
width: 80em;

.tabs-vertical-container .pf-v5-c-tabs {
width: 20%;
}

.tabs-vertical-container .pf-v5-c-tab-content {
width: 80%;
}
Loading

0 comments on commit ea99f09

Please sign in to comment.