diff --git a/frontend/src/admin/datamodel/containers/SegmentApp.jsx b/frontend/src/admin/datamodel/containers/SegmentApp.jsx index 4a7a507881fbed563dd242a2c39adfe611c6c0cb..4a13d35b257e5c882394548c067947576b46c897 100644 --- a/frontend/src/admin/datamodel/containers/SegmentApp.jsx +++ b/frontend/src/admin/datamodel/containers/SegmentApp.jsx @@ -1,26 +1,30 @@ import React, { Component, PropTypes } from "react"; -import { connect } from "react-redux"; + +import SegmentForm from "./SegmentForm.jsx"; import { segmentEditSelectors } from "../selectors"; import * as actions from "../actions"; -import SegmentForm from "./SegmentForm.jsx"; +import { connect } from "react-redux"; @connect(segmentEditSelectors, actions) export default class SegmentApp extends Component { - async componentDidMount() { - let { tableId, segmentId } = this.props; + async componentWillMount() { + const { params } = this.props; - if (segmentId) { + let tableId; + if (params.id) { + const segmentId = parseInt(params.id); this.props.setCurrentSegmentId(segmentId); - let { payload: segment } = await this.props.getSegment({ segmentId }); + const { payload: segment } = await this.props.getSegment({ segmentId }); tableId = segment.table_id; - } else if (tableId) { + } else if (location.query.table) { + tableId = parseInt(location.query.table); this.props.setCurrentSegmentId(null); this.props.newSegment({ id: null, table_id: tableId, definition: { filter: [] } }); } - if (tableId) { + if (tableId != null) { this.props.loadTableMetadata(tableId); } } @@ -32,7 +36,8 @@ export default class SegmentApp extends Component { } else { await this.props.createSegment(segment); } - this.props.onChangeLocation("/admin/datamodel/database/" + tableMetadata.db_id + "/table/" + tableMetadata.id); + + this.onLocationChange("/admin/datamodel/database/" + tableMetadata.db_id + "/table/" + tableMetadata.id); } render() { @@ -45,4 +50,12 @@ export default class SegmentApp extends Component { </div> ); } + + // HACK: figure out a better way to do this that works with both redux-router and Angular's router + onLocationChange(path) { + const el = angular.element(document.querySelector("body")); + el.scope().$apply(function() { + el.injector().get("$location").path(path); + }); + } } diff --git a/frontend/src/admin/datamodel/containers/SegmentForm.jsx b/frontend/src/admin/datamodel/containers/SegmentForm.jsx index fe47609eebdf06700e653bfbba19c57ce9c4e89a..6774f82501998317d5a466371197b4053d73c4a8 100644 --- a/frontend/src/admin/datamodel/containers/SegmentForm.jsx +++ b/frontend/src/admin/datamodel/containers/SegmentForm.jsx @@ -1,17 +1,15 @@ import React, { Component, PropTypes } from "react"; -import { reduxForm } from "redux-form"; - -import { segmentFormSelectors } from "../selectors"; import FormLabel from "../components/FormLabel.jsx"; import FormInput from "../components/FormInput.jsx"; import FormTextArea from "../components/FormTextArea.jsx"; import Fieldset from "../components/FieldSet.jsx"; - import SegmentBuilder from "../components/segment/SegmentBuilder.jsx"; - import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper.jsx"; +import { segmentFormSelectors } from "../selectors"; +import { reduxForm } from "redux-form"; + import cx from "classnames"; @reduxForm({ diff --git a/frontend/src/admin/datamodel/datamodel.module.js b/frontend/src/admin/datamodel/datamodel.module.js index e8aced706613688062aac86b5510ad93c40b9f30..d089cb877c4d263f1fd4a722b98e46ecff24d06e 100644 --- a/frontend/src/admin/datamodel/datamodel.module.js +++ b/frontend/src/admin/datamodel/datamodel.module.js @@ -1,9 +1,3 @@ - -import { createStore, combineReducers } from "metabase/lib/redux"; - -import SegmentApp from "./containers/SegmentApp.jsx"; -import * as reducers from './reducers'; - angular .module('metabase.admin.datamodel', [ 'metabase.admin.datamodel.controllers' @@ -23,24 +17,4 @@ angular $routeProvider.when('/admin/datamodel/database/:databaseId', metadataRoute); $routeProvider.when('/admin/datamodel/database/:databaseId/:mode', metadataRoute); $routeProvider.when('/admin/datamodel/database/:databaseId/:mode/:tableId', metadataRoute); - - var segmentRoute = { - template: '<div mb-redux-component class="flex flex-column flex-full" />', - controller: ['$scope', '$location', '$route', '$routeParams', - function($scope, $location, $route, $routeParams) { - $scope.Component = SegmentApp; - $scope.props = { - segmentId: parseInt($routeParams.segmentId, 10), - tableId: parseInt($routeParams.table, 10), - onChangeLocation: function(url) { - $scope.$apply(() => $location.url(url)); - } - }; - $scope.store = createStore(combineReducers(reducers), {}); - } - ] - } - - $routeProvider.when('/admin/datamodel/segment/create', segmentRoute); - $routeProvider.when('/admin/datamodel/segment/:segmentId', segmentRoute); }]); diff --git a/frontend/src/admin/datamodel/reducers.js b/frontend/src/admin/datamodel/reducers.js index 20368ef539d572ac700f71cafc40521ffa813d8b..fae08eea7b5dc4752cc95f35e708bbcb18641961 100644 --- a/frontend/src/admin/datamodel/reducers.js +++ b/frontend/src/admin/datamodel/reducers.js @@ -3,8 +3,6 @@ import { handleActions } from "redux-actions"; import { momentifyTimestamps } from "metabase/lib/redux"; -export { reducer as form } from "redux-form"; - import { NEW_SEGMENT, GET_SEGMENT, @@ -17,10 +15,10 @@ import { } from "./actions"; export const segments = handleActions({ - [NEW_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload), revision_message: undefined }) }, - [GET_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload), revision_message: undefined }) }, - [CREATE_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload), revision_message: undefined }) }, - [UPDATE_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload), revision_message: undefined }) }, + [NEW_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload) }) }, + [GET_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload) }) }, + [CREATE_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload) }) }, + [UPDATE_SEGMENT]: { next: (state, { payload }) => ({ ...state, [payload.id]: momentifyTimestamps(payload) }) }, [DELETE_SEGMENT]: { next: (state, { payload }) => { state = { ...state }; delete state[payload.id]; return state; }} }, {}); diff --git a/frontend/src/admin/datamodel/selectors.js b/frontend/src/admin/datamodel/selectors.js index a6b67729c580cfe545d47455fd6de7ff26891112..465699d8ffb39bb6a64c87600fe8242e1d43a6e4 100644 --- a/frontend/src/admin/datamodel/selectors.js +++ b/frontend/src/admin/datamodel/selectors.js @@ -1,14 +1,15 @@ import { createSelector } from 'reselect'; -const segmentsSelector = state => state.segments; -const currentSegmentIdSelector = state => state.currentSegmentId; -const tableMetadataSelector = state => state.tableMetadata; -const resultCountSelector = state => state.resultCount; +const segmentsSelector = state => state.datamodel.segments; +const currentSegmentIdSelector = state => state.datamodel.currentSegmentId; +const tableMetadataSelector = state => state.datamodel.tableMetadata; +const resultCountSelector = state => state.datamodel.resultCount; -// EDIT export const segmentEditSelectors = createSelector( - [segmentsSelector, currentSegmentIdSelector, tableMetadataSelector], + segmentsSelector, + currentSegmentIdSelector, + tableMetadataSelector, (segments, currentSegmentId, tableMetadata) => ({ segment: segments[currentSegmentId], tableMetadata @@ -16,6 +17,11 @@ export const segmentEditSelectors = createSelector( ); export const segmentFormSelectors = createSelector( - [segmentEditSelectors, tableMetadataSelector, resultCountSelector], - ({ segment }, tableMetadata, resultCount) => ({ initialValues: segment, tableMetadata, resultCount }) + segmentEditSelectors, + resultCountSelector, + ({ segment, tableMetadata }, resultCount) => ({ + initialValues: segment, + tableMetadata, + resultCount + }) ); diff --git a/frontend/src/lib/redux.js b/frontend/src/lib/redux.js index 58572893023f2c8baad397b6e1ba3437db10ce53..14d7a934df699d824f8d8df97ebf7b2e60bbf7a7 100644 --- a/frontend/src/lib/redux.js +++ b/frontend/src/lib/redux.js @@ -2,18 +2,19 @@ import moment from "moment"; import _ from "underscore"; import { createStore as originalCreateStore, applyMiddleware, compose } from "redux"; -import promiseMiddleware from 'redux-promise'; -import thunkMidleware from "redux-thunk"; +import promise from 'redux-promise'; +import thunk from "redux-thunk"; + +import { createHistory } from 'history'; +import { reduxReactRouter } from 'redux-router'; // convienence export { combineReducers } from "redux"; // common createStore with middleware applied export const createStore = compose( - applyMiddleware( - thunkMidleware, - promiseMiddleware - ) + applyMiddleware(thunk, promise), + reduxReactRouter({ createHistory }) )(originalCreateStore); // HACK: just use our Angular resources for now diff --git a/package.json b/package.json index 32f26026ba4bcd960b4495aa66683840a9ab0691..7414f31149b39f1e84c15d5b80cde3fe157eddc4 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "d3-tip": "^0.6.7", "dc": "^2.0.0-beta.14", "fixed-data-table": "^0.4.7", + "history": "^1.13.1", "humanize-plus": "^1.5.0", "inflection": "^1.7.1", "moment": "^2.10.6", @@ -34,12 +35,14 @@ "react-onclickout": "^1.1.0", "react-redux": "^3.1.0", "react-retina-image": "^2.0.0", + "react-router": "^1.0.2", "redux": "^3.0.4", "redux-actions": "^0.8.0", "redux-devtools": "^2.1.5", "redux-form": "3.1.0", "redux-logger": "^2.1.1", "redux-promise": "^0.5.0", + "redux-router": "^1.0.0-beta5", "redux-thunk": "^1.0.0", "reselect": "^2.0.1", "tether": "^1.1.0",