Repository: reportportal/service-ui
Pull request #4280: implement create product version modal and version list content
Author: login: OleksandrDragun
Created: 2025-03-24T19:37:47Z | Merged: 2025-03-31T10:46:14Z

## PR Checklist

* [x] Have you verified that the PR is pointing to the correct target branch? (`develop` for features/bugfixes, other if mentioned in the task)
* [x] Have you verified that your branch is consistent with the target branch and has no conflicts? (if not, make a rebase under the target branch)
* [x] Have you checked that everything works within the branch according to the task description and tested it locally?
* [x] Have you run the linter (`npm run lint`) prior to submission? Enable the git hook on commit in your IDE to run it and format the code automatically.
* [ ] Have you run the tests locally and added/updated them if needed?
* [ ] Have you checked that app can be built (`npm run build`)?
* [ ] Have you checked that no new circular dependencies appreared with your changes? (the webpack plugin reports circular dependencies within the `dev` npm script)
* [ ] Have you made sure that all the necessary pipelines has been successfully completed?
* [ ] If the task requires translations to be updated, have you done this by running the `manage:translations` script?

## Visuals

Modal
![image](https://github.com/user-attachments/assets/f8b5db13-80bf-4821-999f-32776b7dfd03)

List
![image](https://github.com/user-attachments/assets/a1c5f6af-3fe7-4b3c-b741-009372a2e301)




Diff:
diff --git a/app/package-lock.json b/app/package-lock.json
index f61c6d8565..0eb086728a 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -34,6 +34,7 @@
         "html-react-parser": "^5.2.2",
         "intl": "1.2.5",
         "intl-locales-supported": "1.8.4",
+        "lodash.isempty": "^4.4.0",
         "marked": "0.7.0",
         "marked-lts": "npm:marked@5.1.1",
         "mime-types": "2.1.35",
@@ -4883,7 +4884,7 @@
       "version": "22.0.0",
       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz",
       "integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==",
-      "dev": true,
+      "devOptional": true,
       "dependencies": {
         "undici-types": "~6.11.1"
       }
@@ -16862,6 +16863,11 @@
       "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
       "dev": true
     },
+    "node_modules/lodash.isempty": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+      "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg=="
+    },
     "node_modules/lodash.isequal": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
@@ -25508,7 +25514,7 @@
       "version": "6.11.1",
       "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz",
       "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==",
-      "dev": true
+      "devOptional": true
     },
     "node_modules/unicode-canonical-property-names-ecmascript": {
       "version": "2.0.1",
diff --git a/app/package.json b/app/package.json
index 88e03b5e01..308b44a80e 100644
--- a/app/package.json
+++ b/app/package.json
@@ -47,6 +47,7 @@
     "html-react-parser": "^5.2.2",
     "intl": "1.2.5",
     "intl-locales-supported": "1.8.4",
+    "lodash.isempty": "^4.4.0",
     "marked": "0.7.0",
     "marked-lts": "npm:marked@5.1.1",
     "mime-types": "2.1.35",
diff --git a/app/src/common/utils/validation/commonValidators.js b/app/src/common/utils/validation/commonValidators.js
index f4aa0b2de8..6bd29d65a6 100644
--- a/app/src/common/utils/validation/commonValidators.js
+++ b/app/src/common/utils/validation/commonValidators.js
@@ -88,3 +88,9 @@ export const createDescriptionValidator = bindMessageToValidator(
 
 export const createKeywordMatcherValidator = (keyword) =>
   bindMessageToValidator(validate.keywordMatcher(keyword), 'keywordMatcherHint');
+
+export const createProjectVersionValidator = () =>
+  composeBoundValidators([
+    commonValidators.requiredField,
+    bindMessageToValidator(validate.projectVersionLength, 'projectVersionLengthHint'),
+  ]);
diff --git a/app/src/common/utils/validation/validate.js b/app/src/common/utils/validation/validate.js
index 347e4c332d..4f05a9dc23 100644
--- a/app/src/common/utils/validation/validate.js
+++ b/app/src/common/utils/validation/validate.js
@@ -56,6 +56,7 @@ export const defectTypeLongName = composeValidators([isNotEmpty, lengthRange(3,
 export const defectTypeShortName = composeValidators([isNotEmpty, maxLength(4)]);
 export const projectNamePattern = composeValidators([isNotEmpty, regex(/^[0-9a-zA-Z-_. ]+$/)]);
 export const projectNameLength = composeValidators([isNotEmpty, lengthRange(3, 60)]);
+export const projectVersionLength = composeValidators([isNotEmpty, maxLength(60)]);
 export const btsIntegrationName = composeValidators([isNotEmpty, maxLength(55)]);
 export const btsProject = composeValidators([isNotEmpty, maxLength(55)]);
 export const btsUserName = composeValidators([isNotEmpty, maxLength(55)]);
diff --git a/app/src/components/fields/fieldErrorHint/fieldErrorHint.jsx b/app/src/components/fields/fieldErrorHint/fieldErrorHint.jsx
index 104bf7ef76..863c3b7f95 100644
--- a/app/src/components/fields/fieldErrorHint/fieldErrorHint.jsx
+++ b/app/src/components/fields/fieldErrorHint/fieldErrorHint.jsx
@@ -268,6 +268,10 @@ const messages = defineMessages({
     id: 'DeleteProjectModal.keywordMatcherHint',
     defaultMessage: 'The entered text does not match the required keyword',
   },
+  projectVersionLengthHint: {
+    id: 'ListOfVersionsPage.projectVersionLengthHint',
+    defaultMessage: 'Name must not exceed 60 characters',
+  },
 });
 
 @injectIntl
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent/LinkComponent.jsx b/app/src/pages/inside/common/LinkComponent/LinkComponent.jsx
similarity index 100%
rename from app/src/pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent/LinkComponent.jsx
rename to app/src/pages/inside/common/LinkComponent/LinkComponent.jsx
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent/LinkComponent.scss b/app/src/pages/inside/common/LinkComponent/LinkComponent.scss
similarity index 100%
rename from app/src/pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent/LinkComponent.scss
rename to app/src/pages/inside/common/LinkComponent/LinkComponent.scss
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent/index.js b/app/src/pages/inside/common/LinkComponent/index.js
similarity index 100%
rename from app/src/pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent/index.js
rename to app/src/pages/inside/common/LinkComponent/index.js
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/helpPanel/helpPanel.jsx b/app/src/pages/inside/common/helpPanel/helpPanel.jsx
similarity index 100%
rename from app/src/pages/inside/projectSettingsPageContainer/content/notifications/helpPanel/helpPanel.jsx
rename to app/src/pages/inside/common/helpPanel/helpPanel.jsx
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/helpPanel/helpPanel.scss b/app/src/pages/inside/common/helpPanel/helpPanel.scss
similarity index 100%
rename from app/src/pages/inside/projectSettingsPageContainer/content/notifications/helpPanel/helpPanel.scss
rename to app/src/pages/inside/common/helpPanel/helpPanel.scss
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/helpPanel/index.js b/app/src/pages/inside/common/helpPanel/index.js
similarity index 100%
rename from app/src/pages/inside/projectSettingsPageContainer/content/notifications/helpPanel/index.js
rename to app/src/pages/inside/common/helpPanel/index.js
diff --git a/app/src/pages/inside/common/utils.js b/app/src/pages/inside/common/utils.js
index 54a803e97d..4517c33c2a 100644
--- a/app/src/pages/inside/common/utils.js
+++ b/app/src/pages/inside/common/utils.js
@@ -186,3 +186,7 @@ export const getGroupedDefectTypesOptions = (
 
   return defectTypesOptions;
 };
+
+export const isInternalLink = (to) => {
+  return typeof to === 'object' && to.type;
+};
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/content/content.jsx b/app/src/pages/inside/productVersionsPage/listOfVersions/content/content.jsx
new file mode 100644
index 0000000000..b63793ccd6
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/content/content.jsx
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import classNames from 'classnames/bind';
+import { useIntl } from 'react-intl';
+import PropTypes from 'prop-types';
+import { ChevronDownDropdownIcon } from '@reportportal/ui-kit';
+
+import { HelpPanel } from 'pages/inside/common/helpPanel';
+import discoverPluginsIcon from 'common/img/discover-icon-inline.svg';
+import openInNewTabIcon from 'common/img/open-in-new-tab-inline.svg';
+
+import styles from './content.scss';
+import { messages } from './messages';
+
+const cx = classNames.bind(styles);
+
+export const Content = ({ versions }) => {
+  const { formatMessage, formatDate } = useIntl();
+
+  const infoItems = [
+    {
+      title: formatMessage(messages.productVersionWorkTitle),
+      mainIcon: discoverPluginsIcon,
+      description: formatMessage(messages.productVersionWorkDescription),
+      openIcon: openInNewTabIcon,
+      automationId: 'productVersionWorkLink',
+      link: 'https://reportportal.io/docs/',
+    },
+    {
+      title: formatMessage(messages.manageProductVersionsTitle),
+      mainIcon: discoverPluginsIcon,
+      description: formatMessage(messages.manageProductVersionsDescription),
+      openIcon: openInNewTabIcon,
+      automationId: 'manageProductVersionLink',
+      link: 'https://reportportal.io/docs/',
+    },
+    {
+      title: formatMessage(messages.linkToTestCaseVersionTitle),
+      mainIcon: discoverPluginsIcon,
+      description: formatMessage(messages.linkToTestCaseVersionDescription),
+      openIcon: openInNewTabIcon,
+      automationId: 'testCaseVersionLink',
+      link: 'https://reportportal.io/docs/',
+    },
+  ];
+
+  return (
+    <>
+      <div className={cx('content-list')}>
+        {versions.map(({ productVersion, timestamp }) => (
+          <div className={cx('content-list__item')} key={productVersion}>
+            <div className={cx('content-list__item-title')}>{productVersion}</div>
+            <div className={cx('content-list__item-timestamp')}>
+              {formatMessage(messages.lastUpdatedDate, {
+                date: formatDate(timestamp, {
+                  year: 'numeric',
+                  month: 'long',
+                  day: '2-digit',
+                }),
+              })}
+            </div>
+            <ChevronDownDropdownIcon />
+          </div>
+        ))}
+      </div>
+      <HelpPanel items={infoItems} />
+    </>
+  );
+};
+
+Content.propTypes = {
+  versions: PropTypes.arrayOf(
+    PropTypes.shape({
+      productVersion: PropTypes.string,
+      timestamp: PropTypes.object,
+    }),
+  ).isRequired,
+};
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/content/content.scss b/app/src/pages/inside/productVersionsPage/listOfVersions/content/content.scss
new file mode 100644
index 0000000000..5e22017245
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/content/content.scss
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.content-list {
+  &__item {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    width: 820px;
+    height: 104px;
+    margin-bottom: 16px;
+    padding: 24px;
+    box-sizing: border-box;
+    cursor: pointer;
+    background-color: var(--rp-ui-base-bg-000);
+    border-radius: 8px;
+    box-shadow: var(--rp-ui-base-shadow);
+
+    &:last-child {
+      margin-bottom: 24px;
+    }
+
+    &:hover {
+      box-shadow: var(--rp-ui-base-shadow-hover);
+    }
+
+    &-title {
+      font-family: $FONT-REGULAR;
+      font-size: 20px;
+      line-height: 31px;
+      letter-spacing: 0;
+      color: var(--rp-ui-base-almost-black);
+    }
+
+    &-timestamp {
+      font-family: $FONT-ROBOTO-REGULAR;
+      font-size: 11px;
+      line-height: 16px;
+      letter-spacing: 0;
+      color: var(--rp-ui-base-e-400);
+    }
+
+    svg {
+      position: absolute;
+      top: 47px;
+      right: 24px;
+      transform: rotate(-90deg);
+    }
+  }
+}
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/content/index.js b/app/src/pages/inside/productVersionsPage/listOfVersions/content/index.js
new file mode 100644
index 0000000000..f5d07ad864
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/content/index.js
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { Content } from './content';
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/content/messages.js b/app/src/pages/inside/productVersionsPage/listOfVersions/content/messages.js
new file mode 100644
index 0000000000..00ea7937ff
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/content/messages.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  productVersionWorkTitle: {
+    id: 'VersionsList.productVersionWorkTitle',
+    defaultMessage: 'How does Product version work?',
+  },
+  productVersionWorkDescription: {
+    id: 'VersionsList.productVersionWorkDescription',
+    defaultMessage: 'Explore the functionality and benefits of Product versions',
+  },
+  manageProductVersionsTitle: {
+    id: 'VersionsList.manageProductVersionsTitle',
+    defaultMessage: 'How to manage Product versions?',
+  },
+  manageProductVersionsDescription: {
+    id: 'VersionsList.manageProductVersionsDescription',
+    defaultMessage: 'Learn effective strategies for managing your Product versions',
+  },
+  linkToTestCaseVersionTitle: {
+    id: 'VersionsList.linkToTestCaseVersionTitle',
+    defaultMessage: 'How to link to test case version?',
+  },
+  linkToTestCaseVersionDescription: {
+    id: 'VersionsList.linkToTestCaseVersionDescription',
+    defaultMessage: 'Understand the steps to link a test to a Product version',
+  },
+  lastUpdatedDate: {
+    id: 'VersionsList.lastUpdatedDate',
+    defaultMessage: 'Last updated: {date}',
+  },
+});
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx b/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
new file mode 100644
index 0000000000..f801958b46
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
+  reduxForm({
+    form: 'createProductVersionForm',
+    validate: ({ productVersion }) => ({
+      productVersion: commonValidators.createProjectVersionValidator()(productVersion),
+    }),
+  })(CreateProductVersionModal),
+);
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/index.js b/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/index.js
new file mode 100644
index 0000000000..188001b232
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/index.js
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { CREATE_PRODUCT_VERSION_MODAL_KEY } from './createProductVersionModal';
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/messages.js b/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/messages.js
new file mode 100644
index 0000000000..1ef82cfa8d
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/messages.js
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  title: {
+    id: 'CreateProductVersionModal.title',
+    defaultMessage: 'Create product version',
+  },
+  name: {
+    id: 'CreateProductVersionModal.name',
+    defaultMessage: 'Name',
+  },
+  namePlaceholder: {
+    id: 'CreateProductVersionModal.namePlaceholder',
+    defaultMessage: 'Enter product version’s name ',
+  },
+});
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/emptyState.jsx b/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/emptyState.jsx
new file mode 100644
index 0000000000..56f77f2b7e
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/emptyState.jsx
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from 'react';
+import Parser from 'html-react-parser';
+import { useIntl } from 'react-intl';
+import PropTypes from 'prop-types';
+
+import { NumerableBlock } from 'pages/common/numerableBlock';
+import PlusIcon from 'common/img/plus-button-inline.svg';
+import { EmptyStatePage } from 'pages/inside/projectSettingsPageContainer/content/emptyStatePage';
+
+import { messages as parentMessage } from '../../messages';
+import { messages } from './messages';
+
+export const EmptyState = ({ openCreateProductVersionModal }) => {
+  const { formatMessage } = useIntl();
+
+  const benefits = [
+    messages.stayOrganizedBenefit,
+    messages.beUpToDateBenefit,
+    messages.enhanceTrackingBenefit,
+  ].map((translation) =>
+    formatMessage(translation, {
+      strong: (chunks) => <strong>{chunks}</strong>,
+    }),
+  );
+
+  return (
+    <>
+      <EmptyStatePage
+        title={formatMessage(messages.emptyPageTitle)}
+        description={Parser(formatMessage(messages.emptyPageDescription))}
+        buttonName={formatMessage(parentMessage.addProductVersionButtonText)}
+        buttonIcon={PlusIcon}
+        imageType="branches"
+        buttonDataAutomationId="addProductVersionButton"
+        handleButton={openCreateProductVersionModal}
+      />
+      <NumerableBlock
+        items={benefits}
+        title={formatMessage(messages.numerableBlockTitle)}
+        fullWidth
+      />
+    </>
+  );
+};
+
+EmptyState.propTypes = {
+  openCreateProductVersionModal: PropTypes.func.isRequired,
+};
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/index.js b/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/index.js
new file mode 100644
index 0000000000..6ad80e255d
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/index.js
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export { EmptyState } from './emptyState';
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/messages.js b/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/messages.js
new file mode 100644
index 0000000000..26284861e0
--- /dev/null
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/messages.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  emptyPageTitle: {
+    id: 'ListOfVersionsPage.emptyTitle',
+    defaultMessage: 'No Product versions yet',
+  },
+  emptyPageDescription: {
+    id: 'ListOfVersionsPage.emptyDescription',
+    defaultMessage:
+      'Add your first Product version to let you effectively manage and track the Launches on each version of your product',
+  },
+  numerableBlockTitle: {
+    id: 'ListOfVersionsPage.numerableBlock.title',
+    defaultMessage: 'Why is it beneficial?',
+  },
+  stayOrganizedBenefit: {
+    id: 'ListOfVersionsPage.stayOrganizedBenefit',
+    defaultMessage:
+      '<strong>Stay Organized:</strong> Product versions help organize your tests and manage their settings in one place, ensuring efficiency and saving time',
+  },
+  beUpToDateBenefit: {
+    id: 'ListOfVersionsPage.beUpToDateBenefit',
+    defaultMessage:
+      '<strong>Be Up-to-Date:</strong> Mark tests as default to use the latest version for the next run. Stay updated without any extra hassle.',
+  },
+  enhanceTrackingBenefit: {
+    id: 'ListOfVersionsPage.enhanceTrackingBenefit',
+    defaultMessage:
+      '<strong>Enhance Tracking:</strong> Understand the evolution of your product by comparing tests across different versions. This will boost your product analysis.',
+  },
+});
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.jsx b/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.jsx
index 6f745c8ea3..3baf59cd0a 100644
--- a/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.jsx
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.jsx
@@ -16,47 +16,30 @@
 
 import React from 'react';
 import classNames from 'classnames/bind';
-import Parser from 'html-react-parser';
-import { useIntl } from 'react-intl';
-
-import { NumerableBlock } from 'pages/common/numerableBlock';
-import PlusIcon from 'common/img/plus-button-inline.svg';
-
-import { EmptyStatePage } from '../../projectSettingsPageContainer/content/emptyStatePage';
-import { messages } from './messages';
+import PropTypes from 'prop-types';
+import isEmpty from 'lodash.isempty';
 
 import styles from './listOfVersions.scss';
+import { EmptyState } from './emptyState';
+import { Content } from './content';
 
 const cx = classNames.bind(styles);
 
-export const ListOfVersions = () => {
-  const { formatMessage } = useIntl();
-
-  const benefits = [
-    messages.emptyPageFirstBenefit,
-    messages.emptyPageSecondBenefit,
-    messages.emptyPageThirdBenefit,
-  ].map((translation) =>
-    formatMessage(translation, {
-      strong: (chunks) => <strong>{chunks}</strong>,
-    }),
-  );
-
-  return (
-    <div className={cx('list-of-versions')}>
-      <EmptyStatePage
-        title={formatMessage(messages.emptyPageTitle)}
-        description={Parser(formatMessage(messages.emptyPageDescription))}
-        buttonName={formatMessage(messages.emptyPageButtonText)}
-        buttonIcon={PlusIcon}
-        imageType="branches"
-        buttonDataAutomationId="addProductVersionButton"
-      />
-      <NumerableBlock
-        items={benefits}
-        title={formatMessage(messages.numerableBlockTitle)}
-        fullWidth
-      />
-    </div>
-  );
+export const ListOfVersions = ({ openCreateProductVersionModal, versions }) => (
+  <div
+    className={cx('list-of-versions', {
+      'list-of-versions--empty': isEmpty(versions),
+    })}
+  >
+    {isEmpty(versions) ? (
+      <EmptyState openCreateProductVersionModal={openCreateProductVersionModal} />
+    ) : (
+      <Content versions={versions} />
+    )}
+  </div>
+);
+
+ListOfVersions.propTypes = {
+  openCreateProductVersionModal: PropTypes.func.isRequired,
+  versions: PropTypes.array,
 };
diff --git a/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.scss b/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.scss
index 7ecfc8bbd6..1b170d95b0 100644
--- a/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.scss
+++ b/app/src/pages/inside/productVersionsPage/listOfVersions/listOfVersions.scss
@@ -17,7 +17,10 @@
 .list-of-versions {
   display: flex;
   flex-direction: column;
-  gap: 80px;
   justify-content: center;
   align-items: center;
+
+  &--empty {
+    gap: 80px;
+  }
 }
diff --git a/app/src/pages/inside/productVersionsPage/messages.js b/app/src/pages/inside/productVersionsPage/messages.js
index 16de098686..3707955c93 100644
--- a/app/src/pages/inside/productVersionsPage/messages.js
+++ b/app/src/pages/inside/productVersionsPage/messages.js
@@ -29,4 +29,8 @@ export const messages = defineMessages({
     id: 'ProductVersionsPage.generalDocumentation',
     defaultMessage: 'General documentation',
   },
+  addProductVersionButtonText: {
+    id: 'ProductVersionsPage.addProductVersionButtonText',
+    defaultMessage: 'Add Product version',
+  },
 });
diff --git a/app/src/pages/inside/productVersionsPage/productVersionsPage.jsx b/app/src/pages/inside/productVersionsPage/productVersionsPage.jsx
index 3ef5ab9cff..0a647bfc95 100644
--- a/app/src/pages/inside/productVersionsPage/productVersionsPage.jsx
+++ b/app/src/pages/inside/productVersionsPage/productVersionsPage.jsx
@@ -18,6 +18,10 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import { useIntl } from 'react-intl';
 import classNames from 'classnames/bind';
+import Parser from 'html-react-parser';
+import isEmpty from 'lodash.isempty';
+import { Button } from '@reportportal/ui-kit';
+
 import {
   payloadSelector,
   PRODUCT_VERSIONS_TAB_PAGE,
@@ -29,10 +33,14 @@ import { Header } from 'pages/inside/projectSettingsPageContainer/header';
 import { ScrollWrapper } from 'components/main/scrollWrapper';
 import { SettingsLayout } from 'layouts/settingsLayout';
 import { MarkdownEditor } from 'components/main/markdown';
-import { ListOfVersions } from './listOfVersions';
-import { LIST_OF_VERSIONS, GENERAL_DOCUMENTATION } from './constants';
-import { messages } from './messages';
+import { hideModalAction, showModalAction } from 'controllers/modal';
+import { CREATE_PRODUCT_VERSION_MODAL_KEY } from 'pages/inside/productVersionsPage/listOfVersions/createProductVersionModal';
+import PlusIcon from 'common/img/plus-button-inline.svg';
+
 import styles from './productVersionsPage.scss';
+import { messages } from './messages';
+import { LIST_OF_VERSIONS, GENERAL_DOCUMENTATION } from './constants';
+import { ListOfVersions } from './listOfVersions';
 
 const cx = classNames.bind(styles);
 
@@ -40,7 +48,7 @@ export const ProductVersionsPage = () => {
   const { formatMessage } = useIntl();
   const dispatch = useDispatch();
   const { organizationSlug, projectSlug } = useSelector(urlOrganizationAndProjectSelector);
-  const [headerNodes, setHeaderNodes] = useState({});
+  const [versions, setVersions] = useState([]);
   const { subPage: activeSubPage } = useSelector(payloadSelector);
   const { subPage } = useSelector(querySelector);
 
@@ -56,12 +64,33 @@ export const ProductVersionsPage = () => {
     [organizationSlug, projectSlug],
   );
 
+  const handleModalSubmit = (data) => {
+    setVersions((prevState) => [...prevState, { ...data, timestamp: new Date() }]);
+    dispatch(hideModalAction());
+  };
+
+  const openCreateProductVersionModal = () => {
+    dispatch(
+      showModalAction({
+        id: CREATE_PRODUCT_VERSION_MODAL_KEY,
+        data: {
+          onSubmit: handleModalSubmit,
+        },
+      }),
+    );
+  };
+
   const tabsConfig = useMemo(
     () => ({
       [LIST_OF_VERSIONS]: {
         name: formatMessage(messages.listOfVersions),
         link: createTabLink(LIST_OF_VERSIONS),
-        component: <ListOfVersions />,
+        component: (
+          <ListOfVersions
+            versions={versions}
+            openCreateProductVersionModal={openCreateProductVersionModal}
+          />
+        ),
       },
       [GENERAL_DOCUMENTATION]: {
         name: formatMessage(messages.generalDocumentation),
@@ -69,25 +98,15 @@ export const ProductVersionsPage = () => {
         component: <MarkdownEditor placeholder="Simple example" />,
       },
     }),
-    [createTabLink],
+    [createTabLink, versions],
   );
 
   useEffect(() => {
-    setHeaderNodes({
-      children: (
-        <div className={cx('product-versions-page__tabs')}>
-          <Tabs config={tabsConfig} activeTab={activeSubPage} withContent={false} />
-        </div>
-      ),
-    });
-
     if (!activeSubPage || !tabsConfig[activeSubPage]) {
       const firstTabConfigKey = Object.keys(tabsConfig)[0];
       dispatch(tabsConfig[firstTabConfigKey].link);
     }
-
-    return () => setHeaderNodes(null);
-  }, [activeSubPage]);
+  }, [activeSubPage, versions]);
 
   return (
     <SettingsLayout>
@@ -95,11 +114,23 @@ export const ProductVersionsPage = () => {
         <div className={cx('product-versions-page')}>
           {!subPage && (
             <div className={cx('product-versions-page__header')}>
-              <Header
-                title={formatMessage(messages.productVersions)}
-                titleNode={headerNodes.titleNode}
-              >
-                {headerNodes.children}
+              <Header title={formatMessage(messages.productVersions)}>
+                <div className={cx('product-versions-page__navigation-panel')}>
+                  <div className={cx('product-versions-page__tabs')}>
+                    <Tabs config={tabsConfig} activeTab={activeSubPage} withContent={false} />
+                  </div>
+                  {!isEmpty(versions) && (
+                    <Button
+                      adjustWidthOn={'wide-content'}
+                      onClick={openCreateProductVersionModal}
+                      data-automation-id="addProductVersionButton"
+                      icon={Parser(PlusIcon)}
+                      className={cx('product-versions-page__button')}
+                    >
+                      {formatMessage(messages.addProductVersionButtonText)}
+                    </Button>
+                  )}
+                </div>
               </Header>
             </div>
           )}
diff --git a/app/src/pages/inside/productVersionsPage/productVersionsPage.scss b/app/src/pages/inside/productVersionsPage/productVersionsPage.scss
index e1086e35cb..105b7a9089 100644
--- a/app/src/pages/inside/productVersionsPage/productVersionsPage.scss
+++ b/app/src/pages/inside/productVersionsPage/productVersionsPage.scss
@@ -25,10 +25,20 @@
     z-index: $Z-INDEX-PAGE-CONTAINER-HEADER;
   }
 
+  &__navigation-panel {
+    position: relative;
+  }
+
   &__tabs {
     min-height: 32px;
   }
 
+  &__button {
+    position: absolute;
+    bottom: 14px;
+    right: 0;
+  }
+
   &__content {
     display: flex;
     flex-direction: column;
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/footer/footer.jsx b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/footer/footer.jsx
index 27f44f657b..6f183158ee 100644
--- a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/footer/footer.jsx
+++ b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/footer/footer.jsx
@@ -30,9 +30,9 @@ import { activeProjectSelector } from 'controllers/user';
 import { docsReferences } from 'common/utils';
 import { PROJECT_SETTINGS_NOTIFICATIONS_EVENTS } from 'components/main/analytics/events/ga4Events/projectSettingsPageEvents';
 import PropTypes from 'prop-types';
+import { HelpPanel } from 'pages/inside/common/helpPanel';
 import { messages } from '../messages';
 import styles from './footer.scss';
-import { HelpPanel } from '../helpPanel';
 
 const cx = classNames.bind(styles);
 
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/ruleGroup/ruleGroup.jsx b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/ruleGroup/ruleGroup.jsx
index 53a53b66d7..a92fb07304 100644
--- a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/ruleGroup/ruleGroup.jsx
+++ b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/ruleGroup/ruleGroup.jsx
@@ -42,7 +42,7 @@ import { withTooltip } from 'components/main/tooltips/tooltip';
 import { TextTooltip } from 'components/main/tooltips/textTooltip';
 import { PROJECT_SETTINGS_TAB_PAGE, userRolesSelector } from 'controllers/pages';
 import { INTEGRATIONS } from 'common/constants/settingsTabs';
-import { LinkComponent } from 'pages/inside/projectSettingsPageContainer/content/notifications/LinkComponent';
+import { LinkComponent } from 'pages/inside/common/LinkComponent';
 import arrowRightIcon from 'common/img/arrow-right-inline.svg';
 import { updateNotificationStateAction } from 'controllers/project/actionCreators';
 import { NOTIFICATIONS_PLUGIN_ATTRIBUTE_ENABLED_KEY } from 'controllers/project/constants';
diff --git a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/utils.js b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/utils.js
index db19980f2a..62a012c12b 100644
--- a/app/src/pages/inside/projectSettingsPageContainer/content/notifications/utils.js
+++ b/app/src/pages/inside/projectSettingsPageContainer/content/notifications/utils.js
@@ -48,10 +48,6 @@ export const convertNotificationCaseForSubmission = (obj) => {
   };
 };
 
-export const isInternalLink = (to) => {
-  return typeof to === 'object' && to.type;
-};
-
 export const flatRule = (notification) => {
   return { ...notification, ...notification?.ruleDetails };
 };


Reviews:
user: login: yelyzavetakhokhlova
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T12:31:28Z
user: login: ViktorSoroka07
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T12:37:15Z
user: login: ViktorSoroka07
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T12:37:59Z
user: login: ViktorSoroka07
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T12:42:57Z
user: login: ViktorSoroka07
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T12:50:15Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T12:51:45Z
user: login: yelyzavetakhokhlova
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T12:52:47Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T12:57:03Z
user: login: ViktorSoroka07
state: COMMENTED
author_association: NONE
submitted_at: 2025-03-28T15:37:15Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T19:58:48Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T19:59:01Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T19:59:12Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T19:59:22Z
user: login: OleksandrDragun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T20:00:04Z
user: login: ViktorSoroka07
state: APPROVED
author_association: NONE
submitted_at: 2025-03-31T10:02:31Z
user: login: yelyzavetakhokhlova
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T10:04:35Z

Review comments:
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: yelyzavetakhokhlova
body: ```suggestion
export const CreateProductVersionModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
```
created_at: 2025-03-28T12:29:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,50 @@
+.version-list {
+  &__item {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    width: 820px;
+    height: 104px;
+    margin-bottom: 16px;
+    padding: 24px;
+    box-sizing: border-box;
+    cursor: pointer;
+    background-color: var(--rp-ui-base-bg-000);
+    border-radius: 8px;
+    box-shadow: var(--rp-ui-base-shadow);
+
+    &:last-child {
+      margin-bottom: 24px;
+    }
+
+    &:hover {
+      box-shadow: var(--rp-ui-base-shadow-hover);
+    }
+
+    &-title {
+      font-family: $FONT-REGULAR;
+      font-weight: 400;
path: app/src/pages/inside/productVersionsPage/listOfVersions/versionList/versionList.scss
user: login: yelyzavetakhokhlova
body: please, remove font-weight
created_at: 2025-03-28T12:30:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  firstInfoTitle: {
path: app/src/pages/inside/productVersionsPage/listOfVersions/versionList/messages.js
user: login: ViktorSoroka07
body: Let's not specify the ordering in messages. Now it is first, tomorrow it is fifth. Check out other messages
created_at: 2025-03-28T12:37:15Z
author_association: NONE
diff_hunk: @@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  emptyPageTitle: {
+    id: 'ListOfVersionsPage.emptyTitle',
+    defaultMessage: 'No Product versions yet',
+  },
+  emptyPageDescription: {
+    id: 'ListOfVersionsPage.emptyDescription',
+    defaultMessage:
+      'Add your first Product version to let you effectively manage and track the Launches on each version of your product',
+  },
+  numerableBlockTitle: {
+    id: 'ListOfVersionsPage.numerableBlock.title',
+    defaultMessage: 'Why is it beneficial?',
+  },
+  emptyPageFirstBenefit: {
+    id: 'ListOfVersionsPage.emptyPageFirstBenefit',
+    defaultMessage:
+      '<strong>Stay Organized:</strong> Product versions help organize your tests and manage their settings in one place, ensuring efficiency and saving time',
+  },
+  emptyPageSecondBenefit: {
+    id: 'ListOfVersionsPage.emptyPageSecondBenefit',
+    defaultMessage:
+      '<strong>Be Up-to-Date:</strong> Mark tests as default to use the latest version for the next run. Stay updated without any extra hassle.',
+  },
+  emptyPageThirdBenefit: {
path: app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/messages.js
user: login: ViktorSoroka07
body: The same about ordering in messages
created_at: 2025-03-28T12:37:58Z
author_association: NONE
path: app/src/pages/inside/productVersionsPage/listOfVersions/versionList/versionList.scss
user: login: ViktorSoroka07
body: Let's move out everything from `versionList` folder outside of it and remove the folder and use naming `listOfVersions` for files & variables. Because now we have `listOfVersions/versionList` nesting - we give here two names for basically the same thing
created_at: 2025-03-28T12:42:57Z
author_association: NONE
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: ViktorSoroka07
body: Copy paste in action?)
created_at: 2025-03-28T12:50:15Z
author_association: NONE
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: OleksandrDragun
body: Absolutely :)
created_at: 2025-03-28T12:51:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: yelyzavetakhokhlova
body: i do the same 👌
created_at: 2025-03-28T12:52:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: OleksandrDragun
body: Common, everyone does it ))
created_at: 2025-03-28T12:57:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: ViktorSoroka07
body: Agree:)
created_at: 2025-03-28T15:37:15Z
author_association: NONE
diff_hunk: @@ -0,0 +1,73 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { useIntl } from 'react-intl';
+import { useDispatch } from 'react-redux';
+import PropTypes from 'prop-types';
+import { reduxForm } from 'redux-form';
+import { Modal, FieldText } from '@reportportal/ui-kit';
+import { COMMON_LOCALE_KEYS } from 'common/constants/localization';
+import { hideModalAction, withModal } from 'controllers/modal';
+import { FieldProvider } from 'components/fields';
+import { commonValidators } from 'common/utils/validation';
+import { FieldErrorHint } from 'components/fields/fieldErrorHint';
+
+import { messages } from './messages';
+
+export const CREATE_PRODUCT_VERSION_MODAL_KEY = 'createProductVersionModal';
+
+export const CreateProductVersionModal = ({ data: { onSubmit }, handleSubmit }) => {
+  const { formatMessage } = useIntl();
+  const dispatch = useDispatch();
+
+  const okButton = {
+    children: formatMessage(COMMON_LOCALE_KEYS.CREATE),
+    onClick: handleSubmit(onSubmit),
+  };
+
+  return (
+    <Modal
+      title={formatMessage(messages.title)}
+      okButton={okButton}
+      cancelButton={{ children: formatMessage(COMMON_LOCALE_KEYS.CANCEL) }}
+      onClose={() => dispatch(hideModalAction())}
+    >
+      <form>
+        <FieldProvider name="productVersion" placeholder={formatMessage(messages.namePlaceholder)}>
+          <FieldErrorHint provideHint={false}>
+            <FieldText label={formatMessage(messages.name)} defaultWidth={false} />
+          </FieldErrorHint>
+        </FieldProvider>
+      </form>
+    </Modal>
+  );
+};
+
+CreateProductVersionModal.propTypes = {
+  data: PropTypes.shape({
+    onSubmit: PropTypes.func.isRequired,
+  }),
+  handleSubmit: PropTypes.func.isRequired,
+};
+
+export const CreateDatasetModal = withModal(CREATE_PRODUCT_VERSION_MODAL_KEY)(
path: app/src/pages/inside/productVersionsPage/listOfVersions/createProductVersionModal/createProductVersionModal.jsx
user: login: OleksandrDragun
body: Corrected. Thanks.
created_at: 2025-03-28T19:58:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,50 @@
+.version-list {
+  &__item {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    width: 820px;
+    height: 104px;
+    margin-bottom: 16px;
+    padding: 24px;
+    box-sizing: border-box;
+    cursor: pointer;
+    background-color: var(--rp-ui-base-bg-000);
+    border-radius: 8px;
+    box-shadow: var(--rp-ui-base-shadow);
+
+    &:last-child {
+      margin-bottom: 24px;
+    }
+
+    &:hover {
+      box-shadow: var(--rp-ui-base-shadow-hover);
+    }
+
+    &-title {
+      font-family: $FONT-REGULAR;
+      font-weight: 400;
path: app/src/pages/inside/productVersionsPage/listOfVersions/versionList/versionList.scss
user: login: OleksandrDragun
body: Done.
created_at: 2025-03-28T19:59:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  firstInfoTitle: {
path: app/src/pages/inside/productVersionsPage/listOfVersions/versionList/messages.js
user: login: OleksandrDragun
body: Done.
created_at: 2025-03-28T19:59:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,48 @@
+/*
+ * Copyright 2025 EPAM Systems
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { defineMessages } from 'react-intl';
+
+export const messages = defineMessages({
+  emptyPageTitle: {
+    id: 'ListOfVersionsPage.emptyTitle',
+    defaultMessage: 'No Product versions yet',
+  },
+  emptyPageDescription: {
+    id: 'ListOfVersionsPage.emptyDescription',
+    defaultMessage:
+      'Add your first Product version to let you effectively manage and track the Launches on each version of your product',
+  },
+  numerableBlockTitle: {
+    id: 'ListOfVersionsPage.numerableBlock.title',
+    defaultMessage: 'Why is it beneficial?',
+  },
+  emptyPageFirstBenefit: {
+    id: 'ListOfVersionsPage.emptyPageFirstBenefit',
+    defaultMessage:
+      '<strong>Stay Organized:</strong> Product versions help organize your tests and manage their settings in one place, ensuring efficiency and saving time',
+  },
+  emptyPageSecondBenefit: {
+    id: 'ListOfVersionsPage.emptyPageSecondBenefit',
+    defaultMessage:
+      '<strong>Be Up-to-Date:</strong> Mark tests as default to use the latest version for the next run. Stay updated without any extra hassle.',
+  },
+  emptyPageThirdBenefit: {
path: app/src/pages/inside/productVersionsPage/listOfVersions/emptyState/messages.js
user: login: OleksandrDragun
body: Done.
created_at: 2025-03-28T19:59:22Z
author_association: CONTRIBUTOR
path: app/src/pages/inside/productVersionsPage/listOfVersions/versionList/versionList.scss
user: login: OleksandrDragun
body: It was discussed to rename inner component.
Done.
created_at: 2025-03-28T20:00:04Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov-commenter
created_at: 2025-03-24T19:38:05Z
body: ## [Codecov](https://app.codecov.io/gh/reportportal/service-ui/pull/4280?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal) Report
:x: Patch coverage is `33.33333%` with `2 lines` in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 61.64%. Comparing base ([`27ab505`](https://app.codecov.io/gh/reportportal/service-ui/commit/27ab505c796eacec087d4b779d898932853f86ff?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal)) to head ([`5944e7b`](https://app.codecov.io/gh/reportportal/service-ui/commit/5944e7b5edfe3d8e7dea2940dd4986684a873987?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal)).
:warning: Report is 553 commits behind head on feature/test-library.

| [Files with missing lines](https://app.codecov.io/gh/reportportal/service-ui/pull/4280?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal) | Patch % | Lines |
|---|---|---|
| [...pp/src/common/utils/validation/commonValidators.js](https://app.codecov.io/gh/reportportal/service-ui/pull/4280?src=pr&el=tree&filepath=app%2Fsrc%2Fcommon%2Futils%2Fvalidation%2FcommonValidators.js&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal#diff-YXBwL3NyYy9jb21tb24vdXRpbHMvdmFsaWRhdGlvbi9jb21tb25WYWxpZGF0b3JzLmpz) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/reportportal/service-ui/pull/4280?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal) |

<details><summary>Additional details and impacted files</summary>



```diff
@@                   Coverage Diff                    @@
##           feature/test-library    #4280      +/-   ##
========================================================
- Coverage                 61.73%   61.64%   -0.09%     
========================================================
  Files                        85       85              
  Lines                       967      970       +3     
  Branches                    141      142       +1     
========================================================
+ Hits                        597      598       +1     
- Misses                      339      341       +2     
  Partials                     31       31              
```
</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/reportportal/service-ui/pull/4280?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=reportportal).
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-03-28T19:58:54Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=reportportal_service-ui&pullRequest=4280) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1 New issue](https://sonarcloud.io/project/issues?id=reportportal_service-ui&pullRequest=4280&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=reportportal_service-ui&pullRequest=4280&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=reportportal_service-ui&pullRequest=4280&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=reportportal_service-ui&pullRequest=4280&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=reportportal_service-ui&pullRequest=4280&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=reportportal_service-ui&pullRequest=4280)


author_association: NONE