aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/overview/meta
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2017-08-17 21:39:59 +0200
committerJanos Gyerik <janos.gyerik@sonarsource.com>2017-09-12 11:34:36 +0200
commitcff416d7f9910c258bc8d7175c08afff96a9eb2a (patch)
tree78500908a2afde31b28ef938d4d61609d448f279 /server/sonar-web/src/main/js/apps/overview/meta
parent139467cf51932ba232190f363ad864e60eb3fd4d (diff)
downloadsonarqube-cff416d7f9910c258bc8d7175c08afff96a9eb2a.tar.gz
sonarqube-cff416d7f9910c258bc8d7175c08afff96a9eb2a.zip
SONAR-9702 Build UI for short-lived branches (#2371)
Diffstat (limited to 'server/sonar-web/src/main/js/apps/overview/meta')
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/Meta.js11
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js16
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/MetaTagsSelector.js89
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaTagsSelector-test.js61
-rw-r--r--server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaTags-test.js.snap3
5 files changed, 174 insertions, 6 deletions
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/Meta.js b/server/sonar-web/src/main/js/apps/overview/meta/Meta.js
index fd849228480..a79b44dbd41 100644
--- a/server/sonar-web/src/main/js/apps/overview/meta/Meta.js
+++ b/server/sonar-web/src/main/js/apps/overview/meta/Meta.js
@@ -30,7 +30,14 @@ import MetaSize from './MetaSize';
import MetaTags from './MetaTags';
import { areThereCustomOrganizations } from '../../../store/rootReducer';
-const Meta = ({ component, history, measures, areThereCustomOrganizations, router }) => {
+const Meta = ({
+ component,
+ history,
+ measures,
+ areThereCustomOrganizations,
+ onComponentChange,
+ router
+}) => {
const { qualifier, description, qualityProfiles, qualityGate } = component;
const isProject = qualifier === 'TRK';
@@ -53,7 +60,7 @@ const Meta = ({ component, history, measures, areThereCustomOrganizations, route
<MetaSize component={component} measures={measures} />
- {isProject && <MetaTags component={component} />}
+ {isProject && <MetaTags component={component} onComponentChange={onComponentChange} />}
{(isProject || isApplication) &&
<AnalysesList
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js
index b9d67b8e474..7254f0e2197 100644
--- a/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js
+++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaTags.js
@@ -19,9 +19,10 @@
*/
//@flow
import React from 'react';
+import { setProjectTags } from '../../../api/components';
import { translate } from '../../../helpers/l10n';
import TagsList from '../../../components/tags/TagsList';
-import ProjectTagsSelectorContainer from '../../projects/components/ProjectTagsSelectorContainer';
+import MetaTagsSelector from './MetaTagsSelector';
/*::
type Props = {
@@ -31,7 +32,8 @@ type Props = {
configuration?: {
showSettings?: boolean
}
- }
+ },
+ onComponentChange: {} => void
};
*/
@@ -104,6 +106,13 @@ export default class MetaTags extends React.PureComponent {
};
}
+ handleSetProjectTags = (tags /*: Array<string> */) => {
+ setProjectTags({ project: this.props.component.key, tags: tags.join(',') }).then(
+ () => this.props.onComponentChange({ tags }),
+ () => {}
+ );
+ };
+
render() {
const { tags, key } = this.props.component;
const { popupOpen, popupPosition } = this.state;
@@ -119,10 +128,11 @@ export default class MetaTags extends React.PureComponent {
</button>
{popupOpen &&
<div ref={tagsSelector => (this.tagsSelector = tagsSelector)}>
- <ProjectTagsSelectorContainer
+ <MetaTagsSelector
position={popupPosition}
project={key}
selectedTags={tags}
+ setProjectTags={this.handleSetProjectTags}
/>
</div>}
</div>
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaTagsSelector.js b/server/sonar-web/src/main/js/apps/overview/meta/MetaTagsSelector.js
new file mode 100644
index 00000000000..76e25c9c1f1
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaTagsSelector.js
@@ -0,0 +1,89 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.
+ */
+//@flow
+import React from 'react';
+import { debounce, without } from 'lodash';
+import TagsSelector from '../../../components/tags/TagsSelector';
+import { searchProjectTags } from '../../../api/components';
+
+/*::
+type Props = {
+ position: {},
+ project: string,
+ selectedTags: Array<string>,
+ setProjectTags: (Array<string>) => void
+};
+*/
+
+/*::
+type State = {
+ searchResult: Array<string>
+};
+*/
+
+const LIST_SIZE = 10;
+
+export default class MetaTagsSelector extends React.PureComponent {
+ /*:: props: Props; */
+ /*:: state: State; */
+
+ constructor(props /*: Props */) {
+ super(props);
+ this.state = { searchResult: [] };
+ this.onSearch = debounce(this.onSearch, 250);
+ }
+
+ componentDidMount() {
+ this.onSearch('');
+ }
+
+ onSearch = (query /*: string */) => {
+ searchProjectTags({
+ q: query || '',
+ ps: Math.min(this.props.selectedTags.length - 1 + LIST_SIZE, 100)
+ }).then(result => {
+ this.setState({
+ searchResult: result.tags
+ });
+ });
+ };
+
+ onSelect = (tag /*: string */) => {
+ this.props.setProjectTags([...this.props.selectedTags, tag]);
+ };
+
+ onUnselect = (tag /*: string */) => {
+ this.props.setProjectTags(without(this.props.selectedTags, tag));
+ };
+
+ render() {
+ return (
+ <TagsSelector
+ position={this.props.position}
+ tags={this.state.searchResult}
+ selectedTags={this.props.selectedTags}
+ listSize={LIST_SIZE}
+ onSearch={this.onSearch}
+ onSelect={this.onSelect}
+ onUnselect={this.onUnselect}
+ />
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaTagsSelector-test.js b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaTagsSelector-test.js
new file mode 100644
index 00000000000..59744a204de
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/MetaTagsSelector-test.js
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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.
+ */
+/* eslint-disable import/order, import/first */
+import * as React from 'react';
+import { mount, shallow } from 'enzyme';
+import MetaTagsSelector from '../MetaTagsSelector';
+
+jest.mock('../../../../api/components', () => ({
+ searchProjectTags: jest.fn()
+}));
+
+jest.useFakeTimers();
+
+import { searchProjectTags } from '../../../../api/components';
+
+it('searches tags on mount', () => {
+ searchProjectTags.mockImplementation(() => Promise.resolve({ tags: ['foo', 'bar'] }));
+
+ mount(
+ <MetaTagsSelector position={{}} project="foo" selectedTags={[]} setProjectTags={jest.fn()} />
+ );
+ jest.runAllTimers();
+
+ expect(searchProjectTags).toBeCalledWith({ ps: 9, q: '' });
+});
+
+it('selects and deselects tags', () => {
+ const setProjectTags = jest.fn();
+ const wrapper = shallow(
+ <MetaTagsSelector
+ position={{}}
+ project="foo"
+ selectedTags={['foo', 'bar']}
+ setProjectTags={setProjectTags}
+ />
+ );
+
+ wrapper.find('TagsSelector').prop('onSelect')('baz');
+ expect(setProjectTags).toHaveBeenLastCalledWith(['foo', 'bar', 'baz']);
+
+ // note that the `selectedTags` is a prop and so it wasn't changed
+ wrapper.find('TagsSelector').prop('onUnselect')('bar');
+ expect(setProjectTags).toHaveBeenLastCalledWith(['foo']);
+});
diff --git a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaTags-test.js.snap b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaTags-test.js.snap
index 0eb1415ab03..875302462d5 100644
--- a/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaTags-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/overview/meta/__tests__/__snapshots__/MetaTags-test.js.snap
@@ -40,7 +40,7 @@ exports[`should open the tag selector on click 2`] = `
/>
</button>
<div>
- <Connect(ProjectTagsSelectorContainer)
+ <MetaTagsSelector
position={
Object {
"right": 0,
@@ -54,6 +54,7 @@ exports[`should open the tag selector on click 2`] = `
"bar",
]
}
+ setProjectTags={[Function]}
/>
</div>
</div>