Skip to content
Snippets Groups Projects
Commit 5897fffb authored by Tom Robinson's avatar Tom Robinson
Browse files

Segment revisions

parent ceba2fd1
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,7 @@ import { Route } from 'react-router';
import { ReduxRouter } from 'redux-router';
import SegmentApp from "./datamodel/containers/SegmentApp.jsx";
import RevisionHistoryApp from "./datamodel/containers/RevisionHistoryApp.jsx";
export default class AdminRoutes extends Component {
render() {
......@@ -14,6 +15,8 @@ export default class AdminRoutes extends Component {
<Route path="datamodel">
<Route path="segment/create" component={SegmentApp} />
<Route path="segment/:id" component={SegmentApp} />
<Route path=":entity/:id/revisions" component={RevisionHistoryApp} />
</Route>
</Route>
<Route path="/*"/>
......
......@@ -6,6 +6,9 @@ import { loadTable } from "metabase/lib/table";
const Segment = new AngularResourceProxy("Segment", ["get", "create", "update", "delete"]);
const Metabase = new AngularResourceProxy("Metabase", ["dataset"]);
const Revisions = new AngularResourceProxy("Revisions", ["get"]);
// SEGMENTS
export const NEW_SEGMENT = "NEW_SEGMENT";
export const GET_SEGMENT = "GET_SEGMENT";
......@@ -13,21 +16,20 @@ export const CREATE_SEGMENT = "CREATE_SEGMENT";
export const UPDATE_SEGMENT = "UPDATE_SEGMENT";
export const DELETE_SEGMENT = "DELETE_SEGMENT";
export const SET_CURRENT_SEGMENT_ID = "SET_CURRENT_SEGMENT_ID";
export const LOAD_TABLE_METADATA = "LOAD_TABLE_METADATA";
export const UPDATE_RESULT_COUNT = "UPDATE_RESULT_COUNT";
export const newSegment = createAction(NEW_SEGMENT);
export const getSegment = createAction(GET_SEGMENT, Segment.get);
export const createSegment = createAction(CREATE_SEGMENT, Segment.create);
export const updateSegment = createAction(UPDATE_SEGMENT, Segment.update);
export const deleteSegment = createAction(DELETE_SEGMENT, Segment.delete);
export const setCurrentSegmentId = createAction(SET_CURRENT_SEGMENT_ID);
// SEGMENT DETAIL
export const loadTableMetadata = createAction(LOAD_TABLE_METADATA, loadTable);
export const SET_CURRENT_SEGMENT_ID = "SET_CURRENT_SEGMENT_ID";
export const LOAD_TABLE_METADATA = "LOAD_TABLE_METADATA";
export const UPDATE_RESULT_COUNT = "UPDATE_RESULT_COUNT";
export const setCurrentSegmentId = createAction(SET_CURRENT_SEGMENT_ID);
export const loadTableMetadata = createAction(LOAD_TABLE_METADATA, loadTable);
export const updateResultCount = createAction(UPDATE_RESULT_COUNT, async (query) => {
let result = await Metabase.dataset({
...query,
......@@ -38,3 +40,15 @@ export const updateResultCount = createAction(UPDATE_RESULT_COUNT, async (query)
});
return result.data.rows[0][0];
});
// REVISION HISTORY
export const FETCH_REVISIONS = "FETCH_REVISIONS";
export const fetchRevisions = createAction(FETCH_REVISIONS, async ({ entity, id }) => {
let [segment, revisions] = await * [
Segment.get({ segmentId: id }),
Revisions.get({ entity, id })
];
return { name: segment.name, revisions };
})
import React, { Component, PropTypes } from "react";
import UserAvatar from "metabase/components/UserAvatar.jsx"
import moment from "moment";
// TODO: "you" for current user
// TODO: format diffs
// TODO: show different color avatars for users that aren't me
export default class Revision extends Component {
static propTypes = {
revision: PropTypes.object.isRequired
};
render() {
const { revision, objectName } = this.props;
let name = revision.user.common_name;
let action;
if (revision.is_creation) {
action = "created \"" + objectName + "\"";
} else {
action = "made some changes";
}
return (
<li className="flex flex-row">
<div className="flex flex-column align-center mr2">
<div className="text-white">
<UserAvatar user={revision.user} />
</div>
<div className="flex-full my1 border-left" style={{borderWidth: 2}} />
</div>
<div className="flex-full mt1 mb4">
<div className="flex mb1">
<span><strong>{name}</strong> {action}</span>
<span className="flex-align-right">{moment(revision.timestamp).format("MMMM DD, YYYY")}</span>
</div>
{ revision.message && <p>"{revision.message}"</p> }
<div className="bordered rounded mt2 p2" style={{borderWidth: 2}}>
<pre className="m1">{JSON.stringify(revision.diff, null, 2)}</pre>
</div>
</div>
</li>
);
}
}
import React, { Component, PropTypes } from "react";
import Revision from "./Revision.jsx";
import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper.jsx"
export default class RevisionHistory extends Component {
render() {
const { name, revisions } = this.props;
return (
<LoadingAndErrorWrapper loading={!revisions}>
{() =>
<div className="wrapper py4" style={{maxWidth: 950}}>
<h2 className="mb4">Revision History for "{name}"</h2>
<ol>
{revisions.map(revision =>
<Revision revision={revision} objectName={name} />
)}
</ol>
</div>
}
</LoadingAndErrorWrapper>
);
}
}
import React, { Component, PropTypes } from "react";
import RevisionHistory from "../components/revisions/RevisionHistory.jsx";
import { revisionHistorySelectors } from "../selectors";
import * as actions from "../actions";
import { connect } from "react-redux";
@connect(revisionHistorySelectors, actions)
export default class RevisionHistoryApp extends Component {
componentWillMount() {
let { entity, id } = this.props.params;
this.props.fetchRevisions({ entity, id })
}
render() {
return (
<RevisionHistory {...this.props} />
);
}
}
......@@ -11,7 +11,8 @@ import {
DELETE_SEGMENT,
SET_CURRENT_SEGMENT_ID,
LOAD_TABLE_METADATA,
UPDATE_RESULT_COUNT
UPDATE_RESULT_COUNT,
FETCH_REVISIONS
} from "./actions";
export const segments = handleActions({
......@@ -37,3 +38,7 @@ export const tableMetadata = handleActions({
export const resultCount = handleActions({
[UPDATE_RESULT_COUNT]: { next: (state, { payload: resultCount }) => resultCount }
}, null);
export const revisionObject = handleActions({
[FETCH_REVISIONS]: { next: (state, { payload: revisions }) => revisions }
}, null);
......@@ -5,6 +5,7 @@ const segmentsSelector = state => state.datamodel.segments;
const currentSegmentIdSelector = state => state.datamodel.currentSegmentId;
const tableMetadataSelector = state => state.datamodel.tableMetadata;
const resultCountSelector = state => state.datamodel.resultCount;
const revisionObjectSelector = state => state.datamodel.revisionObject;
export const segmentEditSelectors = createSelector(
segmentsSelector,
......@@ -25,3 +26,11 @@ export const segmentFormSelectors = createSelector(
resultCount
})
);
export const revisionHistorySelectors = createSelector(
revisionObjectSelector,
(object) => ({
name: object && object.name,
revisions: object && object.revisions
})
);
......@@ -680,6 +680,20 @@ CoreServices.factory('Revision', ['$resource', function($resource) {
});
}]);
// Revisions V2
CoreServices.factory('Revisions', ['$resource', function($resource) {
return $resource('/api/:entity/:id/revisions', {}, {
get: {
method: 'GET',
isArray: true,
params: {
'entity': '@entity',
'id': '@id'
}
}
});
}]);
CoreServices.factory('Session', ['$resource', '$cookies', function($resource, $cookies) {
return $resource('/api/session/', {}, {
create: {
......
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