From d7128452ed937748f7a5b8dd618d38cd17fd129b Mon Sep 17 00:00:00 2001 From: Revanshu Paliwal Date: Wed, 1 Nov 2023 08:16:34 +0100 Subject: [PATCH] SONAR-20925 Migrating project's links page to new UI --- .../js/app/components/GlobalContainer.tsx | 1 + .../js/apps/projectLinks/CreationModal.tsx | 115 ++++++++---------- .../src/main/js/apps/projectLinks/Header.tsx | 15 +-- .../{LinkRow.tsx => ProjectLinkRow.tsx} | 67 +++++----- .../{Table.tsx => ProjectLinkTable.tsx} | 52 ++++---- .../js/apps/projectLinks/ProjectLinksApp.tsx | 21 ++-- .../__tests__/ProjectLinksApp-it.tsx | 2 +- .../resources/org/sonar/l10n/core.properties | 1 + 8 files changed, 129 insertions(+), 145 deletions(-) rename server/sonar-web/src/main/js/apps/projectLinks/{LinkRow.tsx => ProjectLinkRow.tsx} (67%) rename server/sonar-web/src/main/js/apps/projectLinks/{Table.tsx => ProjectLinkTable.tsx} (53%) diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx index dccd65c1304..f8c8b6c0ace 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx @@ -61,6 +61,7 @@ const TEMP_PAGELIST_WITH_NEW_BACKGROUND_WHITE = [ '/project/branches', '/project/key', '/project/deletion', + '/project/links', ]; export default function GlobalContainer() { diff --git a/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx b/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx index 30823e150ca..830dfb8ed81 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/CreationModal.tsx @@ -17,12 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +import { ButtonPrimary, FormField, InputField, Modal } from 'design-system'; import * as React from 'react'; -import SimpleModal from '../../components/controls/SimpleModal'; -import { ResetButtonLink, SubmitButton } from '../../components/controls/buttons'; -import MandatoryFieldMarker from '../../components/ui/MandatoryFieldMarker'; import MandatoryFieldsExplanation from '../../components/ui/MandatoryFieldsExplanation'; -import Spinner from '../../components/ui/Spinner'; import { translate } from '../../helpers/l10n'; interface Props { @@ -35,10 +32,13 @@ interface State { url: string; } +const FORM_ID = 'create-link-form'; + export default class CreationModal extends React.PureComponent { state: State = { name: '', url: '' }; - handleSubmit = () => { + handleSubmit = (event: React.SyntheticEvent) => { + event.preventDefault(); return this.props.onSubmit(this.state.name, this.state.url).then(this.props.onClose); }; @@ -53,68 +53,55 @@ export default class CreationModal extends React.PureComponent { render() { const header = translate('project_links.create_new_project_link'); - return ( - - {({ onCloseClick, onFormSubmit, submitting }) => ( -
-
-

{header}

-
- -
- + const formBody = ( + + -
- - -
+ + + -
- - -
-
+ + + +
+ ); -
- - - {translate('create')} - - - {translate('cancel')} - -
- - )} -
+ return ( + + {translate('create')} + + } + /> ); } } diff --git a/server/sonar-web/src/main/js/apps/projectLinks/Header.tsx b/server/sonar-web/src/main/js/apps/projectLinks/Header.tsx index 141ed03726d..a8729cf784f 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/Header.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/Header.tsx @@ -17,8 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +import { ButtonPrimary, Title } from 'design-system'; import * as React from 'react'; -import { Button } from '../../components/controls/buttons'; import { translate } from '../../helpers/l10n'; import CreationModal from './CreationModal'; @@ -55,14 +56,14 @@ export default class Header extends React.PureComponent { render() { return ( <> -
-

{translate('project_links.page')}

-
- +
-
{translate('project_links.page.description')}
+

{translate('project_links.page.description')}

{this.state.creationModal && ( diff --git a/server/sonar-web/src/main/js/apps/projectLinks/LinkRow.tsx b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinkRow.tsx similarity index 67% rename from server/sonar-web/src/main/js/apps/projectLinks/LinkRow.tsx rename to server/sonar-web/src/main/js/apps/projectLinks/ProjectLinkRow.tsx index 056d03b166a..f676e1fcce5 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/LinkRow.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinkRow.tsx @@ -17,12 +17,19 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +import { + ActionCell, + ContentCell, + DestructiveIcon, + Link, + Note, + TableRow, + TrashIcon, +} from 'design-system'; import * as React from 'react'; import isValidUri from '../../app/utils/isValidUri'; -import Link from '../../components/common/Link'; -import { Button } from '../../components/controls/buttons'; import ConfirmButton from '../../components/controls/ConfirmButton'; -import ProjectLinkIcon from '../../components/icons/ProjectLinkIcon'; import { translate, translateWithParameters } from '../../helpers/l10n'; import { getLinkName, isProvided } from '../../helpers/projectLinks'; import { ProjectLink } from '../../types/types'; @@ -35,28 +42,13 @@ interface Props { export default class LinkRow extends React.PureComponent { renderNameForProvided = (link: ProjectLink) => { return ( -
+
- {getLinkName(link)} -
-
- {`sonar.links.${link.type}`} + {getLinkName(link)}
-
- ); - }; - - renderName = (link: ProjectLink) => { - return ( -
- - {isProvided(link) ? ( - this.renderNameForProvided(link) - ) : ( -
- {link.name} -
- )} + + {`sonar.links.${link.type}`} +
); }; @@ -79,13 +71,12 @@ export default class LinkRow extends React.PureComponent { onConfirm={this.props.onDelete} > {({ onClick }) => ( - + size="small" + /> )} ); @@ -95,9 +86,17 @@ export default class LinkRow extends React.PureComponent { const { link } = this.props; return ( - - {this.renderName(link)} - + + + {isProvided(link) ? ( + this.renderNameForProvided(link) + ) : ( +
+ {link.name} +
+ )} +
+ {isValidUri(link.url) ? ( {link.url} @@ -105,9 +104,9 @@ export default class LinkRow extends React.PureComponent { ) : ( link.url )} - - {this.renderDeleteButton(link)} - + + {this.renderDeleteButton(link)} +
); } } diff --git a/server/sonar-web/src/main/js/apps/projectLinks/Table.tsx b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinkTable.tsx similarity index 53% rename from server/sonar-web/src/main/js/apps/projectLinks/Table.tsx rename to server/sonar-web/src/main/js/apps/projectLinks/ProjectLinkTable.tsx index 32807d0e219..9974c6c9964 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/Table.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinkTable.tsx @@ -17,49 +17,41 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +import { ActionCell, ContentCell, Note, Table, TableRow } from 'design-system'; import * as React from 'react'; import { translate } from '../../helpers/l10n'; import { orderLinks } from '../../helpers/projectLinks'; import { ProjectLink } from '../../types/types'; -import LinkRow from './LinkRow'; +import LinkRow from './ProjectLinkRow'; interface Props { links: ProjectLink[]; onDelete: (linkId: string) => Promise; } -export default class Table extends React.PureComponent { - renderHeader() { - // keep empty cell for actions - return ( - - - {translate('project_links.name')} - {translate('project_links.url')} -   - - - ); +export default function ProjectLinkTable({ links, onDelete }: Readonly) { + if (!links.length) { + return {translate('project_links.no_results')}; } - render() { - if (!this.props.links.length) { - return
{translate('no_results')}
; - } + const orderedLinks = orderLinks(links); - const orderedLinks = orderLinks(this.props.links); + const linkRows = orderedLinks.map((link) => ( + + )); - const linkRows = orderedLinks.map((link) => ( - - )); + const header = ( + + {translate('project_links.name')} + {translate('project_links.url')} +   + + ); - return ( -
- - {this.renderHeader()} - {linkRows} - -
- ); - } + return ( + + {linkRows} +
+ ); } diff --git a/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx index 9ab0eddd0ed..5165a7b37bb 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/ProjectLinksApp.tsx @@ -17,15 +17,16 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +import { LargeCenteredLayout, PageContentFontWrapper, Spinner } from 'design-system'; import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { createLink, deleteLink, getProjectLinks } from '../../api/projectLinks'; import withComponentContext from '../../app/components/componentContext/withComponentContext'; -import Spinner from '../../components/ui/Spinner'; import { translate } from '../../helpers/l10n'; import { Component, ProjectLink } from '../../types/types'; import Header from './Header'; -import Table from './Table'; +import ProjectLinkTable from './ProjectLinkTable'; interface Props { component: Component; @@ -102,13 +103,15 @@ export class ProjectLinksApp extends React.PureComponent { render() { const { loading, links } = this.state; return ( -
- -
- - {links && } - - + + + +
+ + + + + ); } } diff --git a/server/sonar-web/src/main/js/apps/projectLinks/__tests__/ProjectLinksApp-it.tsx b/server/sonar-web/src/main/js/apps/projectLinks/__tests__/ProjectLinksApp-it.tsx index 932f16b3b7b..77051abf2f0 100644 --- a/server/sonar-web/src/main/js/apps/projectLinks/__tests__/ProjectLinksApp-it.tsx +++ b/server/sonar-web/src/main/js/apps/projectLinks/__tests__/ProjectLinksApp-it.tsx @@ -72,7 +72,7 @@ function getPageObjects() { const ui = { pageTitle: byRole('heading', { name: 'project_links.page' }), - noResultsTable: byText('no_results'), + noResultsTable: byText('project_links.no_results'), createLinkButton: byRole('button', { name: 'create' }), nameInput: byRole('textbox', { name: /project_links.name/ }), urlInput: byRole('textbox', { name: /project_links.url/ }), diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index fe1d5567495..1568ee6a866 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -510,6 +510,7 @@ project_links.are_you_sure_to_delete_x_link=Are you sure you want to delete the project_links.delete_x_link=Delete "{0}" link project_links.name=Name project_links.url=URL +project_links.no_results=No links yet. Click "Create" to add one. #------------------------------------------------------------------------------ -- 2.39.5