aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/projects/search.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src/main/js/apps/projects/search.js')
-rw-r--r--server/sonar-web/src/main/js/apps/projects/search.js118
1 files changed, 118 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/apps/projects/search.js b/server/sonar-web/src/main/js/apps/projects/search.js
new file mode 100644
index 00000000000..5c5668af1e5
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projects/search.js
@@ -0,0 +1,118 @@
+import _ from 'underscore';
+import React from 'react';
+import {TYPE, QUALIFIERS_ORDER} from './constants';
+import DeleteView from './delete-view';
+import RadioToggle from '../../components/shared/radio-toggle';
+import Checkbox from '../../components/shared/checkbox';
+
+export default React.createClass({
+ propTypes: {
+ onSearch: React.PropTypes.func.isRequired
+ },
+
+ onSubmit(e) {
+ e.preventDefault();
+ this.search();
+ },
+
+ search() {
+ let q = React.findDOMNode(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() {
+ let options = this.props.topLevelQualifiers.map(q => {
+ return { value: q, label: window.t('qualifiers', q) };
+ });
+ return _.sortBy(options, option => {
+ return QUALIFIERS_ORDER.indexOf(option.value);
+ });
+ },
+
+ renderCheckbox() {
+ let isAllChecked = this.props.projects.length > 0 &&
+ this.props.selection.length === this.props.projects.length,
+ thirdState = this.props.projects.length > 0 &&
+ this.props.selection.length > 0 &&
+ this.props.selection.length < this.props.projects.length,
+ isChecked = isAllChecked || thirdState;
+ return <Checkbox onCheck={this.onCheck} initiallyChecked={isChecked} thirdState={thirdState}/>;
+ },
+
+ onCheck(checked) {
+ if (checked) {
+ this.props.onAllSelected();
+ } else {
+ this.props.onAllDeselected();
+ }
+ },
+
+ renderGhostsDescription () {
+ if (this.props.type !== TYPE.GHOSTS) {
+ return null;
+ }
+ return <div className="spacer-top alert alert-info">{window.t('bulk_deletion.ghosts.description')}</div>;
+ },
+
+ deleteProjects() {
+ new DeleteView({
+ deleteProjects: this.props.deleteProjects
+ }).render();
+ },
+
+ renderQualifierFilter() {
+ let 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() {
+ let isSomethingSelected = this.props.projects.length > 0 && this.props.selection.length > 0;
+ return (
+ <div className="panel panel-vertical bordered-bottom spacer-bottom">
+ <table className="data">
+ <tr>
+ <td className="thin text-middle">
+ {this.renderCheckbox()}
+ </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>
+ </table>
+ {this.renderGhostsDescription()}
+ </div>
+ );
+ }
+});