Skip to content

Commit

Permalink
🐛 Add conditional tooltip and update template (#1637)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibolton336 authored Dec 18, 2023
1 parent 4316dac commit da92005
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 66 deletions.
7 changes: 7 additions & 0 deletions client/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,11 @@
"archetypeNoApplications": "No applications currently match the criteria tags.",
"archetypeAlreadyAssessed": "An assessment for one or more of the archetypes this application is associated with exists.",
"archetypeAlreadyReviewed": "A review for one or more of the archetypes this application is associated with exists. Open the details drawer to view the review(s).",
"autoSelectTagsLabel": "Automatically select tags based on the answers to the questionnaire. ",
"appNotAssesedTitle": "Assessment has not been completed",
"appNotAssessedBody": "In order to review an application it must be assessed first. Assess the application and try again.",
"autoSelectTooltip": "Automatically select this answer based on tags associated with the application(s) or archetype.",
"autoTagTooltip": "Automatically tag this application or archetype with these tags based on this answer to the questionnaire.",
"assessmentStakeholderHeader": "Select the stakeholder(s) or stakeholder group(s) associated with this assessment.",
"binaryPackaging": "Packaging will default to JAR if left empty.",
"blockedDeleteTracker": "Cannot delete {{what}} because it is associated with a tracker.",
Expand All @@ -188,6 +191,7 @@
"inheritedReviewTooltip_plural": "This application is inheriting reviews from {{count}} archetypes.",
"inheritedAssessmentTooltip": "This application is inheriting an assessment from an archetype.",
"inheritedAssessmentTooltip_plural": "This application is inheriting assessments from {{count}} archetypes.",
"dependentQuestionTooltip": "This question is conditionally included or excluded based on tags:",
"jiraInstanceNotConnected": "Jira instance {{name}} is not connected.",
"manageDependenciesInstructions": "Add northbound and southbound dependencies for the selected application here. Note that any selections made will be saved automatically. To undo any changes, you must manually delete the applications from the dropdowns.",
"noDataAvailableBody": "No data available to be shown here.",
Expand Down Expand Up @@ -302,6 +306,7 @@
"date": "Date",
"decision": "Decision",
"dependencies": "Dependencies",
"dependentQuestion": "Dependent question",
"description": "Description",
"details": "Details",
"displayName": "Display name",
Expand All @@ -310,6 +315,7 @@
"email": "Email",
"error": "Error",
"errorReport": "Error report",
"exclude": "Exclude",
"exportToIssue": "Export to Issue Manager",
"facts": "Facts",
"failed": "Failed",
Expand All @@ -327,6 +333,7 @@
"impactfulButNotAdvisableToMove": "Impactful but not advisable to move",
"image": "Image",
"imports": "Imports",
"include": "Include",
"importSummary": "Import summary",
"importSummaryDeleted": "Import summary deleted",
"inadvisable": "Inadvisable",
Expand Down
22 changes: 14 additions & 8 deletions client/public/templates/questionnaire-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,37 @@ sections:
- order: 1
text: What is the main technology in your application?
explanation: Identify the main framework or technology used in your application.
includeFor:
- category: Language
tag: Java
answers:
- order: 1
text: Quarkus
risk: green
rationale: Quarkus is a modern, container-friendly framework.
mitigation: No mitigation needed.
applyTags:
- category: Technology
- category: Runtime
tag: Quarkus
autoAnswerFor:
- category: Runtime
tag: Quarkus
- order: 2
text: Spring Boot
risk: green
rationale: Spring Boot is versatile and widely used.
mitigation: Ensure container compatibility.
applyTags:
- category: Technology
- category: Runtime
tag: Spring Boot
autoAnswerFor:
- category: Runtime
tag: Spring Boot
- order: 3
text: Legacy Monolithic Application
risk: red
rationale: Legacy monoliths are challenging for cloud adaptation.
mitigation: Consider refactoring into microservices.
applyTags:
- category: Architecture
tag: Monolith
- order: 2
text: Does your application use a microservices architecture?
explanation: Assess if the application is built using a microservices architecture.
Expand All @@ -42,9 +48,6 @@ sections:
risk: green
rationale: Microservices are well-suited for cloud environments.
mitigation: Continue monitoring service dependencies.
applyTags:
- category: Architecture
tag: Microservices
- order: 2
text: No
risk: yellow
Expand All @@ -59,6 +62,9 @@ sections:
- order: 3
text: Is your application's data storage cloud-optimized?
explanation: Evaluate if the data storage solution is optimized for cloud usage.
includeFor:
- category: Language
tag: Java
answers:
- order: 1
text: Cloud-Native Storage Solution
Expand Down
124 changes: 68 additions & 56 deletions client/src/app/components/answer-table/answer-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import {
} from "@app/components/TableControls";
import { NoDataEmptyState } from "@app/components/NoDataEmptyState";
import { Answer } from "@app/api/models";
import { Label, Text } from "@patternfly/react-core";
import { Label, Text, Tooltip } from "@patternfly/react-core";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { IconedStatus } from "@app/components/IconedStatus";
import { TimesCircleIcon } from "@patternfly/react-icons";
import { WarningTriangleIcon } from "@patternfly/react-icons";
import { List, ListItem } from "@patternfly/react-core";
import RiskIcon from "../risk-icon/risk-icon";
import { InfoCircleIcon } from "@patternfly/react-icons";

export interface IAnswerTableProps {
answers: Answer[];
Expand Down Expand Up @@ -101,63 +102,74 @@ const AnswerTable: React.FC<IAnswerTableProps> = ({
}
>
<Tbody>
{currentPageItems?.map((answer, rowIndex) => {
return (
<React.Fragment key={rowIndex}>
<Tr key={answer.text} {...getTrProps({ item: answer })}>
<TableRowContentWithControls
{...tableControls}
item={answer}
rowIndex={rowIndex}
>
<Td width={40} {...getTdProps({ columnKey: "choice" })}>
{answer.text}
</Td>
<Td width={20} {...getTdProps({ columnKey: "choice" })}>
<RiskIcon risk={answer.risk} />
</Td>
</TableRowContentWithControls>
</Tr>
<Tr>
{!!answer?.autoAnswerFor?.length && (
<>
<div style={{ display: "flex" }}>
<Text
className={spacing.mrSm}
style={{ flex: "0 0 5em" }}
>
Auto answer if the following tags are present:
</Text>
{answer?.autoAnswerFor?.map((tag, index) => {
return (
<div key={index} style={{ flex: "0 0 6em" }}>
<Label color="grey">{tag.tag}</Label>
{currentPageItems?.map((answer, rowIndex) => (
<React.Fragment key={rowIndex}>
<Tr {...getTrProps({ item: answer })}>
<TableRowContentWithControls
{...tableControls}
item={answer}
rowIndex={rowIndex}
>
<Td width={40} {...getTdProps({ columnKey: "choice" })}>
<div style={{ display: "flex", alignItems: "center" }}>
<span>{answer.text}</span>
{(!!answer?.autoAnswerFor?.length ||
!!answer?.applyTags?.length) && (
<Tooltip
content={
<div
className="pf-v5-c-tooltip__content pf-m-text-align-left"
id="conditional-tooltip-content"
>
{!!answer?.autoAnswerFor?.length && (
<>
<Text>
{t("message.autoSelectTooltip")}
</Text>
<List isPlain>
{answer.autoAnswerFor.map(
(tag, index) => (
<ListItem key={index}>
<Label color="blue">
{tag.tag}
</Label>
</ListItem>
)
)}
</List>
</>
)}
{!!answer?.applyTags?.length && (
<>
<Text>{t("message.autoTagTooltip")}</Text>
<List isPlain>
{answer.applyTags.map((tag, index) => (
<ListItem key={index}>
<Label color="blue">{tag.tag}</Label>
</ListItem>
))}
</List>
</>
)}
</div>
);
})}
</div>
</>
)}
</Tr>
<Tr>
{!!answer?.applyTags?.length && (
<div style={{ display: "flex" }}>
<Text className={spacing.mrSm}>
Apply Tags for this answer choice:
</Text>
{answer?.applyTags?.map((tag, index) => {
return (
<div key={index} style={{ flex: "0 0 6em" }}>
<Label color="grey">{tag.tag}</Label>
</div>
);
})}
}
>
<span className={spacing.mlXs}>
<InfoCircleIcon />
</span>
</Tooltip>
)}
</div>
)}
</Tr>
</React.Fragment>
);
})}
</Td>

<Td width={20} {...getTdProps({ columnKey: "weight" })}>
<RiskIcon risk={answer.risk} />
</Td>
</TableRowContentWithControls>
</Tr>
{/* ... other rows ... */}
</React.Fragment>
))}
</Tbody>
</ConditionalTableBody>
</Table>
Expand Down
39 changes: 37 additions & 2 deletions client/src/app/components/questions-table/questions-table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useTranslation } from "react-i18next";
import spacing from "@patternfly/react-styles/css/utilities/Spacing/spacing";
import { Assessment, Question, Questionnaire } from "@app/api/models";
import { useLocalTableControls } from "@app/hooks/table-controls";
import { Label } from "@patternfly/react-core";
import { Label, Tooltip } from "@patternfly/react-core";
import { NoDataEmptyState } from "@app/components/NoDataEmptyState";
import AnswerTable from "@app/components/answer-table/answer-table";
import { AxiosError } from "axios";
Expand Down Expand Up @@ -99,6 +99,35 @@ const QuestionsTable: React.FC<{
data?.sections.find((section) =>
section.questions.includes(question)
)?.name || "";

const getConditionalTooltipContent = (question: Question) => {
const includeTags = question?.includeFor
?.map((tag) => tag.tag)
.join(", ");
const excludeTags = question?.excludeFor
?.map((tag) => tag.tag)
.join(", ");

return (
<div
className="pf-v5-c-tooltip__content pf-m-text-align-left"
id="conditional-tooltip-content"
>
<div>{t("message.dependentQuestionTooltip")}</div>
{includeTags && (
<div>
{t("terms.include")}: {includeTags}
</div>
)}
{excludeTags && (
<div>
{t("terms.exclude")}: {excludeTags}
</div>
)}
</div>
);
};

return (
<React.Fragment key={rowIndex}>
<Tr key={question.text} {...getTrProps({ item: question })}>
Expand All @@ -113,7 +142,13 @@ const QuestionsTable: React.FC<{
>
{(!!question?.includeFor?.length ||
!!question?.excludeFor?.length) && (
<Label className={spacing.mrSm}>Conditional</Label>
<Tooltip
content={getConditionalTooltipContent(question)}
>
<Label className={spacing.mrSm}>
{t("terms.dependentQuestion")}
</Label>
</Tooltip>
)}
{question.text}
</Td>
Expand Down

0 comments on commit da92005

Please sign in to comment.