@@ -245,7 +245,7 @@ export default class IssuesServiceMock { | |||
rule: mockRuleDetails({ | |||
key: parameters.key, | |||
name: 'Advanced rule', | |||
genericConcepts: ['defense_in_depth'], | |||
educationPrinciples: ['defense_in_depth'], | |||
descriptionSections: [ | |||
{ key: RuleDescriptionSections.INTRODUCTION, content: '<h1>Into</h1>' }, | |||
{ key: RuleDescriptionSections.ROOT_CAUSE, content: '<h1>Because</h1>' }, |
@@ -58,7 +58,7 @@ module.exports = { | |||
globalNavBarBg: '#262626', | |||
genericConceptBgColor: '#F4F6FF', | |||
educationPrinciplesBgColor: '#F4F6FF', | |||
// table | |||
rowHoverHighlight: '#ecf6fe', |
@@ -108,10 +108,10 @@ export default class RuleViewerTabs extends React.PureComponent<Props, State> { | |||
{ | |||
key: RuleTabKeys.MoreInfo, | |||
label: translate('coding_rules.description_section.title', RuleTabKeys.MoreInfo), | |||
content: (ruleDetails.genericConcepts || | |||
content: (ruleDetails.educationPrinciples || | |||
descriptionSectionsByKey[RuleDescriptionSections.RESOURCES]) && ( | |||
<MoreInfoRuleDescription | |||
genericConcepts={ruleDetails.genericConcepts} | |||
educationPrinciples={ruleDetails.educationPrinciples} | |||
sections={descriptionSectionsByKey[RuleDescriptionSections.RESOURCES]} | |||
/> | |||
) |
@@ -38,7 +38,7 @@ beforeEach(() => { | |||
handler = new IssuesServiceMock(); | |||
}); | |||
it('should show generic concpet', async () => { | |||
it('should show education principles', async () => { | |||
const user = userEvent.setup(); | |||
renderProjectIssuesApp('project/issues?issues=issue2&open=issue2&id=myproject'); | |||
await user.click(await screen.findByRole('button', { name: `issue.tabs.more_info` })); |
@@ -142,10 +142,10 @@ export default class IssueViewerTabs extends React.PureComponent<Props, State> { | |||
{ | |||
key: IssueTabKeys.MoreInfo, | |||
label: translate('issue.tabs', IssueTabKeys.MoreInfo), | |||
content: (ruleDetails.genericConcepts || | |||
content: (ruleDetails.educationPrinciples || | |||
descriptionSectionsByKey[RuleDescriptionSections.RESOURCES]) && ( | |||
<MoreInfoRuleDescription | |||
genericConcepts={ruleDetails.genericConcepts} | |||
educationPrinciples={ruleDetails.educationPrinciples} | |||
sections={descriptionSectionsByKey[RuleDescriptionSections.RESOURCES]} | |||
/> | |||
) |
@@ -21,22 +21,25 @@ import * as React from 'react'; | |||
import { RuleDescriptionSection } from '../../apps/coding-rules/rule'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { Dict } from '../../types/types'; | |||
import DefenseInDepth from './genericConcepts/DefenseInDepth'; | |||
import LeastTrustPrinciple from './genericConcepts/LeastTrustPrinciple'; | |||
import DefenseInDepth from './educationPrinciples/DefenseInDepth'; | |||
import LeastTrustPrinciple from './educationPrinciples/LeastTrustPrinciple'; | |||
import RuleDescription from './RuleDescription'; | |||
import './style.css'; | |||
interface Props { | |||
sections?: RuleDescriptionSection[]; | |||
genericConcepts?: string[]; | |||
educationPrinciples?: string[]; | |||
} | |||
const GENERIC_CONCPET_MAP: Dict<React.ComponentType> = { | |||
const EDUCATION_PRINCIPLES_MAP: Dict<React.ComponentType> = { | |||
defense_in_depth: DefenseInDepth, | |||
least_trust_principle: LeastTrustPrinciple | |||
}; | |||
export default function MoreInfoRuleDescription({ sections = [], genericConcepts = [] }: Props) { | |||
export default function MoreInfoRuleDescription({ | |||
sections = [], | |||
educationPrinciples = [] | |||
}: Props) { | |||
return ( | |||
<> | |||
{sections.length > 0 && ( | |||
@@ -50,20 +53,20 @@ export default function MoreInfoRuleDescription({ sections = [], genericConcepts | |||
</> | |||
)} | |||
{genericConcepts.length > 0 && ( | |||
{educationPrinciples.length > 0 && ( | |||
<> | |||
<div className="big-padded-left big-padded-right rule-desc"> | |||
<h2 className="null-spacer-top"> | |||
{translate('coding_rules.more_info.generic_concept.title')} | |||
{translate('coding_rules.more_info.education_principles.title')} | |||
</h2> | |||
</div> | |||
{genericConcepts.map(key => { | |||
const Concept = GENERIC_CONCPET_MAP[key]; | |||
{educationPrinciples.map(key => { | |||
const Concept = EDUCATION_PRINCIPLES_MAP[key]; | |||
if (Concept === undefined) { | |||
return null; | |||
} | |||
return ( | |||
<div key={key} className="generic-concept rule-desc"> | |||
<div key={key} className="education-principles rule-desc"> | |||
<Concept /> | |||
</div> | |||
); |
@@ -18,8 +18,8 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
.generic-concept { | |||
background-color: var(--genericConceptBgColor); | |||
.education-principles { | |||
background-color: var(--educationPrinciplesBgColor); | |||
border-radius: 2px; | |||
display: inline-block; | |||
margin-left: 16px; |
@@ -589,7 +589,7 @@ export interface RuleDetails extends Rule { | |||
defaultRemFnBaseEffort?: string; | |||
defaultRemFnType?: string; | |||
descriptionSections?: RuleDescriptionSection[]; | |||
genericConcepts?: string[]; | |||
educationPrinciples?: string[]; | |||
effortToFixDescription?: string; | |||
htmlDesc?: string; | |||
htmlNote?: string; |
@@ -1916,7 +1916,7 @@ coding_rules.description_context_title=Which component or framework contains the | |||
coding_rules.description_context_default_information={0} was detected as the most relevant component or framework for this issue. | |||
coding_rules.description_context_other=Other | |||
coding_rules.more_info.generic_concept.title=Security principles | |||
coding_rules.more_info.education_principles.title=Security principles | |||
coding_rules.more_info.resources.title=Resources | |||
#------------------------------------------------------------------------------ |