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

Misc polish

parent 3837cd6e
No related branches found
No related tags found
No related merge requests found
Showing
with 67 additions and 32 deletions
......@@ -4,7 +4,7 @@ import { Link } from "react-router";
import Icon from "metabase/components/Icon.jsx";
const EmptyState = ({ title, message, icon, image, action, link }) =>
<div className="text-centered text-brand-light">
<div className="text-centered text-brand-light my2">
{ title &&
<h2 className="text-brand mb4">{title}</h2>
}
......
......@@ -3,6 +3,7 @@ import React, { Component, PropTypes } from "react";
import Input from "metabase/components/Input.jsx";
import TitleAndDescription from "metabase/components/TitleAndDescription.jsx";
import cx from "classnames";
export default class Header extends Component {
......@@ -13,7 +14,7 @@ export default class Header extends Component {
};
render() {
const { isEditing, name, description, breadcrumb, buttons, className } = this.props;
const { isEditing, name, description, breadcrumb, buttons, className, badge } = this.props;
let titleAndDescription;
if (isEditing) {
......@@ -27,7 +28,7 @@ export default class Header extends Component {
if (name && description) {
titleAndDescription = (
<TitleAndDescription
title={name}
title={name}
description={description}
/>
);
......@@ -41,8 +42,11 @@ export default class Header extends Component {
}
return (
<div className={"QueryBuilder-section flex align-center " + className}>
<div className="Entity py1">
<div className={cx("QueryBuilder-section flex align-center", className)}>
<div className={cx("Entity py1 relative", { "pt2": badge })}>
{ badge &&
<div className="absolute top left">{badge}</div>
}
{titleAndDescription}
</div>
......
import React, { PropTypes } from "react";
import Icon from "metabase/components/Icon";
import TitleAndDescription from "metabase/components/TitleAndDescription";
const HeaderWithBack = ({ name, onBack = () => window.history.back() }) =>
const DEFAULT_BACK = () => window.history.back();
const HeaderWithBack = ({ name, description, onBack }) =>
<div className="flex align-center">
{ /* TODO - is this this the way we should do this? maybe makes more sense to just usa a link to the question index since you can navigate here from other spots potentially */ }
<Icon
className="cursor-pointer text-brand mr2 flex align-center circle p2 bg-light-blue bg-brand-hover text-white-hover transition-background transition-color"
name="backArrow"
onClick={onBack}
{ (onBack || window.history.length > 1) &&
<Icon
className="cursor-pointer text-brand mr2 flex align-center circle p2 bg-light-blue bg-brand-hover text-white-hover transition-background transition-color"
name="backArrow"
onClick={onBack || DEFAULT_BACK}
/>
}
<TitleAndDescription
title={name}
description={description}
/>
<h2>{name}</h2>
</div>
HeaderWithBack.propTypes = {
......
import React, { Component, PropTypes } from "react";
import { Link } from "react-router";
import QueryModeButton from "./QueryModeButton.jsx";
......@@ -22,6 +23,7 @@ import { CardApi, RevisionApi } from "metabase/services";
import MetabaseAnalytics from "metabase/lib/analytics";
import Query from "metabase/lib/query";
import { cancelable } from "metabase/lib/promise";
import Urls from "metabase/lib/urls";
import cx from "classnames";
import _ from "underscore";
......@@ -394,7 +396,7 @@ export default class QueryHeader extends Component {
render() {
return (
<div>
<div className="relative">
<HeaderBar
isEditing={this.props.isEditing}
name={this.props.isNew ? "New question" : this.props.card.name}
......@@ -402,6 +404,16 @@ export default class QueryHeader extends Component {
breadcrumb={(!this.props.card.id && this.props.originalCard) ? (<span className="pl2">started from <a className="link" onClick={this.onFollowBreadcrumb}>{this.props.originalCard.name}</a></span>) : null }
buttons={this.getHeaderButtons()}
setItemAttributeFn={this.props.onSetCardAttribute}
badge={this.props.card.collection &&
<Link
to={Urls.collection(this.props.card.collection)}
className="text-uppercase flex align-center no-decoration"
style={{ color: this.props.card.collection.color, fontSize: 12 }}
>
<Icon name="collection" size={12} style={{ marginRight: "0.5em" }} />
{this.props.card.collection.name}
</Link>
}
/>
<Modal small isOpen={this.state.modal === "saved"} onClose={this.onCloseModal}>
......
import { createAction, createThunkAction, handleActions, combineReducers } from "metabase/lib/redux";
import { reset } from 'redux-form';
import { push } from "react-router-redux";
import { goBack } from "react-router-redux";
import MetabaseAnalytics from "metabase/lib/analytics";
......@@ -29,7 +29,7 @@ export const saveCollection = createThunkAction(SAVE_COLLECTION, (collection) =>
if (response.id != null) {
dispatch(reset("collection"));
}
dispatch(push("/questions"))
dispatch(goBack())
return response;
} catch (e) {
// redux-form expects an object with either { field: error } or { _error: error }
......
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import { goBack } from "react-router-redux";
import CollectionEditorForm from "./CollectionEditorForm.jsx";
......@@ -15,7 +15,7 @@ const mapStateToProps = (state, props) => ({
const mapDispatchToProps = {
loadCollection,
saveCollection,
onClose: () => push("/questions")
onClose: goBack
}
@connect(mapStateToProps, mapDispatchToProps)
......
......@@ -10,7 +10,7 @@ import { reduxForm } from "redux-form";
@reduxForm({
form: 'collection',
fields: ['color', 'name', 'id'],
fields: ['id', 'name', 'description', 'color'],
validate: (values) => {
const errors = {};
if (!values.name) {
......
import React, { Component, PropTypes } from "react";
import { connect } from "react-redux";
import { push } from "react-router-redux";
import { push, replace, goBack } from "react-router-redux";
import HeaderWithBack from "metabase/components/HeaderWithBack";
......@@ -16,6 +16,8 @@ const mapStateToProps = (state, props) => ({
const mapDispatchToProps = ({
push,
replace,
goBack,
loadCollections,
editCollection: (id) => push(`/collections/${id}`),
editPermissions: (id) => push(`/collections/permissions?collection=${id}`)
......@@ -27,18 +29,25 @@ export default class CollectionPage extends Component {
this.props.loadCollections();
}
render () {
const { collection, params, location, push } = this.props;
const { collection, params, location, push, replace, goBack } = this.props;
console.log("collection", collection)
return (
<div className="mx4 mt4">
<div className="flex align-center">
<HeaderWithBack name={collection && collection.name} />
<HeaderWithBack
name={collection && collection.name}
description={collection && collection.description}
onBack={window.history.length === 1 ?
() => push("/questions") :
() => goBack()
}
/>
<div className="ml-auto">
<CollectionActions
actions={[
{ name: 'Archive collection', icon: 'archive', action: () => alert('NYI: archive!') },
{ name: 'Edit collection', icon: 'pencil', action: () => this.props.editCollection(this.props.collection.id) },
{ name: 'Set permissions', icon: 'lock', action: () => this.props.editPermissions(this.props.collection.id) },
{ name: 'Info', icon: 'info', action: () => () => alert('NYI: info!') },
]}
/>
</div>
......@@ -46,7 +55,8 @@ export default class CollectionPage extends Component {
<div className="mt4">
<EntityList
query={{ f: "all", collection: params.collectionSlug, ...location.query }}
onChangeSection={(section) => push({
// use replace when changing sections so back button still takes you back to collections page
onChangeSection={(section) => replace({
...location,
query: { ...location.query, f: section }
})}
......
......@@ -17,7 +17,7 @@ import { search } from "../questions";
import { loadCollections } from "../collections";
import { getUserIsAdmin } from "metabase/selectors/user";
import { push } from "react-router-redux";
import { replace } from "react-router-redux";
const mapStateToProps = (state, props) => ({
items: state.questions.entities.cards,
......@@ -30,7 +30,7 @@ const mapStateToProps = (state, props) => ({
const mapDispatchToProps = ({
search,
loadCollections,
push,
replace,
})
@connect(mapStateToProps, mapDispatchToProps)
......@@ -46,7 +46,7 @@ export default class QuestionIndex extends Component {
}
render () {
const { collections, push, location, isAdmin } = this.props;
const { collections, replace, location, isAdmin } = this.props;
const { questionsExpanded } = this.state;
const hasCollections = collections.length > 0;
const showCollections = isAdmin || hasCollections;
......@@ -105,7 +105,8 @@ export default class QuestionIndex extends Component {
<Collapse isOpened={questionsExpanded || !showCollections} keepCollapsedContent={true}>
<EntityList
query={{ f: "all", collection: "", ...location.query }}
onChangeSection={(section) => push({
// use replace when changing sections so back button still takes you back to collections page
onChangeSection={(section) => replace({
...location,
query: { ...location.query, f: section }
})}
......
......@@ -16,7 +16,8 @@ const mapStateToProps = (state, props) => ({
})
const mapDispatchToProps = ({
search
// pass "true" as 2nd arg to replace history state so back button still takes you back to index
search: (term) => search(term, true)
})
@connect(mapStateToProps, mapDispatchToProps)
......
......@@ -11,7 +11,7 @@ import { setRequestState } from "metabase/redux/requests";
import { getVisibleEntities, getSelectedEntities } from "./selectors";
import { addUndo } from "./undo";
import { push } from "react-router-redux";
import { push, replace } from "react-router-redux";
const card = new Schema('cards');
const label = new Schema('labels');
......@@ -46,7 +46,7 @@ export const selectSection = createThunkAction(SELECT_SECTION, (query = {}, type
}
});
export const search = (q) => push("/questions/search?q=" + encodeURIComponent(q))
export const search = (q, repl) => (repl ? replace : push)("/questions/search?q=" + encodeURIComponent(q))
export const setFavorited = createThunkAction(SET_FAVORITED, (cardId, favorited) => {
return async (dispatch, getState) => {
......
......@@ -38,7 +38,7 @@ export const DashboardApi = {
};
export const CollectionsApi = {
list: GET("/api/collection"),
list: GET("/api/collection"),// () => []),
create: POST("/api/collection"),
get: GET("/api/collection/:id"),
update: PUT("/api/collection/:id"),
......
......@@ -203,7 +203,7 @@
"Get `Card` with ID."
[id]
(-> (read-check Card id)
(hydrate :creator :dashboard_count :labels)
(hydrate :creator :dashboard_count :labels :collection)
(assoc :actor_id *current-user-id*)
(->> (events/publish-event! :card-read))
(dissoc :actor_id)))
......
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