blob: e341d44e2a41d99464e8f968072b27556edf7998 [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
import PropTypes from 'prop-types';
import React from 'react';
import { Collapse } from 'react-bootstrap';
import Components from '../../../components/react-components';
import ReactDOM from 'react-dom';
import FauxtonAPI from '../../../../core/api';
const { MenuDropDown } = Components;
export default class IndexSection extends React.Component {
static propTypes = {
urlNamespace: PropTypes.string.isRequired,
indexLabel: PropTypes.string.isRequired,
database: PropTypes.object.isRequired,
designDocName: PropTypes.string.isRequired,
items: PropTypes.array.isRequired,
isExpanded: PropTypes.bool.isRequired,
selectedIndex: PropTypes.string.isRequired,
onDelete: PropTypes.func.isRequired,
onClone: PropTypes.func.isRequired,
showDeleteIndexModal: PropTypes.func.isRequired,
showCloneIndexModal: PropTypes.func.isRequired,
isPartitioned: PropTypes.bool.isRequired,
selectedPartitionKey: PropTypes.string
};
state = {
placement: 'bottom'
};
// this dynamically changes the placement of the menu (top/bottom) to prevent it going offscreen and causing some
// unsightly shifting
setPlacement = (rowId) => {
const rowTop = document.getElementById(rowId).getBoundingClientRect().top;
const toggleHeight = 150; // the height of the menu overlay, arrow, view row
const placement = (rowTop + toggleHeight > window.innerHeight) ? 'top' : 'bottom';
this.setState({ placement: placement });
};
getItemLinks = (indexName) => {
let listItems = [{
title: 'Edit',
icon: 'fonticon-file-code-o',
onClick: () => {this.indexAction('edit', { indexName: indexName, onEdit: this.props.onEdit });}
},
{
title: 'Clone',
icon: 'fonticon-files-o',
onClick: () => {this.indexAction('clone', { indexName: indexName, onClone: this.props.onClone });}
},
{
title: 'Delete',
icon: 'fonticon-trash',
onClick: () => {this.indexAction('delete', { indexName: indexName, onDelete: this.props.onDelete });}
}];
return [{
title: "Manage View",
links: listItems
}];
};
createItems = () => {
// sort the indexes alphabetically
const sortedItems = this.props.items.sort();
return _.map(sortedItems, (indexName, index) => {
let href = FauxtonAPI.urls(this.props.urlNamespace, 'app', encodeURIComponent(this.props.database.id), encodeURIComponent(this.props.designDocName));
if (this.props.selectedPartitionKey) {
href = FauxtonAPI.urls('partitioned_' + this.props.urlNamespace, 'app',
encodeURIComponent(this.props.database.id),
encodeURIComponent(this.props.selectedPartitionKey),
encodeURIComponent(this.props.designDocName));
}
const className = (this.props.selectedIndex === indexName) ? 'active' : '';
const links = this.getItemLinks(indexName);
return (
<li className={className} key={index}>
<a
id={this.props.designDocName + '_' + indexName}
href={"#/" + href + encodeURIComponent(indexName)}
className="toggle-view">
{indexName}
</a>
<div className='new-button add-dropdown sidebar-sub-item'>
<MenuDropDown links={links} icon={"fonticon-wrench"}/>
</div>
</li>
);
});
};
indexAction = (action, params) => {
switch (action) {
case 'delete':
this.props.showDeleteIndexModal(params.indexName, this.props.designDocName, this.props.indexLabel, params.onDelete);
break;
case 'clone':
this.props.showCloneIndexModal(params.indexName, this.props.designDocName, this.props.indexLabel, params.onClone);
break;
case 'edit':
params.onEdit(this.props.database.id, this.props.selectedPartitionKey, this.props.designDocName, params.indexName);
break;
}
};
toggle = () => {
this.props.toggle(this.props.designDocName, this.props.title);
};
render() {
// if this section has no content, omit it to prevent clutter. Otherwise it would show a toggle option that
// would hide/show nothing
if (this.props.items.length === 0) {
return null;
}
let toggleClassNames = 'accordion-header index-group-header';
let toggleBodyClassNames = 'index-list accordion-body collapse';
if (this.props.isExpanded) {
toggleClassNames += ' down';
toggleBodyClassNames += ' in';
}
const title = this.props.title;
const designDocName = this.props.designDocName;
const linkId = "nav-design-function-" + designDocName + this.props.selector;
return (
<li id={linkId}>
<a className={toggleClassNames} data-toggle="collapse" onClick={this.toggle}>
<div className="fonticon-play"></div>
{title}
</a>
<Collapse in={this.props.isExpanded}>
<ul className={toggleBodyClassNames}>
{this.createItems()}
</ul>
</Collapse>
</li>
);
}
}