diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2019-05-06 15:59:07 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-05-07 20:21:28 +0200 |
commit | 84e8de22330886ae02907ae86e250e486e3ddfd4 (patch) | |
tree | 68b0087a60e726a533af41d2b9883be5fa4a7a5c /server/sonar-web/src | |
parent | e620cd39b96428241cb71a19abf8c80b776e605f (diff) | |
download | sonarqube-84e8de22330886ae02907ae86e250e486e3ddfd4.tar.gz sonarqube-84e8de22330886ae02907ae86e250e486e3ddfd4.zip |
Create and use ClearButton component
Diffstat (limited to 'server/sonar-web/src')
31 files changed, 280 insertions, 190 deletions
diff --git a/server/sonar-web/src/main/js/app/components/notifications/NotificationsSidebar.tsx b/server/sonar-web/src/main/js/app/components/notifications/NotificationsSidebar.tsx index 443987abc97..660678a7552 100644 --- a/server/sonar-web/src/main/js/app/components/notifications/NotificationsSidebar.tsx +++ b/server/sonar-web/src/main/js/app/components/notifications/NotificationsSidebar.tsx @@ -19,12 +19,10 @@ */ import * as React from 'react'; import * as classNames from 'classnames'; -import * as theme from '../../../app/theme'; -import ClearIcon from '../../../components/icons-components/ClearIcon'; import DateFormatter from '../../../components/intl/DateFormatter'; import DeferredSpinner from '../../../components/common/DeferredSpinner'; import Modal from '../../../components/controls/Modal'; -import { ButtonIcon } from '../../../components/ui/buttons'; +import { ClearButton } from '../../../components/ui/buttons'; import { PrismicFeatureNews } from '../../../api/news'; import { differenceInSeconds } from '../../../helpers/dates'; import { translate } from '../../../helpers/l10n'; @@ -46,9 +44,11 @@ export default function NotificationsSidebar(props: Props) { <div className="notifications-sidebar"> <div className="notifications-sidebar-top"> <h3>{translate('embed_docs.whats_new')}</h3> - <ButtonIcon className="button-tiny" color={theme.gray80} onClick={props.onClose}> - <ClearIcon fill={theme.baseFontColor} size={12} thin={true} /> - </ButtonIcon> + <ClearButton + className="button-tiny" + iconProps={{ size: 12, thin: true }} + onClick={props.onClose} + /> </div> <div className="notifications-sidebar-content"> {loading ? ( diff --git a/server/sonar-web/src/main/js/app/components/notifications/__tests__/__snapshots__/NotificationsSidebar-test.tsx.snap b/server/sonar-web/src/main/js/app/components/notifications/__tests__/__snapshots__/NotificationsSidebar-test.tsx.snap index 321569b2d0b..ddcd230ef57 100644 --- a/server/sonar-web/src/main/js/app/components/notifications/__tests__/__snapshots__/NotificationsSidebar-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/notifications/__tests__/__snapshots__/NotificationsSidebar-test.tsx.snap @@ -135,17 +135,16 @@ exports[`#NotificationSidebar should render correctly if there are new features <h3> embed_docs.whats_new </h3> - <ButtonIcon + <ClearButton className="button-tiny" - color="#cdcdcd" + iconProps={ + Object { + "size": 12, + "thin": true, + } + } onClick={[MockFunction]} - > - <ClearIcon - fill="#444" - size={12} - thin={true} - /> - </ButtonIcon> + /> </div> <div className="notifications-sidebar-content" @@ -176,17 +175,16 @@ exports[`#NotificationSidebar should render correctly if there are new features <h3> embed_docs.whats_new </h3> - <ButtonIcon + <ClearButton className="button-tiny" - color="#cdcdcd" + iconProps={ + Object { + "size": 12, + "thin": true, + } + } onClick={[MockFunction]} - > - <ClearIcon - fill="#444" - size={12} - thin={true} - /> - </ButtonIcon> + /> </div> <div className="notifications-sidebar-content" diff --git a/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx b/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx index a9193117774..99c5c5028e7 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx +++ b/server/sonar-web/src/main/js/apps/create/organization/AutoOrganizationCreate.tsx @@ -25,8 +25,7 @@ import OrganizationDetailsStep from './OrganizationDetailsStep'; import PlanStep from './PlanStep'; import { Step } from './utils'; import { Alert } from '../../../components/ui/Alert'; -import { ButtonIcon } from '../../../components/ui/buttons'; -import ClearIcon from '../../../components/icons-components/ClearIcon'; +import { ClearButton } from '../../../components/ui/buttons'; import RadioToggle from '../../../components/controls/RadioToggle'; import { bindAlmOrganization } from '../../../api/alm-integration'; import { sanitizeAlmId, getAlmMembersUrl, isGithub } from '../../../helpers/almIntegrations'; @@ -137,9 +136,7 @@ export default class AutoOrganizationCreate extends React.PureComponent<Props, S name: <strong>{almOrganization.name}</strong> }} /> - <ButtonIcon className="little-spacer-left" onClick={this.props.handleCancelImport}> - <ClearIcon /> - </ButtonIcon> + <ClearButton className="little-spacer-left" onClick={this.props.handleCancelImport} /> </p> {hasUnboundOrgs && ( diff --git a/server/sonar-web/src/main/js/apps/create/organization/AutoPersonalOrganizationBind.tsx b/server/sonar-web/src/main/js/apps/create/organization/AutoPersonalOrganizationBind.tsx index a97e49ed951..9a1afec98b4 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/AutoPersonalOrganizationBind.tsx +++ b/server/sonar-web/src/main/js/apps/create/organization/AutoPersonalOrganizationBind.tsx @@ -23,9 +23,8 @@ import OrganizationDetailsForm from './OrganizationDetailsForm'; import OrganizationDetailsStep from './OrganizationDetailsStep'; import PlanStep from './PlanStep'; import { Step } from './utils'; -import ClearIcon from '../../../components/icons-components/ClearIcon'; +import { ClearButton } from '../../../components/ui/buttons'; import OrganizationAvatar from '../../../components/common/OrganizationAvatar'; -import { ButtonIcon } from '../../../components/ui/buttons'; import { getBaseUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; import { sanitizeAlmId } from '../../../helpers/almIntegrations'; @@ -98,9 +97,7 @@ export default class AutoPersonalOrganizationBind extends React.PureComponent<Pr personalName: importPersonalOrg && <strong>{importPersonalOrg.name}</strong> }} /> - <ButtonIcon className="little-spacer-left" onClick={this.props.handleCancelImport}> - <ClearIcon /> - </ButtonIcon> + <ClearButton className="little-spacer-left" onClick={this.props.handleCancelImport} /> </div> <OrganizationDetailsForm keyReadOnly={true} diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx index 0e5500e5160..1ce72fbeece 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx +++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoOrganizationCreate-test.tsx @@ -62,7 +62,7 @@ it('should allow to cancel org import', () => { const handleCancelImport = jest.fn().mockResolvedValue({ key: 'foo' }); const wrapper = shallowRender({ handleCancelImport }); - click(wrapper.find('ButtonIcon')); + click(wrapper.find('ClearButton')); expect(handleCancelImport).toBeCalled(); }); diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoPersonalOrganizationBind-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoPersonalOrganizationBind-test.tsx index 8d9282c3f10..a66aa36b757 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoPersonalOrganizationBind-test.tsx +++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/AutoPersonalOrganizationBind-test.tsx @@ -56,7 +56,7 @@ it('should allow to cancel org import', () => { handleCancelImport }); - click(wrapper.find('ButtonIcon')); + click(wrapper.find('ClearButton')); expect(handleCancelImport).toBeCalled(); }); diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap index 89856c1c8b3..9b74fb68d47 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoOrganizationCreate-test.tsx.snap @@ -31,12 +31,10 @@ exports[`should display choice between import or creation 1`] = ` } } /> - <ButtonIcon + <ClearButton className="little-spacer-left" onClick={[MockFunction]} - > - <ClearIcon /> - </ButtonIcon> + /> </p> <RadioToggle disabled={false} @@ -132,12 +130,10 @@ exports[`should render prefilled and create org 1`] = ` } } /> - <ButtonIcon + <ClearButton className="little-spacer-left" onClick={[MockFunction]} - > - <ClearIcon /> - </ButtonIcon> + /> </p> </div> <OrganizationDetailsForm diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoPersonalOrganizationBind-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoPersonalOrganizationBind-test.tsx.snap index 0d4420b06ce..d9ad62a78b2 100644 --- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoPersonalOrganizationBind-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/AutoPersonalOrganizationBind-test.tsx.snap @@ -40,12 +40,10 @@ exports[`should render correctly 1`] = ` } } /> - <ButtonIcon + <ClearButton className="little-spacer-left" onClick={[MockFunction]} - > - <ClearIcon /> - </ButtonIcon> + /> </div> <OrganizationDetailsForm keyReadOnly={true} diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.tsx b/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.tsx index 0ce5d2b5419..aff3dd00055 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.tsx +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaLink.tsx @@ -18,10 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import ClearIcon from '../../../components/icons-components/ClearIcon'; import ProjectLinkIcon from '../../../components/icons-components/ProjectLinkIcon'; import isValidUri from '../../../app/utils/isValidUri'; -import { ButtonIcon } from '../../../components/ui/buttons'; +import { ClearButton } from '../../../components/ui/buttons'; import { getLinkName } from '../../projectLinks/utils'; interface Props { @@ -65,7 +64,7 @@ export default class MetaLink extends React.PureComponent<Props, State> { {!iconOnly && linkTitle} </a> {this.state.expanded && ( - <div className="little-spacer-top"> + <div className="little-spacer-top display-flex-center"> <input className="overview-key width-80" onClick={this.handleSelect} @@ -73,9 +72,7 @@ export default class MetaLink extends React.PureComponent<Props, State> { type="text" value={link.url} /> - <ButtonIcon className="little-spacer-left" onClick={this.handleCollapse}> - <ClearIcon /> - </ButtonIcon> + <ClearButton className="little-spacer-left" onClick={this.handleCollapse} /> </div> )} </li> diff --git a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaLink-test.tsx b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaLink-test.tsx index 3f3cea24583..e7b0ad368d0 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaLink-test.tsx +++ b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaLink-test.tsx @@ -67,6 +67,6 @@ it('should expand and collapse dangerous link', () => { // collapse with button click(wrapper.find('a')); expect(wrapper.state('expanded')).toBe(true); - click(wrapper.find('ButtonIcon')); + click(wrapper.find('ClearButton')); expect(wrapper.state('expanded')).toBe(false); }); diff --git a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaLink-test.tsx.snap b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaLink-test.tsx.snap index eeef601d561..773b22685c1 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaLink-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaLink-test.tsx.snap @@ -36,7 +36,7 @@ exports[`should expand and collapse dangerous link 2`] = ` Dangerous </a> <div - className="little-spacer-top" + className="little-spacer-top display-flex-center" > <input className="overview-key width-80" @@ -45,12 +45,10 @@ exports[`should expand and collapse dangerous link 2`] = ` type="text" value="javascript:alert(\\"hi\\")" /> - <ButtonIcon + <ClearButton className="little-spacer-left" onClick={[Function]} - > - <ClearIcon /> - </ButtonIcon> + /> </div> </li> `; diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.tsx b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.tsx index 7fd415ce9e5..5d440346cb5 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.tsx +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.tsx @@ -19,11 +19,9 @@ */ import * as React from 'react'; import * as classNames from 'classnames'; -import * as theme from '../../../app/theme'; import AlertWarnIcon from '../../../components/icons-components/AlertWarnIcon'; import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon'; -import { ButtonIcon } from '../../../components/ui/buttons'; -import ClearIcon from '../../../components/icons-components/ClearIcon'; +import { ClearButton } from '../../../components/ui/buttons'; interface Props { className?: string; @@ -56,12 +54,11 @@ export default class GraphsLegendItem extends React.PureComponent<Props> { )} <span className="text-middle">{this.props.name}</span> {isActionable && ( - <ButtonIcon + <ClearButton className="button-tiny spacer-left text-middle" - color={theme.gray60} - onClick={this.handleClick}> - <ClearIcon size={12} /> - </ButtonIcon> + iconProps={{ size: 12 }} + onClick={this.handleClick} + /> )} </span> ); diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.tsx.snap index 19d9bb6c1d8..68c3c7d6f24 100644 --- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.tsx.snap @@ -29,15 +29,15 @@ exports[`should render correctly an actionable legend 1`] = ` > Foo </span> - <ButtonIcon + <ClearButton className="button-tiny spacer-left text-middle" - color="#999" + iconProps={ + Object { + "size": 12, + } + } onClick={[Function]} - > - <ClearIcon - size={12} - /> - </ButtonIcon> + /> </span> `; diff --git a/server/sonar-web/src/main/js/apps/tutorials/components/__tests__/TokenStep-test.tsx b/server/sonar-web/src/main/js/apps/tutorials/components/__tests__/TokenStep-test.tsx index bdac3e8dc93..a51a10d3f3a 100644 --- a/server/sonar-web/src/main/js/apps/tutorials/components/__tests__/TokenStep-test.tsx +++ b/server/sonar-web/src/main/js/apps/tutorials/components/__tests__/TokenStep-test.tsx @@ -28,8 +28,6 @@ jest.mock('../../../../api/user-tokens', () => ({ revokeToken: () => Promise.resolve() })); -jest.mock('../../../../components/icons-components/ClearIcon'); - const currentUser = { login: 'user' }; it('generates token', async () => { diff --git a/server/sonar-web/src/main/js/components/controls/DateInput.tsx b/server/sonar-web/src/main/js/components/controls/DateInput.tsx index 93ad3ac3910..f7155206822 100644 --- a/server/sonar-web/src/main/js/components/controls/DateInput.tsx +++ b/server/sonar-web/src/main/js/components/controls/DateInput.tsx @@ -29,12 +29,10 @@ import * as subMonths from 'date-fns/sub_months'; import OutsideClickHandler from './OutsideClickHandler'; import Select from './Select'; import { lazyLoad } from '../lazyLoad'; -import * as theme from '../../app/theme'; import CalendarIcon from '../icons-components/CalendarIcon'; import ChevronLeftIcon from '../icons-components/ChevronLeftIcon'; import ChevronRightIcon from '../icons-components/ChevronRightcon'; -import ClearIcon from '../icons-components/ClearIcon'; -import { ButtonIcon } from '../ui/buttons'; +import { ButtonIcon, ClearButton } from '../ui/buttons'; import { getShortMonthName, getWeekDayName, getShortWeekDayName } from '../../helpers/l10n'; import './DayPicker.css'; import './styles.css'; @@ -164,12 +162,11 @@ export default class DateInput extends React.PureComponent<Props, State> { /> <CalendarIcon className="date-input-control-icon" fill="" /> {this.props.value !== undefined && ( - <ButtonIcon + <ClearButton className="button-tiny date-input-control-reset" - color={theme.gray60} - onClick={this.handleResetClick}> - <ClearIcon size={12} /> - </ButtonIcon> + iconProps={{ size: 12 }} + onClick={this.handleResetClick} + /> )} {this.state.open && ( <div className="date-input-calendar"> diff --git a/server/sonar-web/src/main/js/components/controls/GlobalMessages.tsx b/server/sonar-web/src/main/js/components/controls/GlobalMessages.tsx index f72d57e1360..037aabf5ff3 100644 --- a/server/sonar-web/src/main/js/components/controls/GlobalMessages.tsx +++ b/server/sonar-web/src/main/js/components/controls/GlobalMessages.tsx @@ -19,8 +19,8 @@ */ import * as React from 'react'; import * as classNames from 'classnames'; -import ClearIcon from '../icons-components/ClearIcon'; -import { ButtonIcon } from '../ui/buttons'; +import { ClearButton } from '../ui/buttons'; +import { cutLongWords } from '../../helpers/path'; import './GlobalMessages.css'; interface Message { @@ -29,44 +29,49 @@ interface Message { message: string; } -interface Props { +export interface Props { closeGlobalMessage: (id: string) => void; messages: Message[]; } -export default class GlobalMessages extends React.PureComponent<Props> { - cutLongWords = (message: string) => { - return message - .split(' ') - .map(word => (word.length > 35 ? word.substr(0, 35) + '...' : word)) - .join(' '); +export default function GlobalMessages({ closeGlobalMessage, messages }: Props) { + if (messages.length === 0) { + return null; + } + + return ( + <div className="processes-container"> + {messages.map(message => ( + <GlobalMessage closeGlobalMessage={closeGlobalMessage} key={message.id} message={message} /> + ))} + </div> + ); +} + +export class GlobalMessage extends React.PureComponent<{ + closeGlobalMessage: (id: string) => void; + message: Message; +}> { + handleClose = () => { + this.props.closeGlobalMessage(this.props.message.id); }; - renderMessage = (message: Message) => { - const className = classNames('process-spinner', 'shown', { - 'process-spinner-failed': message.level === 'ERROR', - 'process-spinner-success': message.level === 'SUCCESS' - }); + render() { + const { message } = this.props; return ( - <div className={className} key={message.id}> - {this.cutLongWords(message.message)} - <ButtonIcon + <div + className={classNames('process-spinner', 'shown', { + 'process-spinner-failed': message.level === 'ERROR', + 'process-spinner-success': message.level === 'SUCCESS' + })} + key={message.id}> + {cutLongWords(message.message)} + <ClearButton className="button-small process-spinner-close" color="#fff" - onClick={() => this.props.closeGlobalMessage(message.id)}> - <ClearIcon /> - </ButtonIcon> + onClick={this.handleClose} + /> </div> ); - }; - - render() { - const { messages } = this.props; - - if (messages.length === 0) { - return null; - } - - return <div className="processes-container">{messages.map(this.renderMessage)}</div>; } } diff --git a/server/sonar-web/src/main/js/components/controls/SearchBox.tsx b/server/sonar-web/src/main/js/components/controls/SearchBox.tsx index 2d2b5669917..0a6d8e62f09 100644 --- a/server/sonar-web/src/main/js/components/controls/SearchBox.tsx +++ b/server/sonar-web/src/main/js/components/controls/SearchBox.tsx @@ -20,11 +20,9 @@ import * as React from 'react'; import * as classNames from 'classnames'; import { debounce, Cancelable } from 'lodash'; -import ClearIcon from '../icons-components/ClearIcon'; import SearchIcon from '../icons-components/SearchIcon'; import DeferredSpinner from '../common/DeferredSpinner'; -import { ButtonIcon } from '../ui/buttons'; -import * as theme from '../../app/theme'; +import { ClearButton } from '../ui/buttons'; import { translateWithParameters, translate } from '../../helpers/l10n'; import './SearchBox.css'; @@ -156,12 +154,11 @@ export default class SearchBox extends React.PureComponent<Props, State> { </DeferredSpinner> {value && ( - <ButtonIcon + <ClearButton className="button-tiny search-box-clear" - color={theme.gray60} - onClick={this.handleResetClick}> - <ClearIcon size={12} /> - </ButtonIcon> + iconProps={{ size: 12 }} + onClick={this.handleResetClick} + /> )} {tooShort && ( diff --git a/server/sonar-web/src/main/js/components/controls/Select.tsx b/server/sonar-web/src/main/js/components/controls/Select.tsx index 28ce819edbf..05be7b0c5e3 100644 --- a/server/sonar-web/src/main/js/components/controls/Select.tsx +++ b/server/sonar-web/src/main/js/components/controls/Select.tsx @@ -19,9 +19,7 @@ */ import * as React from 'react'; import { ReactSelectProps, ReactCreatableSelectProps, ReactAsyncSelectProps } from 'react-select'; -import * as theme from '../../app/theme'; -import ClearIcon from '../icons-components/ClearIcon'; -import { ButtonIcon } from '../ui/buttons'; +import { ClearButton } from '../ui/buttons'; import { lazyLoad } from '../lazyLoad'; import './react-select.css'; @@ -31,11 +29,7 @@ const ReactCreatable = lazyLoad(() => ReactSelectLib.then(lib => ({ default: lib const ReactAsync = lazyLoad(() => ReactSelectLib.then(lib => ({ default: lib.Async }))); function renderInput() { - return ( - <ButtonIcon className="button-tiny spacer-left text-middle" color={theme.gray60}> - <ClearIcon size={12} /> - </ButtonIcon> - ); + return <ClearButton className="button-tiny spacer-left text-middle" iconProps={{ size: 12 }} />; } interface WithInnerRef { diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/GlobalMessages-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/GlobalMessages-test.tsx new file mode 100644 index 00000000000..f4632492e35 --- /dev/null +++ b/server/sonar-web/src/main/js/components/controls/__tests__/GlobalMessages-test.tsx @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { shallow } from 'enzyme'; +import GlobalMessages, { Props } from '../GlobalMessages'; + +it('should not render when no message', () => { + expect(shallowRender({ messages: [] }).type()).toBeNull(); +}); + +it('should render correctly with a message', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot(); + expect( + wrapper + .find('GlobalMessage') + .first() + .dive() + ).toMatchSnapshot(); +}); + +function shallowRender(props: Partial<Props> = {}) { + return shallow( + <GlobalMessages + closeGlobalMessage={jest.fn()} + messages={[ + { id: '1', level: 'ERROR', message: 'Test' }, + { id: '2', level: 'ERROR', message: 'Test 2' } + ]} + {...props} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap index f4dc4048d63..5b49a50d0f5 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/DateInput-test.tsx.snap @@ -43,15 +43,15 @@ exports[`should render 2`] = ` className="date-input-control-icon" fill="" /> - <ButtonIcon + <ClearButton className="button-tiny date-input-control-reset" - color="#999" + iconProps={ + Object { + "size": 12, + } + } onClick={[Function]} - > - <ClearIcon - size={12} - /> - </ButtonIcon> + /> </span> </OutsideClickHandler> `; @@ -76,15 +76,15 @@ exports[`should render 3`] = ` className="date-input-control-icon" fill="" /> - <ButtonIcon + <ClearButton className="button-tiny date-input-control-reset" - color="#999" + iconProps={ + Object { + "size": 12, + } + } onClick={[Function]} - > - <ClearIcon - size={12} - /> - </ButtonIcon> + /> <div className="date-input-calendar" > diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/GlobalMessages-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/GlobalMessages-test.tsx.snap new file mode 100644 index 00000000000..cf1235d7cd2 --- /dev/null +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/GlobalMessages-test.tsx.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly with a message 1`] = ` +<div + className="processes-container" +> + <GlobalMessage + closeGlobalMessage={[MockFunction]} + key="1" + message={ + Object { + "id": "1", + "level": "ERROR", + "message": "Test", + } + } + /> + <GlobalMessage + closeGlobalMessage={[MockFunction]} + key="2" + message={ + Object { + "id": "2", + "level": "ERROR", + "message": "Test 2", + } + } + /> +</div> +`; + +exports[`should render correctly with a message 2`] = ` +<div + className="process-spinner shown process-spinner-failed" + key="1" +> + Test + <ClearButton + className="button-small process-spinner-close" + color="#fff" + onClick={[Function]} + /> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap index e7183478c77..3a61b8d4358 100644 --- a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/SearchBox-test.tsx.snap @@ -24,14 +24,14 @@ exports[`renders 1`] = ` className="search-box-magnifier" /> </DeferredSpinner> - <ButtonIcon + <ClearButton className="button-tiny search-box-clear" - color="#999" + iconProps={ + Object { + "size": 12, + } + } onClick={[Function]} - > - <ClearIcon - size={12} - /> - </ButtonIcon> + /> </div> `; diff --git a/server/sonar-web/src/main/js/components/ui/NewsBox.tsx b/server/sonar-web/src/main/js/components/ui/NewsBox.tsx index 8fe54f49495..b9ba6bca68e 100644 --- a/server/sonar-web/src/main/js/components/ui/NewsBox.tsx +++ b/server/sonar-web/src/main/js/components/ui/NewsBox.tsx @@ -19,9 +19,7 @@ */ import * as React from 'react'; import * as classNames from 'classnames'; -import { ButtonIcon } from './buttons'; -import ClearIcon from '../icons-components/ClearIcon'; -import * as theme from '../../app/theme'; +import { ClearButton } from './buttons'; import { translate } from '../../helpers/l10n'; import './NewsBox.css'; @@ -40,9 +38,11 @@ export default function NewsBox({ children, className, onClose, title }: Props) <span className="badge badge-new spacer-right">{translate('new')}</span> <strong>{title}</strong> </div> - <ButtonIcon className="button-tiny" color={theme.gray80} onClick={onClose}> - <ClearIcon fill={theme.baseFontColor} size={12} thin={true} /> - </ButtonIcon> + <ClearButton + className="button-tiny" + iconProps={{ size: 12, then: true }} + onClick={onClose} + /> </div> <div className="big-spacer-top note">{children}</div> </div> diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/NewsBox-test.tsx b/server/sonar-web/src/main/js/components/ui/__tests__/NewsBox-test.tsx index e6758a4ec54..e3e93e0e266 100644 --- a/server/sonar-web/src/main/js/components/ui/__tests__/NewsBox-test.tsx +++ b/server/sonar-web/src/main/js/components/ui/__tests__/NewsBox-test.tsx @@ -29,7 +29,7 @@ it('should render correctly', () => { it('should call onClose', () => { const onClose = jest.fn(); const wrapper = shallowRender({ onClose }); - click(wrapper.find('ButtonIcon')); + click(wrapper.find('ClearButton')); expect(onClose).toBeCalled(); }); diff --git a/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/NewsBox-test.tsx.snap b/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/NewsBox-test.tsx.snap index 068bf719d63..05b01c0a492 100644 --- a/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/NewsBox-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/ui/__tests__/__snapshots__/NewsBox-test.tsx.snap @@ -20,17 +20,16 @@ exports[`should render correctly 1`] = ` title </strong> </div> - <ButtonIcon + <ClearButton className="button-tiny" - color="#cdcdcd" + iconProps={ + Object { + "size": 12, + "then": true, + } + } onClick={[MockFunction]} - > - <ClearIcon - fill="#444" - size={12} - thin={true} - /> - </ButtonIcon> + /> </div> <div className="big-spacer-top note" diff --git a/server/sonar-web/src/main/js/components/ui/buttons.tsx b/server/sonar-web/src/main/js/components/ui/buttons.tsx index c8866c5ac4a..d4d15ae9475 100644 --- a/server/sonar-web/src/main/js/components/ui/buttons.tsx +++ b/server/sonar-web/src/main/js/components/ui/buttons.tsx @@ -21,10 +21,12 @@ import * as React from 'react'; import * as classNames from 'classnames'; import * as theme from '../../app/theme'; import ChevronRightIcon from '../icons-components/ChevronRightcon'; +import ClearIcon from '../icons-components/ClearIcon'; import DeleteIcon from '../icons-components/DeleteIcon'; import EditIcon from '../icons-components/EditIcon'; import Tooltip from '../controls/Tooltip'; import './buttons.css'; +import { IconProps } from '../icons-components/Icon'; type AllowedButtonAttributes = Pick< React.ButtonHTMLAttributes<HTMLButtonElement>, @@ -90,12 +92,11 @@ export function ResetButtonLink(props: T.Omit<ButtonProps, 'type'>) { return <ButtonLink {...props} type="reset" />; } -interface ButtonIconProps { +interface ButtonIconProps extends ButtonProps { className?: string; color?: string; onClick?: () => void; tooltip?: string; - [x: string]: any; } export function ButtonIcon(props: ButtonIconProps) { @@ -118,24 +119,32 @@ export function ButtonIcon(props: ButtonIconProps) { return buttonComponent; } -interface ActionButtonProps { +interface ActionButtonProps extends ButtonIconProps { className?: string; + iconProps?: IconProps; onClick?: () => void; - [x: string]: any; } -export function DeleteButton(props: ActionButtonProps) { +export function ClearButton({ color = theme.gray60, iconProps = {}, ...props }: ActionButtonProps) { + return ( + <ButtonIcon color={color} {...props}> + <ClearIcon {...iconProps} /> + </ButtonIcon> + ); +} + +export function DeleteButton({ iconProps = {}, ...props }: ActionButtonProps) { return ( <ButtonIcon color={theme.red} {...props}> - <DeleteIcon /> + <DeleteIcon {...iconProps} /> </ButtonIcon> ); } -export function EditButton(props: ActionButtonProps) { +export function EditButton({ iconProps = {}, ...props }: ActionButtonProps) { return ( <ButtonIcon {...props}> - <EditIcon /> + <EditIcon {...iconProps} /> </ButtonIcon> ); } diff --git a/server/sonar-web/src/main/js/components/workspace/WorkspaceNavItem.tsx b/server/sonar-web/src/main/js/components/workspace/WorkspaceNavItem.tsx index 51505c7dbaa..bb94c03bc04 100644 --- a/server/sonar-web/src/main/js/components/workspace/WorkspaceNavItem.tsx +++ b/server/sonar-web/src/main/js/components/workspace/WorkspaceNavItem.tsx @@ -18,8 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import ClearIcon from '../icons-components/ClearIcon'; -import { ButtonIcon } from '../ui/buttons'; +import { ClearButton } from '../ui/buttons'; export interface Props { children: React.ReactNode; @@ -40,12 +39,12 @@ export default class WorkspaceNavItem extends React.PureComponent<Props> { <a className="workspace-nav-item-link" href="#" onClick={this.handleNameClick}> {this.props.children} </a> - <ButtonIcon + <ClearButton className="js-close workspace-nav-item-close workspace-header-icon button-small little-spacer-left" color="#fff" - onClick={this.props.onClose}> - <ClearIcon fill={undefined} size={12} /> - </ButtonIcon> + iconProps={{ size: 12 }} + onClick={this.props.onClose} + /> </li> ); } diff --git a/server/sonar-web/src/main/js/components/workspace/__tests__/WorkspaceNavItem-test.tsx b/server/sonar-web/src/main/js/components/workspace/__tests__/WorkspaceNavItem-test.tsx index fabed55b690..90ec99f0db8 100644 --- a/server/sonar-web/src/main/js/components/workspace/__tests__/WorkspaceNavItem-test.tsx +++ b/server/sonar-web/src/main/js/components/workspace/__tests__/WorkspaceNavItem-test.tsx @@ -29,7 +29,7 @@ it('should render', () => { it('should close', () => { const onClose = jest.fn(); const wrapper = shallowRender({ onClose }); - click(wrapper.find('ButtonIcon')); + click(wrapper.find('ClearButton')); expect(onClose).toBeCalled(); }); diff --git a/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceNavItem-test.tsx.snap b/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceNavItem-test.tsx.snap index 3834b942dba..92280457eef 100644 --- a/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceNavItem-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceNavItem-test.tsx.snap @@ -13,14 +13,15 @@ exports[`should render 1`] = ` id="workspace-nav-item" /> </a> - <ButtonIcon + <ClearButton className="js-close workspace-nav-item-close workspace-header-icon button-small little-spacer-left" color="#fff" + iconProps={ + Object { + "size": 12, + } + } onClick={[MockFunction]} - > - <ClearIcon - size={12} - /> - </ButtonIcon> + /> </li> `; diff --git a/server/sonar-web/src/main/js/helpers/__tests__/path-test.ts b/server/sonar-web/src/main/js/helpers/__tests__/path-test.ts index ffd53ce4df0..a7f4b1dd993 100644 --- a/server/sonar-web/src/main/js/helpers/__tests__/path-test.ts +++ b/server/sonar-web/src/main/js/helpers/__tests__/path-test.ts @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { collapsedDirFromPath, fileFromPath } from '../path'; +import { collapsedDirFromPath, cutLongWords, fileFromPath } from '../path'; describe('#collapsedDirFromPath()', () => { it('should return null when pass null', () => { @@ -66,3 +66,15 @@ describe('#fileFromPath()', () => { expect(fileFromPath('src/main/file')).toBe('file'); }); }); + +describe('#cutLongWords', () => { + it('should cut the long work in the middle', () => { + expect(cutLongWords('This is a reallylongwordthatdontexistforthe test')).toBe( + 'This is a reallylongwordthatdontexistfor... test' + ); + }); + + it('should not cut anything', () => { + expect(cutLongWords('This is a test')).toBe('This is a test'); + }); +}); diff --git a/server/sonar-web/src/main/js/helpers/path.ts b/server/sonar-web/src/main/js/helpers/path.ts index bbb2ca4b8c6..56a5be1bcdc 100644 --- a/server/sonar-web/src/main/js/helpers/path.ts +++ b/server/sonar-web/src/main/js/helpers/path.ts @@ -95,6 +95,13 @@ export function splitPath(path: string) { }; } +export function cutLongWords(str: string, limit = 30) { + return str + .split(' ') + .map(word => (word.length > limit ? word.substr(0, limit) + '...' : word)) + .join(' '); +} + export function limitComponentName(str: string, limit = 30): string { if (typeof str === 'string') { return str.length > limit ? str.substr(0, limit) + '...' : str; |