]> source.dussan.org Git - sonarqube.git/commitdiff
Revert "SONAR-23137 Remove success status around legacy input"
authorJeremy Davis <jeremy.davis@sonarsource.com>
Thu, 10 Oct 2024 08:53:51 +0000 (10:53 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 10 Oct 2024 20:02:44 +0000 (20:02 +0000)
This reverts commit bba5ffa2fe6afe5c4eed1e4709db9f52710b0a7c.

14 files changed:
server/sonar-web/design-system/src/components/input/InputField.tsx
server/sonar-web/design-system/src/components/input/__tests__/InputField-test.tsx
server/sonar-web/src/main/js/apps/create/project/components/ProjectValidation.tsx
server/sonar-web/src/main/js/apps/create/project/manual/ManualProjectCreate.tsx
server/sonar-web/src/main/js/apps/projectKey/UpdateForm.tsx
server/sonar-web/src/main/js/apps/projectNewCode/components/BranchNewCodeDefinitionSettingModal.tsx
server/sonar-web/src/main/js/apps/projectNewCode/components/ProjectNewCodeDefinitionSelector.tsx
server/sonar-web/src/main/js/apps/settings/components/NewCodeDefinition.tsx
server/sonar-web/src/main/js/apps/users/components/UserForm.tsx
server/sonar-web/src/main/js/components/common/EmailInput.tsx
server/sonar-web/src/main/js/components/common/UserPasswordInput.tsx
server/sonar-web/src/main/js/components/controls/InputValidationField.tsx
server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionDaysOption.tsx
server/sonar-web/src/main/js/components/new-code-definition/NewCodeDefinitionSelector.tsx

index a9501d157761beddbc96363e5e1a4defa4bf8351..4649d739fb3496e7bce68201ffb3d30e9ae76a98 100644 (file)
@@ -29,12 +29,14 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, '
   as?: React.ElementType;
   className?: string;
   isInvalid?: boolean;
+  isValid?: boolean;
   size?: InputSizeKeys;
 }
 
 interface InputTextAreaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
   className?: string;
   isInvalid?: boolean;
+  isValid?: boolean;
   size?: InputSizeKeys;
 }
 
@@ -68,10 +70,18 @@ const dangerStyle = (props: ThemedProps) => css`
   --focusOutline: var(--echoes-focus-border-width-default) solid var(--echoes-color-focus-default);
 `;
 
+const successStyle = (props: ThemedProps) => css`
+  --border: ${themeBorder('default', 'inputSuccess')(props)};
+  --focusBorder: ${themeBorder('default', 'inputSuccessFocus')(props)};
+  --focusOutline: ${themeBorder('focus', 'inputSuccessFocus')(props)};
+`;
+
 const getInputVariant = (props: ThemedProps & { isInvalid?: boolean; isValid?: boolean }) => {
-  const { isInvalid } = props;
+  const { isValid, isInvalid } = props;
   if (isInvalid) {
     return dangerStyle;
+  } else if (isValid) {
+    return successStyle;
   }
   return defaultStyle;
 };
index 1682fca211adc766dd7d690347e0c7733b3f6750..ccac9ace7357d1c42ee39d4ae9951d221b996c76 100644 (file)
@@ -22,10 +22,11 @@ import { InputField } from '../InputField';
 
 describe('Input Field', () => {
   it.each([
-    ['default', false, 'defaultStyle'],
-    ['invalid', true, 'dangerStyle'],
-  ])('should handle status %s', (_, isInvalid, expectedStyle) => {
-    render(<InputField isInvalid={isInvalid} />);
+    ['default', false, false, 'defaultStyle'],
+    ['invalid', true, false, 'dangerStyle'],
+    ['valid', false, true, 'successStyle'],
+  ])('should handle status %s', (_, isInvalid, isValid, expectedStyle) => {
+    render(<InputField isInvalid={isInvalid} isValid={isValid} />);
 
     // Emotion classes contain pseudo-random parts, we're interesting in the fixed part
     // so we can't just check a specific class
index 6505f36e23593e3fd7d6e61c70c6219f98c825a4..481711667b96c8421b31b5d39eb5542eec41d531 100644 (file)
@@ -248,6 +248,7 @@ export default function ProjectValidation<I>(props: Readonly<Props<I>>) {
             value={name}
             autoFocus
             isInvalid={projectNameIsInvalid}
+            isValid={projectNameIsValid}
             required
           />
           {projectNameIsInvalid && <FlagErrorIcon className="sw-ml-2" />}
@@ -277,6 +278,7 @@ export default function ProjectValidation<I>(props: Readonly<Props<I>>) {
             type="text"
             value={key}
             isInvalid={projectKeyIsInvalid}
+            isValid={projectKeyIsValid}
             required
           />
           {projectKeyIsInvalid && <FlagErrorIcon className="sw-ml-2" />}
index a174902cec5bc8daed32a90a3c7de419810febbd..bc7a765f7413d172ed4da1c3818ea358a165ec17 100644 (file)
@@ -185,6 +185,7 @@ export default function ManualProjectCreate(props: Readonly<Props>) {
                 type="text"
                 value={mainBranchName}
                 isInvalid={mainBranchNameIsInvalid}
+                isValid={mainBranchNameIsValid}
                 required
               />
               {mainBranchNameIsInvalid && <FlagErrorIcon className="sw-ml-2" />}
index 5c439b81d833f3048523df2ae2ee83d7ea73553f..7d20cbb1b824474adac7adb507290ae8944dc518 100644 (file)
@@ -85,6 +85,7 @@ export default function UpdateForm(props: UpdateFormProps) {
               name="update_key.new_key"
               required
               isInvalid={hasChanged && error !== undefined}
+              isValid={hasChanged && error === undefined}
               autoFocus
               onChange={onInputChange}
               value={newKey}
index 301ede63c7f8b66b2111984bd8d94c1622a2172b..31360afa2add38e8e7097852b11c220160977ecc 100644 (file)
@@ -185,6 +185,7 @@ export default class BranchNewCodeDefinitionSettingModal extends React.PureCompo
             />
             <NewCodeDefinitionDaysOption
               days={days}
+              isChanged={isChanged}
               isValid={isValid}
               onChangeDays={this.handleSelectDays}
               onSelect={this.handleSelectSetting}
index 6e6d6252f41b750d1dae002fb3d129134cc0fc82..23d3d156c94f9e6248c5a599db3e1cf426301890 100644 (file)
@@ -139,6 +139,7 @@ export default function ProjectNewCodeDefinitionSelector(
           }
           days={days}
           disabled={!overrideGlobalNewCodeDefinition}
+          isChanged={isChanged}
           isValid={isValid}
           onChangeDays={props.onSelectDays}
           onSelect={props.onSelectSetting}
index ddd07fb4086e63749583d09fdc7ee086306e98ef..6810c2a12639a34916e525e642db413924c01996 100644 (file)
@@ -138,6 +138,7 @@ export default function NewCodeDefinition() {
                         previousNonCompliantValue={newCodeDefinition?.previousNonCompliantValue}
                         projectKey={newCodeDefinition?.projectKey}
                         updatedAt={newCodeDefinition?.updatedAt}
+                        isChanged={isFormTouched}
                         isValid={isValid}
                         onChangeDays={setNumberOfDays}
                         onSelect={setSelectedNewCodeDefinitionType}
index 2e8c807a6cb9640c6c354704586600e73d73cc4e..6f8dbc6d68af50784c3855f69982cf60be23c3e0 100644 (file)
@@ -185,6 +185,7 @@ export default function UserForm(props: Props) {
                     !doesLoginHaveValidCharacter ||
                     !doesLoginStartWithLetterOrNumber
                   }
+                  isValid={!isLoginAlreadyUsed && login.length >= MINIMUM_LOGIN_LENGTH}
                   maxLength={MAXIMUM_LOGIN_LENGTH}
                   minLength={MINIMUM_LOGIN_LENGTH}
                   size="full"
@@ -241,6 +242,7 @@ export default function UserForm(props: Props) {
           >
             <div className="sw-flex sw-items-center">
               <InputField
+                isValid={isCreateUserForm ? nameIsValid : undefined}
                 isInvalid={nameIsInvalid}
                 autoFocus={!!user}
                 autoComplete="off"
index ef63d66d8d05d5e79f00f92371c96e753871a36f..54b4c96782dd551efaff4a8feab30f416ed939c7 100644 (file)
@@ -51,6 +51,7 @@ export default function EmailIput(props: Readonly<Props>) {
         <InputField
           id={id}
           isInvalid={isEmailValid === false}
+          isValid={isEmailValid === true}
           size="full"
           onChange={({ currentTarget }) => {
             const isValid = isMandotory
index e4ecbe830b72f1c3af1e9d54d88e976e5e71b094..98ccd7077cb108e3833e0cda380f901a42acaf60 100644 (file)
@@ -57,6 +57,7 @@ export default function UserPasswordInput(props: Readonly<Props>) {
           <div className="sw-flex sw-items-center">
             <InputField
               isInvalid={isInvalid}
+              isValid={isValid}
               onFocus={() => setIsFocused(true)}
               id="create-password"
               size={size}
@@ -92,6 +93,7 @@ export default function UserPasswordInput(props: Readonly<Props>) {
         <div className="sw-flex sw-items-center">
           <InputField
             isInvalid={passwordDontMatch}
+            isValid={passwordMatch}
             onFocus={() => setIsFocused(true)}
             id="confirm-password"
             size={size}
index 9b9bd6ca4125d5c2f7ef35f7fb832e7afa5bc863..de41934095f2f1a273b55b6fc6525075c76389ac 100644 (file)
@@ -45,7 +45,9 @@ export default function InputValidationField({ ...props }: Readonly<Props>) {
   const modalValidationProps = { description, dirty, error, label, touched, required };
   return (
     <ModalValidationField id={props.id} {...modalValidationProps}>
-      {({ isInvalid }) => <InputField size="full" isInvalid={isInvalid} {...inputProps} />}
+      {({ isInvalid, isValid }) => (
+        <InputField size="full" isInvalid={isInvalid} isValid={isValid} {...inputProps} />
+      )}
     </ModalValidationField>
   );
 }
index 4a4629cc763f1a6bd4477bb19cc2e0b74f0d7681..f49479708dfc9ddcc42b09190ae05c1be3389d8b 100644 (file)
@@ -46,6 +46,7 @@ export interface Props {
   currentDaysValue?: string;
   days: string;
   disabled?: boolean;
+  isChanged: boolean;
   isValid: boolean;
   onChangeDays: (value: string) => void;
   onSelect: (selection: NewCodeDefinitionType) => void;
@@ -65,6 +66,7 @@ export default function NewCodeDefinitionDaysOption(props: Props) {
     projectKey,
     updatedAt,
     disabled,
+    isChanged,
     isValid,
     onChangeDays,
     onSelect,
@@ -131,6 +133,7 @@ export default function NewCodeDefinitionDaysOption(props: Props) {
                 <InputField
                   id="baseline_number_of_days"
                   isInvalid={!isValid}
+                  isValid={isChanged && isValid}
                   max={NUMBER_OF_DAYS_MAX_VALUE}
                   min={NUMBER_OF_DAYS_MIN_VALUE}
                   onChange={(e) => onChangeDays(e.currentTarget.value)}
index bf09cda52eb85b4d8711799f0ff87ed954369ddc..535803665c5dc63c93067c263c28506d0ea29131 100644 (file)
@@ -54,6 +54,7 @@ export default function NewCodeDefinitionSelector(props: Props) {
   const [globalNcd, setGlobalNcd] = React.useState<NewCodeDefinition | null>(null);
   const [selectedNcdType, setSelectedNcdType] = React.useState<NewCodeDefinitionType | null>(null);
   const [days, setDays] = React.useState<string>('');
+  const [isChanged, setIsChanged] = React.useState<boolean>(false);
 
   React.useEffect(() => {
     const numberOfDays = getNumberOfDaysDefaultValue(globalNcd);
@@ -74,6 +75,7 @@ export default function NewCodeDefinitionSelector(props: Props) {
     (newNcdType: NewCodeDefinitionType) => {
       if (newNcdType && newNcdType !== selectedNcdType) {
         setSelectedNcdType(newNcdType);
+        setIsChanged(true);
       }
     },
     [selectedNcdType],
@@ -155,6 +157,7 @@ export default function NewCodeDefinitionSelector(props: Props) {
           disabled={Boolean(
             !selectedNcdType || selectedNcdType === NewCodeDefinitionType.Inherited,
           )}
+          isChanged={isChanged}
           isValid={isCompliant}
           onChangeDays={setDays}
           onSelect={handleNcdChanged}