Skip to content
Snippets Groups Projects
Unverified Commit 027f724f authored by Tom Robinson's avatar Tom Robinson
Browse files

Add page titles

parent 4c6630e3
No related branches found
No related tags found
No related merge requests found
/* eslint "react/prop-types": "warn" */
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import title from "metabase/hoc/Title";
import MetabaseSettings from "metabase/lib/settings";
import DeleteDatabaseModal from "../components/DeleteDatabaseModal.jsx";
......@@ -40,6 +41,7 @@ const mapDispatchToProps = {
};
@connect(mapStateToProps, mapDispatchToProps)
@title(({ database }) => database && database.name)
export default class DatabaseEditApp extends Component {
static propTypes = {
database: PropTypes.object,
......
import React, { Component, PropTypes } from "react";
import { Route, IndexRedirect } from 'react-router';
import { IndexRedirect } from 'react-router';
import { Route } from "metabase/hoc/Title";
import DataPermissionsApp from "./containers/DataPermissionsApp.jsx";
import DatabasesPermissionsApp from "./containers/DatabasesPermissionsApp.jsx";
......@@ -7,7 +8,7 @@ import SchemasPermissionsApp from "./containers/SchemasPermissionsApp.jsx";
import TablesPermissionsApp from "./containers/TablesPermissionsApp.jsx";
const getRoutes = (store) =>
<Route path="permissions" component={DataPermissionsApp}>
<Route title="Permissions" path="permissions" component={DataPermissionsApp}>
<IndexRedirect to="databases" />
<Route path="databases" component={DatabasesPermissionsApp} />
<Route path="databases/:databaseId/schemas" component={SchemasPermissionsApp} />
......
import React, { Component, PropTypes } from "react";
import { Link } from "react-router";
import { connect } from "react-redux";
import title from "metabase/hoc/Title";
import MetabaseAnalytics from "metabase/lib/analytics";
import AdminLayout from "metabase/components/AdminLayout.jsx";
......@@ -40,6 +42,7 @@ const mapDispatchToProps = {
}
@connect(mapStateToProps, mapDispatchToProps)
@title(({ activeSection }) => activeSection && activeSection.name)
export default class SettingsEditorApp extends Component {
static propTypes = {
sections: PropTypes.array.isRequired,
......
......@@ -3,6 +3,7 @@
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import title from "metabase/hoc/Title";
import Dashboard from "../components/Dashboard.jsx";
......@@ -40,6 +41,7 @@ const mapDispatchToProps = {
}
@connect(mapStateToProps, mapDispatchToProps)
@title(({ dashboard }) => dashboard && dashboard.name)
export default class DashboardApp extends Component {
render() {
return <Dashboard {...this.props} />;
......
......@@ -4,15 +4,34 @@ import _ from "underscore";
const componentStack = [];
let SEPARATOR = " · ";
let HIERARCHICAL = true;
let BASE_NAME = null;
export const setSeparator = (separator) => SEPARATOR = separator;
export const setHierarchical = (hierarchical) => HIERARCHICAL = hierarchical;
export const setBaseName = (baseName) => BASE_NAME = baseName;
const updateDocumentTitle = _.debounce(() => {
// update with the top-most title
for (let i = componentStack.length - 1; i >= 0; i--) {
const title = componentStack[i]._documentTitle;
if (title) {
if (document.title !== title) {
document.title = title;
if (HIERARCHICAL) {
document.title = componentStack
.map(component => component._documentTitle)
.filter(title => title)
.reverse()
.join(SEPARATOR);
} else {
// update with the top-most title
for (let i = componentStack.length - 1; i >= 0; i--) {
let title = componentStack[i]._documentTitle;
if (title) {
if (BASE_NAME) {
title += SEPARATOR + BASE_NAME;
}
if (document.title !== title) {
document.title = title;
}
break;
}
break;
}
}
})
......@@ -59,9 +78,9 @@ import { Route as _Route } from "react-router";
// react-router Route wrapper that adds a `title` property
export class Route extends _Route {
static createRouteFromReactElement(element) {
if (element.props.component && element.props.title) {
if (element.props.title) {
element = React.cloneElement(element, {
component: title(element.props.title)(element.props.component)
component: title(element.props.title)(element.props.component || (({ children }) => children))
});
}
return _Route.createRouteFromReactElement(element);
......
......@@ -3,6 +3,8 @@ import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import title from "metabase/hoc/Title";
import PulseEdit from "../components/PulseEdit.jsx";
import { editPulseSelectors } from "../selectors";
......@@ -39,6 +41,7 @@ const mapDispatchToProps = {
};
@connect(mapStateToProps, mapDispatchToProps)
@title(({ pulse }) => pulse && pulse.name)
export default class PulseEditApp extends Component {
render() {
return (
......
......@@ -126,7 +126,7 @@ const mapDispatchToProps = {
};
@connect(mapStateToProps, mapDispatchToProps)
@title(({ card }) => (card && card.name) ? `${card.name} | Metabase` : `Metabase`)
@title(({ card }) => (card && card.name) || "Question")
export default class QueryBuilder extends Component {
constructor(props, context) {
......
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { push, replace, goBack } from "react-router-redux";
import title from "metabase/hoc/Title";
import Icon from "metabase/components/Icon";
import HeaderWithBack from "metabase/components/HeaderWithBack";
......@@ -27,6 +28,7 @@ const mapDispatchToProps = ({
})
@connect(mapStateToProps, mapDispatchToProps)
@title(({ collection }) => collection && collection.name)
export default class CollectionPage extends Component {
componentWillMount () {
this.props.loadCollections();
......
......@@ -138,7 +138,7 @@ export const getRoutes = (store) =>
<Route path="/auth">
<IndexRedirect to="/auth/login" />
<Route component={IsNotAuthenticated}>
<Route path="login" component={LoginApp} />
<Route path="login" title="Login" component={LoginApp} />
</Route>
<Route path="logout" component={LogoutApp} />
<Route path="forgot_password" component={ForgotPasswordApp} />
......@@ -152,17 +152,17 @@ export const getRoutes = (store) =>
<Route path="/" component={HomepageApp} />
{/* DASHBOARD */}
<Route path="/dashboard/:dashboardId" component={DashboardApp} />
<Route path="/dashboard/:dashboardId" title="Dashboard" component={DashboardApp} />
{/* QUERY BUILDER */}
<Route path="/question" component={QueryBuilder} />
<Route path="/question/:cardId" component={QueryBuilder} />
{/* QUESTIONS */}
<Route path="/questions">
<Route path="/questions" title="Questions">
<IndexRoute component={QuestionIndex} />
<Route path="search" component={SearchResults} />
<Route path="archive" component={Archive} />
<Route path="search" title={({ location: { query: { q } }}) => "Search: " + q} component={SearchResults} />
<Route path="archive" title="Archive" component={Archive} />
<Route path="collections/:collectionSlug" component={CollectionPage} />
</Route>
......@@ -183,9 +183,9 @@ export const getRoutes = (store) =>
</Route>
{/* REFERENCE */}
<Route path="/reference" component={ReferenceApp}>
<Route path="/reference" title="Data Reference" component={ReferenceApp}>
<IndexRedirect to="/reference/guide" />
<Route path="guide" component={ReferenceGettingStartedGuide} />
<Route path="guide" title="Getting Started" component={ReferenceGettingStartedGuide} />
<Route path="metrics" component={ReferenceEntityList} />
<Route path="metrics/:metricId" component={ReferenceEntity} />
<Route path="metrics/:metricId/questions" component={ReferenceEntityList} />
......@@ -206,23 +206,27 @@ export const getRoutes = (store) =>
</Route>
{/* PULSE */}
<Route path="/pulse" component={PulseListApp} />
<Route path="/pulse/create" component={PulseEditApp} />
<Route path="/pulse/:pulseId" component={PulseEditApp} />
<Route path="/pulse" title="Pulses">
<IndexRoute component={PulseListApp} />
<Route path="create" component={PulseEditApp} />
<Route path=":pulseId" component={PulseEditApp} />
</Route>
{/* USER */}
<Route path="/user/edit_current" component={UserSettingsApp} />
</Route>
{/* ADMIN */}
<Route path="/admin" component={IsAdmin}>
<Route path="/admin" title="Admin" component={IsAdmin}>
<IndexRedirect to="/admin/settings" />
<Route path="databases" component={DatabaseListApp} />
<Route path="databases/create" component={DatabaseEditApp} />
<Route path="databases/:databaseId" component={DatabaseEditApp} />
<Route path="databases" title="Databases">
<IndexRoute component={DatabaseListApp} />
<Route path="create" component={DatabaseEditApp} />
<Route path=":databaseId" component={DatabaseEditApp} />
</Route>
<Route path="datamodel">
<Route path="datamodel" title="Data Model">
<IndexRedirect to="database" />
<Route path="database" component={MetadataEditorApp} />
<Route path="database/:databaseId" component={MetadataEditorApp} />
......@@ -236,16 +240,20 @@ export const getRoutes = (store) =>
</Route>
{/* PEOPLE */}
<Route path="people" component={AdminPeopleApp}>
<Route path="people" title="People" component={AdminPeopleApp}>
<IndexRoute component={PeopleListingApp} />
<Route path="groups">
<Route path="groups" title="Groups">
<IndexRoute component={GroupsListingApp} />
<Route path=":groupId" component={GroupDetailApp} />
</Route>
</Route>
<Route path="settings" component={SettingsEditorApp} />
<Route path="settings/:section" component={SettingsEditorApp} />
{/* SETTINGS */}
<Route path="settings" title="Settings">
<IndexRedirect to="/admin/settings/setup" />
{/* <IndexRoute component={SettingsEditorApp} /> */}
<Route path=":section" component={SettingsEditorApp} />
</Route>
{getAdminPermissionsRoutes(store)}
</Route>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment