export function mockRulesActivationsInQP() {
return {
- [RULE_1]: [
- mockRuleActivation({ qProfile: QP_1 }),
- mockRuleActivation({ qProfile: QP_4 }),
- mockRuleActivation({ qProfile: QP_5, inherit: 'INHERITED' }),
- mockRuleActivation({ qProfile: QP_6 }),
- ],
+ [RULE_1]: [mockRuleActivation({ qProfile: QP_1 }), mockRuleActivation({ qProfile: QP_6 })],
[RULE_7]: [mockRuleActivation({ qProfile: QP_2 })],
[RULE_8]: [mockRuleActivation({ qProfile: QP_2 })],
[RULE_9]: [
mockRuleActivation({ qProfile: QP_2, inherit: 'OVERRIDES', prioritizedRule: true }),
mockRuleActivation({ qProfile: QP_2_Parent, severity: 'MINOR' }),
],
+ [RULE_11]: [
+ mockRuleActivation({ qProfile: QP_4 }),
+ mockRuleActivation({ qProfile: QP_5, inherit: 'INHERITED' }),
+ ],
};
}
// Change rule details in quality profile
await user.click(ui.changeButton('QP FooBaz').get());
+ await user.clear(ui.paramInput('1').get());
await user.type(ui.paramInput('1').get(), 'New');
await user.click(ui.saveButton.get(ui.changeQPDialog.get()));
- expect(screen.getByText('New')).toBeInTheDocument();
+ expect(await screen.findByText('New')).toBeInTheDocument();
// Revert rule details in quality profile
await user.click(ui.revertToParentDefinitionButton.get());
it('can deactivate an inherrited rule', async () => {
const { ui, user } = getPageObjects();
rulesHandler.setIsAdmin();
- renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule1');
+ renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule11');
await ui.detailsloaded();
// Should show 2 deactivate buttons: one for the parent, one for the child profile.
const { ui } = getPageObjects();
rulesHandler.setIsAdmin();
settingsHandler.set(SettingsKey.QPAdminCanDisableInheritedRules, 'false');
- renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule1');
+ renderCodingRulesApp(mockLoggedInUser(), 'coding_rules?open=rule11');
await ui.detailsloaded();
// Should show 1 deactivate button: one for the parent, none for the child profile.
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { ButtonSecondary } from 'design-system';
+import { Button, ButtonVariety } from '@sonarsource/echoes-react';
import * as React from 'react';
import { Profile as BaseProfile } from '../../../api/quality-profiles';
import { Rule, RuleActivation, RuleDetails } from '../../../types/types';
return (
<>
- <ButtonSecondary
+ <Button
+ variety={ButtonVariety.Default}
aria-label={ariaLabel}
className={className}
id="coding-rules-quality-profile-activate"
onClick={() => setModalOpen(true)}
>
{buttonText}
- </ButtonSecondary>
+ </Button>
- {modalOpen && (
- <ActivationFormModal
- activation={activation}
- modalHeader={modalHeader}
- onClose={() => setModalOpen(false)}
- onDone={props.onDone}
- profiles={profiles}
- rule={rule}
- />
- )}
+ <ActivationFormModal
+ activation={activation}
+ modalHeader={modalHeader}
+ isOpen={modalOpen}
+ onOpenChange={setModalOpen}
+ onClose={() => setModalOpen(false)}
+ onDone={props.onDone}
+ profiles={profiles}
+ rule={rule}
+ />
</>
);
}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { Button, ButtonVariety, Modal } from '@sonarsource/echoes-react';
import {
- ButtonPrimary,
FlagMessage,
FormField,
InputField,
InputSelect,
InputTextArea,
LabelValueSelectOption,
- Modal,
Note,
Switch,
} from 'design-system';
interface Props {
activation?: RuleActivation;
+ isOpen: boolean;
modalHeader: string;
onClose: () => void;
onDone?: (severity: string, prioritizedRule: boolean) => Promise<void> | void;
+ onOpenChange: (isOpen: boolean) => void;
profiles: Profile[];
rule: Rule | RuleDetails;
}
const FORM_ID = 'rule-activation-modal-form';
export default function ActivationFormModal(props: Readonly<Props>) {
- const { activation, rule, profiles, modalHeader } = props;
+ const { activation, rule, profiles, modalHeader, isOpen, onOpenChange } = props;
const { mutate: activateRule, isPending: submitting } = useActivateRuleMutation((data) => {
props.onDone?.(data.severity as string, data.prioritizedRule as boolean);
props.onClose();
});
const { hasFeature } = useAvailableFeatures();
const intl = useIntl();
- const [prioritizedRule, setPrioritizedRule] = React.useState(
- activation ? activation.prioritizedRule : false,
+ const [changedPrioritizedRule, setChangedPrioritizedRule] = React.useState<boolean | undefined>(
+ undefined,
);
-
- const profilesWithDepth = getQualityProfilesWithDepth(profiles, rule.lang);
- const [profile, setProfile] = React.useState(profilesWithDepth[0]);
- const [params, setParams] = React.useState(getRuleParams({ activation, rule }));
- const [severity, setSeverity] = React.useState(
- (activation ? activation.severity : rule.severity) as IssueSeverity,
+ const [changedProfile, setChangedProfile] = React.useState<ProfileWithDepth | undefined>(
+ undefined,
+ );
+ const [changedParams, setChangedParams] = React.useState<Record<string, string> | undefined>(
+ undefined,
);
+ const [changedSeverity, setChangedSeverity] = React.useState<IssueSeverity | undefined>(
+ undefined,
+ );
+
+ const profilesWithDepth = React.useMemo(() => {
+ return getQualityProfilesWithDepth(profiles, rule.lang);
+ }, [profiles, rule.lang]);
+ const prioritizedRule =
+ changedPrioritizedRule ?? (activation ? activation.prioritizedRule : false);
+ const profile = changedProfile ?? profilesWithDepth[0];
+ const params = changedParams ?? getRuleParams({ activation, rule });
+ const severity =
+ changedSeverity ?? ((activation ? activation.severity : rule.severity) as IssueSeverity);
const profileOptions = profilesWithDepth.map((p) => ({ label: p.name, value: p }));
const isCustomRule = !!(rule as RuleDetails).templateKey;
const activeInAllProfiles = profilesWithDepth.length <= 0;
const isUpdateMode = !!activation;
+ React.useEffect(() => {
+ if (!isOpen) {
+ setChangedPrioritizedRule(undefined);
+ setChangedProfile(undefined);
+ setChangedParams(undefined);
+ setChangedSeverity(undefined);
+ }
+ }, [isOpen]);
+
const handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
event.preventDefault();
const data = {
event: React.SyntheticEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const { name, value } = event.currentTarget;
- setParams({ ...params, [name]: value });
+ setChangedParams({ ...params, [name]: value });
};
- const makeScrollable = (rule.params?.length ?? 0) > 1;
-
return (
<Modal
- headerTitle={modalHeader}
- onClose={props.onClose}
- loading={submitting}
- isOverflowVisible={!makeScrollable}
- isScrollable={makeScrollable}
+ title={modalHeader}
+ isOpen={isOpen}
+ onOpenChange={onOpenChange}
primaryButton={
- <ButtonPrimary disabled={submitting || activeInAllProfiles} form={FORM_ID} type="submit">
+ <Button
+ variety={ButtonVariety.Primary}
+ isDisabled={submitting || activeInAllProfiles}
+ isLoading={submitting}
+ form={FORM_ID}
+ type="submit"
+ >
{isUpdateMode
? intl.formatMessage({ id: 'save' })
: intl.formatMessage({ id: 'coding_rules.activate' })}
- </ButtonPrimary>
+ </Button>
+ }
+ secondaryButton={
+ <Button variety={ButtonVariety.Default} isDisabled={submitting} onClick={props.onClose}>
+ {intl.formatMessage({ id: 'cancel' })}
+ </Button>
}
- secondaryButtonLabel={intl.formatMessage({ id: 'cancel' })}
- body={
+ content={
<form className="sw-pb-10" id={FORM_ID} onSubmit={handleFormSubmit}>
{!isUpdateMode && activeInAllProfiles && (
<FlagMessage className="sw-mb-2" variant="info">
isClearable={false}
isDisabled={submitting || profilesWithDepth.length < MIN_PROFILES_TO_ENABLE_SELECT}
onChange={({ value }: LabelValueSelectOption<ProfileWithDepth>) => {
- setProfile(value);
+ setChangedProfile(value);
}}
getOptionLabel={({ value }: LabelValueSelectOption<ProfileWithDepth>) =>
' '.repeat(value.depth) + value.name
{ state: 'off' },
),
}}
- onChange={setPrioritizedRule}
+ onChange={setChangedPrioritizedRule}
value={prioritizedRule}
/>
<span className="sw-text-xs">
<SeveritySelect
isDisabled={submitting}
onChange={({ value }: LabelValueSelectOption<IssueSeverity>) => {
- setSeverity(value);
+ setChangedSeverity(value);
}}
severity={severity}
/>