+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 Icon, { IconProps } from './Icon';
-
-export default function ProjectEventIcon({ fill = '#fff', size = 14, ...iconProps }: IconProps) {
- return (
- <Icon size={size} {...iconProps}>
- <path
- d="M8 2 L14 8 L8 14 L2 8 L8 2 L14 8"
- style={{ fill, stroke: 'currentColor', strokeWidth: '2px' }}
- />
- </Icon>
- );
-}
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
-import { ResetButtonLink } from 'sonar-ui-common/components/controls/buttons';
+import { ButtonLink } from 'sonar-ui-common/components/controls/buttons';
import BranchIcon from 'sonar-ui-common/components/icons/BranchIcon';
import DropdownIcon from 'sonar-ui-common/components/icons/DropdownIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
interface Props {
branchLike: BranchLike | undefined;
event: DefinitionChangeEvent;
+ readonly?: boolean;
}
interface State {
}
render() {
- const { event } = this.props;
+ const { event, readonly } = this.props;
const { expanded } = this.state;
return (
<>
- <span className="note">{translate('event.category', event.category)}:</span>
+ <span className="note">
+ {translate('event.category', event.category)}
+ {!readonly && ':'}
+ </span>
- <div>
- <ResetButtonLink
- className="project-activity-event-inner-more-link"
- onClick={this.toggleProjectsList}
- stopPropagation={true}>
- {expanded ? translate('hide') : translate('more')}
- <DropdownIcon className="little-spacer-left" turned={expanded} />
- </ResetButtonLink>
- </div>
+ {!readonly && (
+ <div>
+ <ButtonLink
+ className="project-activity-event-inner-more-link"
+ onClick={this.toggleProjectsList}
+ stopPropagation={true}>
+ {expanded ? translate('hide') : translate('more')}
+ <DropdownIcon className="little-spacer-left" turned={expanded} />
+ </ButtonLink>
+ </div>
+ )}
{expanded && (
<ul className="spacer-left spacer-top">
* 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 classNames from 'classnames';
import * as React from 'react';
import { DeleteButton, EditButton } from 'sonar-ui-common/components/controls/buttons';
-import ProjectEventIcon from 'sonar-ui-common/components/icons/ProjectEventIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
import EventInner from './EventInner';
import ChangeEventForm from './forms/ChangeEventForm';
return (
<div className="project-activity-event">
- <ProjectEventIcon
- className={classNames(
- 'project-activity-event-icon little-spacer-right text-middle',
- event.category
- )}
- />
-
<EventInner event={event} />
{showActions && (
export interface EventInnerProps {
event: T.AnalysisEvent;
+ readonly?: boolean;
}
-export default function EventInner({ event }: EventInnerProps) {
+export default function EventInner({ event, readonly }: EventInnerProps) {
if (isRichQualityGateEvent(event)) {
- return <RichQualityGateEventInner event={event} />;
+ return <RichQualityGateEventInner event={event} readonly={readonly} />;
} else if (isDefinitionChangeEvent(event)) {
return (
<ComponentContext.Consumer>
- {({ branchLike }) => <DefinitionChangeEventInner branchLike={branchLike} event={event} />}
+ {({ branchLike }) => (
+ <DefinitionChangeEventInner branchLike={branchLike} event={event} readonly={readonly} />
+ )}
</ComponentContext.Consumer>
);
- } else {
- const content = (
+ }
+
+ return (
+ <Tooltip overlay={event.description || null}>
<span className="text-middle">
<span className="note little-spacer-right">
{translate('event.category', event.category)}:
</span>
<strong className="spacer-right">{event.name}</strong>
</span>
- );
- return event.description ? <Tooltip overlay={event.description}>{content}</Tooltip> : content;
- }
+ </Tooltip>
+ );
}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import ProjectEventIcon from 'sonar-ui-common/components/icons/ProjectEventIcon';
export interface Option {
label: string;
role="link"
tabIndex={0}
title={option.label}>
- <ProjectEventIcon className={'project-activity-event-icon ' + option.value} />
- <span className="little-spacer-left">{this.props.children}</span>
+ {this.props.children}
</div>
);
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2021 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 ProjectEventIcon from 'sonar-ui-common/components/icons/ProjectEventIcon';
-import { Option } from './ProjectActivityEventSelectOption';
-
-interface Props {
- children?: React.ReactNode;
- value: Option;
-}
-
-export default function ProjectActivityEventSelectValue({ children, value }: Props) {
- return (
- <div className="Select-value" title={value.label}>
- <div className="Select-value-label">
- <ProjectEventIcon className={'project-activity-event-icon ' + value.value} />
- <span className="little-spacer-left">{children}</span>
- </div>
- </div>
- );
-}
import { APPLICATION_EVENT_TYPES, EVENT_TYPES, Query } from '../utils';
import ProjectActivityDateInput from './ProjectActivityDateInput';
import ProjectActivityEventSelectOption from './ProjectActivityEventSelectOption';
-import ProjectActivityEventSelectValue from './ProjectActivityEventSelectValue';
interface Props {
category?: string;
placeholder={translate('project_activity.filter_events') + '...'}
searchable={false}
value={this.props.category}
- // @ts-ignore react-select typings are incorrect, they expect `props` of `valueComponent` to be exactly `Option`
- valueComponent={ProjectActivityEventSelectValue}
/>
)}
<ProjectActivityDateInput
interface Props {
event: RichQualityGateEvent;
+ readonly?: boolean;
}
interface State {
};
render() {
- const { event } = this.props;
+ const { event, readonly } = this.props;
const { expanded } = this.state;
return (
<>
)}
<div>
- {event.qualityGate.failing.length > 0 && (
+ {!readonly && event.qualityGate.failing.length > 0 && (
<ResetButtonLink
className="project-activity-event-inner-more-link"
onClick={this.toggleProjectsList}
wrapper.update();
expect(wrapper).toMatchSnapshot();
});
+
+it('should render when readonly', () => {
+ const event: DefinitionChangeEvent = {
+ category: 'DEFINITION_CHANGE',
+ key: 'foo1234',
+ name: '',
+ definitionChange: {
+ projects: [
+ { changeType: 'ADDED', key: 'foo', name: 'Foo', branch: 'master' },
+ { changeType: 'REMOVED', key: 'bar', name: 'Bar', branch: 'master' }
+ ]
+ }
+ };
+ const wrapper = shallow(
+ <DefinitionChangeEventInner branchLike={undefined} event={event} readonly={true} />
+ );
+ expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find('.project-activity-event-inner-more-link').exists()).toBe(false);
+});
);
expect(wrapper.find('.project-activity-event-inner-more-link').exists()).toBe(false);
});
+
+it('should not expand when readonly', () => {
+ const wrapper = shallow(<RichQualityGateEventInner event={event} readonly={true} />);
+ expect(wrapper.find('.project-activity-event-inner-more-link').exists()).toBe(false);
+});
:
</span>
<div>
- <ResetButtonLink
+ <ButtonLink
className="project-activity-event-inner-more-link"
onClick={[Function]}
stopPropagation={true}
className="little-spacer-left"
turned={false}
/>
- </ResetButtonLink>
+ </ButtonLink>
</div>
</Fragment>
`;
:
</span>
<div>
- <ResetButtonLink
+ <ButtonLink
className="project-activity-event-inner-more-link"
onClick={[Function]}
stopPropagation={true}
className="little-spacer-left"
turned={true}
/>
- </ResetButtonLink>
+ </ButtonLink>
</div>
<ul
className="spacer-left spacer-top"
:
</span>
<div>
- <ResetButtonLink
+ <ButtonLink
className="project-activity-event-inner-more-link"
onClick={[Function]}
stopPropagation={true}
className="little-spacer-left"
turned={true}
/>
- </ResetButtonLink>
+ </ButtonLink>
</div>
<ul
className="spacer-left spacer-top"
</ul>
</Fragment>
`;
+
+exports[`should render when readonly 1`] = `
+<Fragment>
+ <span
+ className="note"
+ >
+ event.category.DEFINITION_CHANGE
+ </span>
+</Fragment>
+`;
<div
className="project-activity-event"
>
- <ProjectEventIcon
- className="project-activity-event-icon little-spacer-right text-middle OTHER"
- />
<EventInner
event={
Object {
<div
className="project-activity-event"
>
- <ProjectEventIcon
- className="project-activity-event-icon little-spacer-right text-middle OTHER"
- />
<EventInner
event={
Object {
`;
exports[`should render correctly: no description 1`] = `
-<span
- className="text-middle"
+<Tooltip
+ overlay={null}
>
<span
- className="note little-spacer-right"
+ className="text-middle"
>
- event.category.VERSION
- :
+ <span
+ className="note little-spacer-right"
+ >
+ event.category.VERSION
+ :
+ </span>
+ <strong
+ className="spacer-right"
+ >
+ Lorem ipsum
+ </strong>
</span>
- <strong
- className="spacer-right"
- >
- Lorem ipsum
- </strong>
-</span>
+</Tooltip>
`;
exports[`should render correctly: rich quality gate 1`] = `
role="link"
tabIndex={0}
title="Foo"
->
- <ProjectEventIcon
- className="project-activity-event-icon foo"
- />
- <span
- className="little-spacer-left"
- />
-</div>
+/>
`;
placeholder="project_activity.filter_events..."
searchable={false}
value=""
- valueComponent={[Function]}
/>
<ProjectActivityDateInput
from={2016-10-27T10:21:15.000Z}
<DateTimeFormatter date={this.props.selectedDate} />
</div>
<table className="width-100">
+ {events && events.length > 0 && (
+ <GraphsTooltipsContentEvents addSeparator={addSeparator} events={events} />
+ )}
<tbody>{tooltipContent}</tbody>
{this.props.graph === 'coverage' && (
<GraphsTooltipsContentCoverage
tooltipIdx={tooltipIdx}
/>
)}
- {events && events.length > 0 && (
- <GraphsTooltipsContentEvents addSeparator={addSeparator} events={events} />
- )}
</table>
</div>
</Popup>
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import classNames from 'classnames';
import * as React from 'react';
-import ProjectEventIcon from 'sonar-ui-common/components/icons/ProjectEventIcon';
-import { translate } from 'sonar-ui-common/helpers/l10n';
+import EventInner from '../../apps/projectActivity/components/EventInner';
interface Props {
addSeparator: boolean;
)}
<tr className="activity-graph-tooltip-line">
<td colSpan={3}>
- <span>{translate('events')}:</span>
{events.map(event => (
- <span className="spacer-left" key={event.key}>
- <ProjectEventIcon
- className={classNames('project-activity-event-icon', event.category)}
- />
- </span>
+ <div className="little-spacer-bottom" key={event.key}>
+ <EventInner event={event} readonly={true} />
+ </div>
))}
</td>
</tr>
+ {addSeparator && (
+ <tr>
+ <td className="activity-graph-tooltip-separator" colSpan={3}>
+ <hr />
+ </td>
+ </tr>
+ )}
</tbody>
);
}
import { shallow } from 'enzyme';
import * as React from 'react';
import { parseDate } from 'sonar-ui-common/helpers/dates';
+import { mockEvent } from '../../../helpers/testMocks';
import GraphsTooltips from '../GraphsTooltips';
import { DEFAULT_GRAPH } from '../utils';
it('should render correctly for issues graphs', () => {
expect(shallow(<GraphsTooltips {...DEFAULT_PROPS} />)).toMatchSnapshot();
+ expect(shallow(<GraphsTooltips {...DEFAULT_PROPS} events={[mockEvent()]} />)).toMatchSnapshot(
+ 'with events'
+ );
});
it('should render correctly for random graphs', () => {
</Popup>
`;
+exports[`should render correctly for issues graphs: with events 1`] = `
+<Popup
+ className="disabled-pointer-events"
+ placement="left-top"
+ style={
+ Object {
+ "left": 476,
+ "top": 30,
+ "width": 250,
+ }
+ }
+>
+ <div
+ className="activity-graph-tooltip"
+ >
+ <div
+ className="activity-graph-tooltip-title spacer-bottom"
+ >
+ <DateTimeFormatter
+ date={2011-10-01T22:01:00.000Z}
+ />
+ </div>
+ <table
+ className="width-100"
+ >
+ <GraphsTooltipsContentEvents
+ addSeparator={true}
+ events={
+ Array [
+ Object {
+ "currentTarget": Object {
+ "blur": [Function],
+ },
+ "preventDefault": [Function],
+ "stopPropagation": [Function],
+ "target": Object {
+ "blur": [Function],
+ },
+ },
+ ]
+ }
+ />
+ <tbody>
+ <GraphsTooltipsContentIssues
+ index={0}
+ key="bugs"
+ measuresHistory={Array []}
+ name="bugs"
+ tooltipIdx={0}
+ translatedName="Bugs"
+ value="Formated.3"
+ />
+ <GraphsTooltipsContentIssues
+ index={1}
+ key="code_smells"
+ measuresHistory={Array []}
+ name="code_smells"
+ tooltipIdx={0}
+ translatedName="Code Smells"
+ value="Formated.18"
+ />
+ <GraphsTooltipsContentIssues
+ index={2}
+ key="vulnerabilities"
+ measuresHistory={Array []}
+ name="vulnerabilities"
+ tooltipIdx={0}
+ translatedName="Vulnerabilities"
+ value="Formated.0"
+ />
+ </tbody>
+ </table>
+ </div>
+</Popup>
+`;
+
exports[`should render correctly for random graphs 1`] = `
<Popup
className="disabled-pointer-events"
<td
colSpan={3}
>
- <span>
- events
- :
- </span>
- <span
- className="spacer-left"
+ <div
+ className="little-spacer-bottom"
key="1"
>
- <ProjectEventIcon
- className="project-activity-event-icon VERSION"
+ <EventInner
+ event={
+ Object {
+ "category": "VERSION",
+ "key": "1",
+ "name": "6.5",
+ }
+ }
+ readonly={true}
/>
- </span>
- <span
- className="spacer-left"
+ </div>
+ <div
+ className="little-spacer-bottom"
key="2"
>
- <ProjectEventIcon
- className="project-activity-event-icon OTHER"
+ <EventInner
+ event={
+ Object {
+ "category": "OTHER",
+ "key": "2",
+ "name": "Foo",
+ }
+ }
+ readonly={true}
/>
- </span>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td
+ className="activity-graph-tooltip-separator"
+ colSpan={3}
+ >
+ <hr />
</td>
</tr>
</tbody>