terriajs
Version:
Geospatial data visualization platform.
208 lines (193 loc) • 6.01 kB
JSX
import classNames from "classnames";
import { runInAction } from "mobx";
import { observer } from "mobx-react";
import PropTypes from "prop-types";
import { Component } from "react";
import { withTranslation } from "react-i18next";
import styled from "styled-components";
import defined from "terriajs-cesium/Source/Core/defined";
import MappableMixin from "../../ModelMixins/MappableMixin";
import DataCatalogTab from "./Tabs/DataCatalogTab";
import MyDataTab from "./Tabs/MyDataTab/MyDataTab";
import Styles from "./tabs.scss";
class Tabs extends Component {
static propTypes = {
terria: PropTypes.object.isRequired,
viewState: PropTypes.object.isRequired,
tabs: PropTypes.array,
t: PropTypes.func.isRequired
};
async onFileAddFinished(files) {
const file = files.find((f) => MappableMixin.isMixedInto(f));
if (file) {
const result = await this.props.viewState.viewCatalogMember(file);
if (result.error) {
result.raiseError(this.props.terria);
} else {
if (!file.disableZoomTo) {
this.props.terria.currentViewer.zoomTo(file, 1);
}
}
}
this.props.viewState.myDataIsUploadView = false;
}
async onUrlAddFinished() {
this.props.viewState.openAddData();
}
getTabs() {
const { t } = this.props;
// This can be passed in as prop
if (this.props.tabs) {
return this.props.tabs;
}
const myDataTab = {
title: "my-data",
name: t("addData.myData"),
category: "my-data",
panel: (
<MyDataTab
terria={this.props.terria}
viewState={this.props.viewState}
onFileAddFinished={(files) => this.onFileAddFinished(files)}
onUrlAddFinished={() => this.onUrlAddFinished()}
/>
)
};
if (this.props.terria.configParameters.tabbedCatalog) {
return [].concat(
this.props.terria.catalog.group.memberModels
.filter(
(member) => member !== this.props.terria.catalog.userAddedDataGroup
)
.map((member) => ({
name: member.nameInCatalog,
title: `data-catalog-${member.name}`,
category: "data-catalog",
idInCategory: member.uniqueId,
panel: (
<DataCatalogTab
items={member.memberModels || [member]}
searchPlaceholder={t("addData.searchPlaceholderWhole")}
/>
)
})),
[myDataTab]
);
} else {
return [
{
name: t("addData.data"),
title: "data-catalog",
category: "data-catalog",
panel: (
<DataCatalogTab
items={this.props.terria.catalog.group.memberModels}
searchPlaceholder={t("addData.searchPlaceholder")}
/>
)
},
myDataTab
];
}
}
async activateTab(category, idInCategory) {
runInAction(() => {
this.props.viewState.activeTabCategory = category;
if (this.props.terria.configParameters.tabbedCatalog) {
this.props.viewState.activeTabIdInCategory = idInCategory;
if (category === "data-catalog") {
const member = this.props.terria.catalog.group.memberModels.filter(
(m) => m.uniqueId === idInCategory
)[0];
// If member was found and member can be opened, open it (causes CkanCatalogGroups to fetch etc.)
if (defined(member)) {
this.props.viewState
.viewCatalogMember(member)
.then((result) => result.raiseError(this.props.viewState.terria));
}
}
}
});
}
render() {
const tabs = this.getTabs();
const sameCategory = tabs.filter(
(t) => t.category === this.props.viewState.activeTabCategory
);
const currentTab =
sameCategory.filter(
(t) => t.idInCategory === this.props.viewState.activeTabIdInCategory
)[0] ||
sameCategory[0] ||
tabs[0];
return (
<div className={Styles.tabs}>
<ul
className={Styles.tabList}
role="tablist"
style={{ padding: "10px 24px", background: "#fff" }}
>
{tabs.map((item, i) => (
<li
key={i}
id={"tablist--" + item.title}
className={Styles.tabListItem}
role="tab"
aria-controls={"panel--" + item.title}
aria-selected={item === currentTab}
>
<ButtonTab
type="button"
onClick={this.activateTab.bind(
this,
item.category,
item.idInCategory
)}
className={classNames(Styles.btnTab, {
[Styles.btnSelected]: item === currentTab
})}
isCurrent={item === currentTab}
>
{item.name}
</ButtonTab>
</li>
))}
</ul>
<section
key={currentTab.title}
id={"panel--" + currentTab.title}
className={classNames(Styles.tabPanel, Styles.isActive)}
aria-labelledby={"tablist--" + currentTab.title}
role="tabpanel"
tabIndex="0"
>
<div className={Styles.panelContent}>{currentTab.panel}</div>
</section>
</div>
);
}
}
const ButtonTab = styled.button`
${(props) => `
/* overrides padding and margin in scss */
padding: 10px 12px;
margin: 0;
background: transparent;
color: ${props.theme.dark};
border: 1px solid transparent;
&:hover,
&:focus {
background: ${props.theme.textLight};
${props.isCurrent && `border: 1px solid ${props.theme.greyLighter};`}
}
${
props.isCurrent &&
`
background: ${props.theme.textLight};
border: 1px solid ${props.theme.greyLighter};
`
}
`}
`;
export default withTranslation()(Tabs);