aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/projects-admin/search.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src/main/js/apps/projects-admin/search.js')
-rw-r--r--server/sonar-web/src/main/js/apps/projects-admin/search.js159
1 files changed, 159 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects-admin/search.js b/server/sonar-web/src/main/js/apps/projects-admin/search.js
new file mode 100644
index 00000000000..24817c916f9
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects-admin/search.js
@@ -0,0 +1,159 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact 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 _ from 'underscore';
+import React from 'react';
+import { TYPE, QUALIFIERS_ORDER } from './constants';
+import DeleteView from './delete-view';
+import RadioToggle from '../../components/controls/RadioToggle';
+import Checkbox from '../../components/controls/Checkbox';
+import { translate } from '../../helpers/l10n';
+
+export default React.createClass({
+ propTypes: {
+ onSearch: React.PropTypes.func.isRequired
+ },
+
+ onSubmit(e) {
+ e.preventDefault();
+ this.search();
+ },
+
+ search() {
+ const q = this.refs.input.value;
+ this.props.onSearch(q);
+ },
+
+ getTypeOptions() {
+ return [
+ { value: TYPE.ALL, label: 'All' },
+ { value: TYPE.PROVISIONED, label: 'Provisioned' },
+ { value: TYPE.GHOSTS, label: 'Ghosts' }
+ ];
+ },
+
+ getQualifierOptions() {
+ const options = this.props.topLevelQualifiers.map(q => {
+ return { value: q, label: translate('qualifiers', q) };
+ });
+ return _.sortBy(options, option => {
+ return QUALIFIERS_ORDER.indexOf(option.value);
+ });
+ },
+
+ renderCheckbox() {
+ const isAllChecked = this.props.projects.length > 0 &&
+ this.props.selection.length === this.props.projects.length;
+ const thirdState = this.props.projects.length > 0 &&
+ this.props.selection.length > 0 &&
+ this.props.selection.length < this.props.projects.length;
+ const checked = isAllChecked || thirdState;
+ return (
+ <Checkbox
+ checked={checked}
+ thirdState={thirdState}
+ onCheck={this.onCheck}/>
+ );
+ },
+
+ renderSpinner() {
+ return <i className="spinner"/>;
+ },
+
+ onCheck(checked) {
+ if (checked) {
+ this.props.onAllSelected();
+ } else {
+ this.props.onAllDeselected();
+ }
+ },
+
+ renderGhostsDescription () {
+ if (this.props.type !== TYPE.GHOSTS || !this.props.ready) {
+ return null;
+ }
+ return <div className="spacer-top alert alert-info">{translate('bulk_deletion.ghosts.description')}</div>;
+ },
+
+ deleteProjects() {
+ new DeleteView({
+ deleteProjects: this.props.deleteProjects
+ }).render();
+ },
+
+ renderQualifierFilter() {
+ const options = this.getQualifierOptions();
+ if (options.length < 2) {
+ return null;
+ }
+ return (
+ <td className="thin nowrap text-middle">
+ <RadioToggle
+ options={this.getQualifierOptions()}
+ value={this.props.qualifiers}
+ name="projects-qualifier"
+ onCheck={this.props.onQualifierChanged}/>
+ </td>
+ );
+ },
+
+ render() {
+ const isSomethingSelected = this.props.projects.length > 0 && this.props.selection.length > 0;
+ return (
+ <div className="panel panel-vertical bordered-bottom spacer-bottom">
+ <table className="data">
+ <tbody>
+ <tr>
+ <td className="thin text-middle">
+ {this.props.ready ? this.renderCheckbox() : this.renderSpinner()}
+ </td>
+ {this.renderQualifierFilter()}
+ <td className="thin nowrap text-middle">
+ <RadioToggle
+ options={this.getTypeOptions()}
+ value={this.props.type}
+ name="projects-type"
+ onCheck={this.props.onTypeChanged}/>
+ </td>
+ <td className="text-middle">
+ <form onSubmit={this.onSubmit} className="search-box">
+ <button className="search-box-submit button-clean">
+ <i className="icon-search"></i>
+ </button>
+ <input onChange={this.search}
+ value={this.props.query}
+ ref="input"
+ className="search-box-input"
+ type="search"
+ placeholder="Search"/>
+ </form>
+ </td>
+ <td className="thin text-middle">
+ <button onClick={this.deleteProjects} className="button-red"
+ disabled={!isSomethingSelected}>Delete
+ </button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ {this.renderGhostsDescription()}
+ </div>
+ );
+ }
+});