}
export function getSecurityHotspotDetails(securityHotspotKey: string): Promise<Hotspot> {
- return getJSON('/api/hotspots/show', { hotspot: securityHotspotKey }).catch(throwGlobalError);
+ return getJSON('/api/hotspots/show', { hotspot: securityHotspotKey })
+ .then((response: Hotspot & { users: T.UserBase[] }) => {
+ const { users, ...hotspot } = response;
+
+ if (users) {
+ if (hotspot.assignee) {
+ hotspot.assigneeUser = users.find(u => u.login === hotspot.assignee) || {
+ active: true,
+ login: hotspot.assignee
+ };
+ }
+ hotspot.authorUser = users.find(u => u.login === hotspot.author) || {
+ active: true,
+ login: hotspot.author
+ };
+ hotspot.comment.forEach(c => {
+ c.user = users.find(u => u.login === c.login) || { active: true, login: c.login };
+ });
+ }
+
+ return hotspot;
+ })
+ .catch(throwGlobalError);
}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { mockHotspot, mockRawHotspot } from '../../../helpers/mocks/security-hotspots';
+import { mockUser } from '../../../helpers/testMocks';
import { ReviewHistoryType, RiskExposure } from '../../../types/security-hotspots';
import { getHotspotReviewHistory, groupByCategory, mapRules, sortHotspots } from '../utils';
}
]
};
+ const commentElement = {
+ key: 'comment-1',
+ createdAt: '2018-09-10',
+ htmlText: '<strong>TEST</strong>',
+ markdown: '*TEST*',
+ updatable: true,
+ login: 'dude-1',
+ user: mockUser({ login: 'dude-1' })
+ };
+ const commentElement1 = {
+ key: 'comment-2',
+ createdAt: '2018-09-11',
+ htmlText: '<strong>TEST</strong>',
+ markdown: '*TEST*',
+ updatable: true,
+ login: 'dude-2',
+ user: mockUser({ login: 'dude-2' })
+ };
const hotspot = mockHotspot({
creationDate: '2018-09-01',
- changelog: [changelogElement]
+ changelog: [changelogElement],
+ comment: [commentElement, commentElement1]
});
const history = getHotspotReviewHistory(hotspot);
- expect(history.length).toBe(2);
+ expect(history.length).toBe(4);
expect(history[0]).toEqual(
expect.objectContaining({
type: ReviewHistoryType.Creation,
date: hotspot.creationDate,
- user: {
- avatar: hotspot.author.avatar,
- name: hotspot.author.name,
- active: hotspot.author.active
- }
+ user: hotspot.authorUser
})
);
expect(history[1]).toEqual(
+ expect.objectContaining({
+ type: ReviewHistoryType.Comment,
+ date: commentElement.createdAt,
+ user: commentElement.user,
+ html: commentElement.htmlText
+ })
+ );
+ expect(history[2]).toEqual(
+ expect.objectContaining({
+ type: ReviewHistoryType.Comment,
+ date: commentElement1.createdAt,
+ user: commentElement1.user,
+ html: commentElement1.htmlText
+ })
+ );
+ expect(history[3]).toEqual(
expect.objectContaining({
type: ReviewHistoryType.Diff,
date: changelogElement.creationDate,
<span className="badge little-spacer-left">
{translate('hotspot.status', hotspot.resolution || hotspot.status)}
</span>
- {hotspot.assignee && hotspot.assignee.name && (
+ {hotspot.assigneeUser && hotspot.assigneeUser.name && (
<>
<span className="huge-spacer-left">{translate('assigned_to')}:</span>
<strong className="little-spacer-left">
- {hotspot.assignee.active
- ? hotspot.assignee.name
- : translateWithParameters('user.x_deleted', hotspot.assignee.name)}
+ {hotspot.assigneeUser.active
+ ? hotspot.assigneeUser.name
+ : translateWithParameters('user.x_deleted', hotspot.assigneeUser.name)}
</strong>
</>
)}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+
+import { sanitize } from 'dompurify';
import * as React from 'react';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
return (
<>
{history.map((elt, i) => (
- <React.Fragment key={`${elt.user.name}-${elt.date}`}>
+ <React.Fragment key={i}>
{i > 0 && <hr />}
- <div>
+ <div className="padded">
<div className="display-flex-center">
{elt.user.name && (
<>
{translate('hotspots.tabs.review_history.created')}
</span>
)}
+ {elt.type === ReviewHistoryType.Comment && (
+ <span className="little-spacer-left">
+ {translate('hotspots.tabs.review_history.comment')}
+ </span>
+ )}
<span className="little-spacer-left little-spacer-right">-</span>
</>
)}
{elt.type === ReviewHistoryType.Diff && elt.diffs && (
<div className="spacer-top">
- {elt.diffs.map(diff => (
- <IssueChangelogDiff
- diff={diff}
- key={`${diff.key}-${diff.oldValue}-${diff.newValue}`}
- />
+ {elt.diffs.map((diff, i) => (
+ <IssueChangelogDiff diff={diff} key={i} />
))}
</div>
)}
+
+ {elt.type === ReviewHistoryType.Comment && elt.html && (
+ <div
+ className="spacer-top markdown"
+ dangerouslySetInnerHTML={{ __html: sanitize(elt.html) }}
+ />
+ )}
</div>
</React.Fragment>
))}
selected={currentTabKey}
tabs={tabs}
/>
- <div className="boxed-group big-padded">
+ <div className="bordered">
{typeof currentTab.content === 'string' ? (
<div
- className="markdown"
+ className="markdown big-padded"
dangerouslySetInnerHTML={{ __html: sanitize(currentTab.content) }}
/>
) : (
'unassigned'
);
expect(
- shallowRender({ hotspot: mockHotspot({ assignee: mockUser({ active: false }) }) })
+ shallowRender({ hotspot: mockHotspot({ assigneeUser: mockUser({ active: false }) }) })
).toMatchSnapshot('deleted assignee');
expect(
shallowRender({
hotspot: mockHotspot({
- assignee: mockUser({ name: undefined, login: 'assignee_login' })
+ assigneeUser: mockUser({ name: undefined, login: 'assignee_login' })
})
})
).toMatchSnapshot('assignee without name');
{ key: 'test', oldValue: 'old', newValue: 'new' },
{ key: 'test-1', oldValue: 'old-1', newValue: 'new-1' }
]
+ }),
+ mockHotspotReviewHistoryElement({
+ type: ReviewHistoryType.Comment,
+ html: '<strong>bold text</strong>'
})
]}
{...props}
highlightedSymbols={Array []}
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
loading={true}
index={0}
issue={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
issuesByLine={Object {}}
<HotspotSnippetContainer
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotViewerTabs
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotSnippetContainer
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotViewerTabs
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotSnippetContainer
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
"login": "assignee_login",
"name": undefined,
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotViewerTabs
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
"login": "assignee_login",
"name": undefined,
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotSnippetContainer
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": false,
"local": true,
"login": "john.doe",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotViewerTabs
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": false,
"local": true,
"login": "john.doe",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
>
hotspot.status.FIXED
</span>
+ <span
+ className="huge-spacer-left"
+ >
+ assigned_to
+ :
+ </span>
+ <strong
+ className="little-spacer-left"
+ >
+ John Doe
+ </strong>
</div>
<HotspotSnippetContainer
hotspot={
Object {
"assignee": undefined,
- "author": Object {
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
hotspot={
Object {
"assignee": undefined,
- "author": Object {
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ "author": "author",
+ "authorUser": Object {
+ "active": true,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotActions
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
onSubmit={[MockFunction]}
<HotspotSnippetContainer
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
<HotspotViewerTabs
hotspot={
Object {
- "assignee": Object {
+ "assignee": "assignee",
+ "assigneeUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "assignee",
"name": "John Doe",
},
- "author": Object {
+ "author": "author",
+ "authorUser": Object {
"active": true,
"local": true,
- "login": "john.doe",
+ "login": "author",
"name": "John Doe",
},
"changelog": Array [],
+ "comment": Array [],
"component": Object {
"breadcrumbs": Array [],
"key": "my-project",
"startOffset": 26,
},
"updateDate": "2013-05-13T17:55:42+0200",
+ "users": Array [
+ Object {
+ "active": true,
+ "local": true,
+ "login": "assignee",
+ "name": "John Doe",
+ },
+ Object {
+ "active": true,
+ "local": true,
+ "login": "author",
+ "name": "John Doe",
+ },
+ ],
}
}
/>
exports[`should render correctly 1`] = `
<Fragment>
- <div>
+ <div
+ className="padded"
+ >
<div
className="display-flex-center"
>
</div>
</div>
<hr />
- <div>
+ <div
+ className="padded"
+ >
<div
className="display-flex-center"
>
</div>
</div>
<hr />
- <div>
+ <div
+ className="padded"
+ >
<div
className="display-flex-center"
>
</div>
</div>
<hr />
- <div>
+ <div
+ className="padded"
+ >
<div
className="display-flex-center"
>
"oldValue": "old",
}
}
- key="test-old-new"
+ key="0"
/>
<IssueChangelogDiff
diff={
"oldValue": "old-1",
}
}
- key="test-1-old-1-new-1"
+ key="1"
/>
</div>
</div>
+ <hr />
+ <div
+ className="padded"
+ >
+ <div
+ className="display-flex-center"
+ >
+ <Connect(Avatar)
+ className="little-spacer-right"
+ name="John Doe"
+ size={20}
+ />
+ <strong>
+ John Doe
+ </strong>
+ <span
+ className="little-spacer-left"
+ >
+ hotspots.tabs.review_history.comment
+ </span>
+ <span
+ className="little-spacer-left little-spacer-right"
+ >
+ -
+ </span>
+ <DateTimeFormatter
+ date="2019-09-13T17:55:42+0200"
+ />
+ </div>
+ <div
+ className="spacer-top markdown"
+ dangerouslySetInnerHTML={
+ Object {
+ "__html": "<strong>bold text</strong>",
+ }
+ }
+ />
+ </div>
</Fragment>
`;
"type": 0,
"user": Object {
"active": true,
- "avatar": undefined,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
},
}
/>
<div
- className="boxed-group big-padded"
+ className="bordered"
>
<div
- className="markdown"
+ className="markdown big-padded"
dangerouslySetInnerHTML={
Object {
"__html": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
"type": 0,
"user": Object {
"active": true,
- "avatar": undefined,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
},
}
/>
<div
- className="boxed-group big-padded"
+ className="bordered"
>
<div
- className="markdown"
+ className="markdown big-padded"
dangerouslySetInnerHTML={
Object {
"__html": "<p>This a <strong>strong</strong> message about fixing !</p>",
"type": 0,
"user": Object {
"active": true,
- "avatar": undefined,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
},
}
/>
<div
- className="boxed-group big-padded"
+ className="bordered"
>
<HotspotViewerReviewHistoryTab
history={
"type": 0,
"user": Object {
"active": true,
- "avatar": undefined,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
},
"type": 0,
"user": Object {
"active": true,
- "avatar": undefined,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
},
}
/>
<div
- className="boxed-group big-padded"
+ className="bordered"
>
<div
- className="markdown"
+ className="markdown big-padded"
dangerouslySetInnerHTML={
Object {
"__html": "<p>This a <strong>strong</strong> message about risk !</p>",
"type": 0,
"user": Object {
"active": true,
- "avatar": undefined,
+ "local": true,
+ "login": "author",
"name": "John Doe",
},
},
}
/>
<div
- className="boxed-group big-padded"
+ className="bordered"
>
<div
- className="markdown"
+ className="markdown big-padded"
dangerouslySetInnerHTML={
Object {
"__html": "<p>This a <strong>strong</strong> message about vulnerability !</p>",
type: ReviewHistoryType.Creation,
date: hotspot.creationDate,
user: {
- avatar: hotspot.author.avatar,
- name: hotspot.author.name || hotspot.author.login,
- active: hotspot.author.active
+ ...hotspot.authorUser,
+ name: hotspot.authorUser.name || hotspot.authorUser.login
}
});
}
- if (hotspot.changelog) {
+ if (hotspot.changelog && hotspot.changelog.length > 0) {
history.push(
...hotspot.changelog.map(log => ({
type: ReviewHistoryType.Diff,
date: log.creationDate,
user: {
+ active: log.isUserActive,
avatar: log.avatar,
- name: log.userName || log.user,
- active: log.isUserActive
+ name: log.userName || log.user
},
diffs: log.diffs
}))
);
}
+ if (hotspot.comment && hotspot.comment.length > 0) {
+ history.push(
+ ...hotspot.comment.map(comment => ({
+ type: ReviewHistoryType.Comment,
+ date: comment.createdAt,
+ user: {
+ ...comment.user,
+ name: comment.user.name || comment.user.login
+ },
+ html: comment.htmlText
+ }))
+ );
+ }
+
return sortBy(history, elt => elt.date);
}
}
export function mockHotspot(overrides?: Partial<Hotspot>): Hotspot {
+ const assigneeUser = mockUser({ login: 'assignee' });
+ const authorUser = mockUser({ login: 'author' });
return {
- assignee: mockUser(),
- author: mockUser(),
+ assignee: 'assignee',
+ assigneeUser,
+ author: 'author',
+ authorUser,
changelog: [],
+ comment: [],
component: mockComponent({ qualifier: ComponentQualifier.File }),
creationDate: '2013-05-13T17:55:41+0200',
key: '01fc972e-2a3c-433e-bcae-0bd7f88f5123',
endOffset: 83
},
updateDate: '2013-05-13T17:55:42+0200',
+ users: [assigneeUser, authorUser],
...overrides
};
}
}
export interface Hotspot {
- assignee?: Pick<T.UserBase, 'active' | 'login' | 'name'>;
- author: Pick<T.UserBase, 'active' | 'avatar' | 'login' | 'name'>;
- changelog?: T.IssueChangelog[];
+ assignee?: string;
+ assigneeUser?: T.UserBase;
+ author: string;
+ authorUser: T.UserBase;
+ changelog: T.IssueChangelog[];
+ comment: HotspotComment[];
component: T.Component;
creationDate: string;
key: string;
status: string;
textRange: T.TextRange;
updateDate: string;
+ users: T.UserBase[];
}
export interface HotspotUpdateFields {
vulnerabilityProbability: RiskExposure;
}
+export interface HotspotComment {
+ key: string;
+ htmlText: string;
+ markdown: string;
+ updatable: boolean;
+ createdAt: string;
+ login: string;
+ user: T.UserBase;
+}
+
export interface ReviewHistoryElement {
type: ReviewHistoryType;
date: string;
user: Pick<T.UserBase, 'active' | 'avatar' | 'name'>;
diffs?: T.IssueChangelogDiff[];
+ html?: string;
}
export enum ReviewHistoryType {
Creation,
- Diff
+ Diff,
+ Comment
}
export interface HotspotSearchResponse {
hotspots.tabs.fix_recommendations=How can you fix it?
hotspots.tabs.review_history=Review history
hotspots.tabs.review_history.created=created Security Hotspot
+hotspots.tabs.review_history.comment=added a comment
hotspot.change_status.REVIEWED=Change status
hotspot.change_status.TO_REVIEW=Review Hotspot