瀏覽代碼

Change explorer behavior for pages w/ children, with tests

Sævar Öfjörð Magnússon 8 年之前
父節點
當前提交
81c6f3e3b1

+ 2 - 3
client/src/api/admin.js

@@ -9,9 +9,8 @@ export const getChildPages = (id, options = {}) => {
     url += `&fields=${global.encodeURIComponent(options.fields.join(','))}`;
   }
 
-  if (options.filter) {
-    url += `&${options.filter}`;
-  }
+  // Only show pages that have children for now
+  url += `&has_children=1`;
 
   return get(url).then(res => res.body);
 };

+ 1 - 1
client/src/components/AbsoluteDate/__snapshots__/AbsoluteDate.test.js.snap

@@ -1,6 +1,6 @@
 exports[`AbsoluteDate #time 1`] = `
 <span>
-  19.09.2016
+  Sep. 19, 2016
 </span>
 `;
 

+ 22 - 0
client/src/components/Explorer/PageCount.js

@@ -0,0 +1,22 @@
+import React from 'react';
+
+import { ADMIN_URLS, STRINGS } from 'config/wagtail';
+
+const PageCount = ({ id, count, title }) => (
+  <a
+    href={`${ADMIN_URLS.PAGES}${id}/`}
+    className="c-explorer__see-more"
+  >
+    {STRINGS.EXPLORE_ALL_IN}{' '}
+    <span className="c-explorer__see-more__title">{title}</span>{' '}
+    ({count} {count !== 1 ? STRINGS.PAGES : STRINGS.PAGE})
+  </a>
+);
+
+PageCount.propTypes = {
+  id: React.PropTypes.number.isRequired,
+  count: React.PropTypes.number.isRequired,
+  title: React.PropTypes.string.isRequired,
+};
+
+export default PageCount;

+ 3 - 52
client/src/components/Explorer/reducers/index.test.js

@@ -1,57 +1,8 @@
 import * as actions from '../actions';
 import rootReducer from './index';
-import explorer from './explorer';
-import nodes from './nodes';
-import transport from './transport';
 
-describe('explorer reducers', () => {
-  describe('root', () => {
-    it('exists', () => {
-      expect(rootReducer).toBeDefined();
-    });
-  });
-
-  describe('explorer', () => {
-    it('exists', () => {
-      expect(explorer).toBeDefined();
-    });
-  });
-
-  describe('nodes', () => {
-    it('exists', () => {
-      expect(nodes).toBeDefined();
-    });
-  });
-
-  describe('transport', () => {
-    const initialState = {
-      error: null,
-      showMessage: false,
-    };
-
-    it('exists', () => {
-      expect(transport).toBeDefined();
-    });
-
-    it('returns the initial state', () => {
-      expect(transport(undefined, {})).toEqual(initialState);
-    });
-
-    it('returns error message and flag', () => {
-      const action = actions.fetchFailure(new Error('Test error'));
-      expect(transport(initialState, action)).toEqual({
-        error: 'Test error',
-        showMessage: true,
-      });
-    });
-
-    it('clears previous error message and flag', () => {
-      const action = actions.clearError();
-      const errorState = {
-        error: 'Test error',
-        showMessage: true,
-      };
-      expect(transport(errorState, action)).toEqual(initialState);
-    });
+describe('root', () => {
+  it('exists', () => {
+    expect(rootReducer).toBeDefined();
   });
 });

+ 1 - 7
client/src/components/explorer/Explorer.js

@@ -34,7 +34,7 @@ class Explorer extends React.Component {
   }
 
   render() {
-    const { isVisible, nodes, path, pageTypes, type, filter, fetching, resolved } = this.props;
+    const { isVisible, nodes, path, pageTypes, type, fetching, resolved } = this.props;
     const page = this.getPage();
 
     const explorerProps = {
@@ -43,14 +43,12 @@ class Explorer extends React.Component {
       page,
       type,
       fetching,
-      filter,
       nodes,
       resolved,
       ref: 'explorer',
       onPop: this.props.onPop,
       onClose: this.props.onClose,
       transport: this.props.transport,
-      onFilter: this.props.onFilter,
       getChildren: this.props.getChildren,
       loadItemWithChildren: this.props.loadItemWithChildren,
       pushPage: this.props.pushPage,
@@ -78,7 +76,6 @@ Explorer.propTypes = {
   resolved: React.PropTypes.bool.isRequired,
   path: React.PropTypes.array,
   type: React.PropTypes.string.isRequired,
-  filter: React.PropTypes.string.isRequired,
   nodes: React.PropTypes.object.isRequired,
   transport: React.PropTypes.object.isRequired,
   page: React.PropTypes.any,
@@ -87,7 +84,6 @@ Explorer.propTypes = {
   setDefaultPage: React.PropTypes.func.isRequired,
   onShow: React.PropTypes.func.isRequired,
   onClose: React.PropTypes.func.isRequired,
-  onFilter: React.PropTypes.func.isRequired,
   getChildren: React.PropTypes.func.isRequired,
   loadItemWithChildren: React.PropTypes.func.isRequired,
   pushPage: React.PropTypes.func.isRequired,
@@ -105,7 +101,6 @@ const mapStateToProps = (state) => ({
   // indexes: state.entities.indexes,
   nodes: state.nodes,
   animation: state.explorer.animation,
-  filter: state.explorer.filter,
   transport: state.transport
 });
 
@@ -113,7 +108,6 @@ const mapDispatchToProps = (dispatch) => ({
   setDefaultPage: (id) => dispatch(actions.setDefaultPage(id)),
   getChildren: (id) => dispatch(actions.fetchChildren(id)),
   onShow: () => dispatch(actions.fetchRoot()),
-  onFilter: (filter) => dispatch(actions.setFilter(filter)),
   loadItemWithChildren: (id) => dispatch(actions.fetchPage(id)),
   pushPage: (id) => dispatch(actions.pushPage(id)),
   onPop: () => dispatch(actions.popPage()),

+ 2 - 15
client/src/components/explorer/ExplorerHeader.js

@@ -1,12 +1,11 @@
 import React from 'react';
 import CSSTransitionGroup from 'react-addons-css-transition-group';
-import { EXPLORER_ANIM_DURATION, EXPLORER_FILTERS } from '../../config/config';
+import { EXPLORER_ANIM_DURATION } from '../../config/config';
 import { STRINGS } from '../../config/wagtail';
 
 import Icon from '../../components/Icon/Icon';
-import Filter from '../../components/Explorer/Filter';
 
-const ExplorerHeader = ({ page, depth, filter, onPop, onFilter, transName }) => {
+const ExplorerHeader = ({ page, depth, onPop, transName }) => {
   const title = depth < 2 || !page ? STRINGS.PAGES : page.title;
 
   const transitionProps = {
@@ -34,16 +33,6 @@ const ExplorerHeader = ({ page, depth, filter, onPop, onFilter, transName }) =>
           </CSSTransitionGroup>
         </span>
       </span>
-      <span className="c-explorer__filter">
-        {EXPLORER_FILTERS.map((item) => (
-          <Filter
-            key={item.id}
-            {...item}
-            activeFilter={filter}
-            onFilter={onFilter}
-          />
-        ))}
-      </span>
     </div>
   );
 };
@@ -51,9 +40,7 @@ const ExplorerHeader = ({ page, depth, filter, onPop, onFilter, transName }) =>
 ExplorerHeader.propTypes = {
   page: React.PropTypes.object,
   depth: React.PropTypes.number,
-  filter: React.PropTypes.string,
   onPop: React.PropTypes.func,
-  onFilter: React.PropTypes.func,
   transName: React.PropTypes.string,
 };
 

+ 3 - 5
client/src/components/explorer/ExplorerItem.js

@@ -6,7 +6,7 @@ import Button from '../../components/Button/Button';
 import PublicationStatus from '../../components/PublicationStatus/PublicationStatus';
 import AbsoluteDate from '../../components/AbsoluteDate/AbsoluteDate';
 
-const ExplorerItem = ({ title, typeName, data, filter, onItemClick }) => {
+const ExplorerItem = ({ title, typeName, data, onItemClick }) => {
   const { id, meta } = data;
   const status = meta ? meta.status : null;
   const time = meta ? meta.latest_revision_created_at : null;
@@ -16,7 +16,7 @@ const ExplorerItem = ({ title, typeName, data, filter, onItemClick }) => {
   // // TODO refactor.
   let count = 0;
   if (meta) {
-    count = filter.match(/has_children/) ? meta.descendants.count - meta.children.count : meta.children.count;
+    count = meta.children.count;
   }
   const hasChildren = count > 0;
 
@@ -28,7 +28,7 @@ const ExplorerItem = ({ title, typeName, data, filter, onItemClick }) => {
           className="c-explorer__children"
           onClick={onItemClick.bind(null, id)}
         >
-          <Icon name="folder-inverse" title={STRINGS.SEE_CHILDREN} />
+          <Icon name="arrow-right" title={STRINGS.SEE_CHILDREN} />
         </span>
       ) : null}
 
@@ -44,13 +44,11 @@ const ExplorerItem = ({ title, typeName, data, filter, onItemClick }) => {
 ExplorerItem.propTypes = {
   title: React.PropTypes.string,
   data: React.PropTypes.object,
-  filter: React.PropTypes.string,
   typeName: React.PropTypes.string,
   onItemClick: React.PropTypes.func,
 };
 
 ExplorerItem.defaultProps = {
-  filter: '',
   data: {},
   onItemClick: () => {},
 };

+ 6 - 9
client/src/components/explorer/ExplorerPanel.js

@@ -8,6 +8,7 @@ import { STRINGS } from '../../config/wagtail';
 import ExplorerHeader from './ExplorerHeader';
 import ExplorerItem from './ExplorerItem';
 import LoadingSpinner from './LoadingSpinner';
+import PageCount from './PageCount';
 
 export default class ExplorerPanel extends React.Component {
   constructor(props) {
@@ -105,7 +106,7 @@ export default class ExplorerPanel extends React.Component {
   }
 
   renderChildren(page) {
-    const { nodes, pageTypes, filter } = this.props;
+    const { nodes, pageTypes } = this.props;
 
     if (!page || !page.children.items) {
       return [];
@@ -122,7 +123,6 @@ export default class ExplorerPanel extends React.Component {
           title: item.title,
           typeName,
           data: item,
-          filter,
         };
 
         return (
@@ -153,8 +153,6 @@ export default class ExplorerPanel extends React.Component {
       page,
       onPop,
       onClose,
-      onFilter,
-      filter,
       path,
       resolved
     } = this.props;
@@ -169,8 +167,6 @@ export default class ExplorerPanel extends React.Component {
       page,
       onPop,
       onClose,
-      onFilter,
-      filter
     };
 
     const transitionTargetProps = {
@@ -202,8 +198,11 @@ export default class ExplorerPanel extends React.Component {
                 {page.isFetching ? <LoadingSpinner key={1} /> : (
                   <div key={0}>
                     {this.getContents()}
+                    {(page.children.count > page.children.items.length) && (
+                      <PageCount id={page.id} count={page.meta.children.count} title={page.title} />
+                    )}
                   </div>
-              )}
+                )}
               </CSSTransitionGroup>
 
             </div>
@@ -219,8 +218,6 @@ ExplorerPanel.propTypes = {
   onPop: React.PropTypes.func.isRequired,
   onClose: React.PropTypes.func.isRequired,
   type: React.PropTypes.string.isRequired,
-  onFilter: React.PropTypes.func.isRequired,
-  filter: React.PropTypes.string.isRequired,
   path: React.PropTypes.array,
   resolved: React.PropTypes.bool.isRequired,
   init: React.PropTypes.func.isRequired,

+ 0 - 20
client/src/components/explorer/Filter.js

@@ -1,20 +0,0 @@
-import React from 'react';
-
-// TODO Do not use a span for a clickable element.
-const Filter = ({ label, filter = null, activeFilter, onFilter }) => (
-  <span
-    className={`c-filter${activeFilter === filter ? ' c-filter--active' : ''}`}
-    onClick={onFilter.bind(this, filter)}
-  >
-    {label}
-  </span>
-);
-
-Filter.propTypes = {
-  label: React.PropTypes.string.isRequired,
-  filter: React.PropTypes.string,
-  activeFilter: React.PropTypes.string,
-  onFilter: React.PropTypes.func.isRequired,
-};
-
-export default Filter;

+ 0 - 18
client/src/components/explorer/actions/index.js

@@ -38,7 +38,6 @@ export function fetchChildren(id = 'root') {
 
     return admin.getChildPages(id, {
       fields: explorer.fields,
-      filter: explorer.filter,
     }).then(json => dispatch(fetchChildrenSuccess(id, json)));
   };
 }
@@ -84,23 +83,6 @@ export function fetchRoot() {
 export const toggleExplorer = createAction('TOGGLE_EXPLORER');
 
 
-export function setFilter(filter) {
-  return (dispatch, getState) => {
-    const { explorer } = getState();
-    const id = explorer.path[explorer.path.length - 1];
-
-    dispatch({
-      payload: {
-        filter,
-        id,
-      },
-      type: 'SET_FILTER',
-    });
-
-    dispatch(fetchChildren(id));
-  };
-}
-
 /**
  * TODO: determine if page is already loaded, don't load it again, just push.
  */

+ 1 - 7
client/src/components/explorer/reducers/explorer.js

@@ -10,12 +10,11 @@ const defaultState = {
   // TODO Change to include less fields (just 'descendants'?) in the next version of the admin API.
   // Specificies which fields are to be fetched in the API calls.
   fields: ['title', 'latest_revision_created_at', 'status', 'descendants', 'children'],
-  filter: 'has_children=1',
   // Coming from the API in order to get translated / pluralised labels.
   pageTypes: {},
 };
 
-export default function explorer(state = defaultState, action) {
+export default function explorer(state = defaultState, action = {}) {
   let newNodes = state.path;
 
   switch (action.type) {
@@ -87,11 +86,6 @@ export default function explorer(state = defaultState, action) {
       pageTypes: _.assign({}, state.pageTypes, action.payload.json.__types),
     });
 
-  case 'SET_FILTER':
-    return _.assign({}, state, {
-      filter: action.filter
-    });
-
   default:
     return state;
   }

+ 55 - 0
client/src/components/explorer/reducers/explorer.test.js

@@ -0,0 +1,55 @@
+import * as actions from '../actions';
+import _ from 'lodash';
+import rootReducer from './index';
+import explorer from './explorer';
+
+describe('explorer', () => {
+  const initialState = {
+    isVisible: false,
+    isFetching: false,
+    isResolved: false,
+    path: [],
+    currentPage: 1,
+    defaultPage: 1,
+    fields: ['title', 'latest_revision_created_at', 'status', 'descendants', 'children'],
+    pageTypes: {},
+  };
+
+  it('exists', () => {
+    expect(explorer).toBeDefined();
+  });
+  it('returns the initial state if no input is provided', () =>  {
+    expect(explorer(undefined, undefined))
+      .toEqual(initialState);
+  });
+  it('sets the default page', () => {
+    expect(explorer(initialState, {type: 'SET_DEFAULT_PAGE', payload: 100}))
+      .toEqual(_.assign({}, initialState, {defaultPage: 100}))
+  });
+  it('resets the tree', () => {
+    expect(explorer(initialState, {type: 'RESET_TREE', payload: 100}))
+      .toEqual(_.assign({}, initialState, {isFetching: true, currentPage: 100}))
+  });
+  it('has resolved the tree', () => {
+    expect(explorer(initialState, {type: 'TREE_RESOLVED'}))
+      .toEqual(_.assign({}, initialState, {isResolved: true}))
+  });
+  it('toggles the explorer', () => {
+    expect(explorer(initialState, {type: 'TOGGLE_EXPLORER', payload: 100}))
+      .toEqual(
+        _.assign({}, initialState, {isVisible: !initialState.isVisible, currentPage: 100})
+      )
+  });
+  it('starts fetching', () => {
+    expect(explorer(initialState, {type: 'FETCH_START'}))
+      .toEqual(_.assign({}, initialState, {isFetching: true}))
+  });
+  it('pushes a page to the path', () => {
+    expect(explorer(initialState, {type: 'PUSH_PAGE', payload: 100}))
+      .toEqual(_.assign({}, initialState, {path: initialState.path.concat([100])}))
+  });
+  it('pops a page off the path', () => {
+    expect(explorer(_.assign({}, initialState, {path: initialState.path.concat(["root", 100])}), {type: 'POP_PAGE', payload: 100}))
+      .toEqual(_.assign({}, initialState, {path: initialState.path.concat(["root"])}))
+  });
+});

+ 1 - 22
client/src/components/explorer/reducers/nodes.js

@@ -34,7 +34,7 @@ const defaultState = {
 };
 
 // TODO Why isn't the default state used on init?
-export default function nodes(state = {}, action) {
+export default function nodes(state = {}, action = {}) {
   switch (action.type) {
   case 'FETCH_CHILDREN_START':
     // TODO Very hard to understand this code. To refactor.
@@ -67,27 +67,6 @@ export default function nodes(state = {}, action) {
   case 'RESET_TREE':
     return defaultState;
 
-  // eslint-disable-next-line no-case-declarations
-  case 'SET_FILTER':
-      // Unset all isLoaded states when the filter changes
-    const updatedState = {};
-
-    // TODO Do not use for in.
-    // TODO Very hard to understand this code. To refactor.
-    // eslint-disable-next-line
-    for (let key in state) {
-      if (state.hasOwnProperty(key)) {
-        // eslint-disable-next-line prefer-const
-        let obj = state[key];
-        obj.children.isLoaded = false;
-        updatedState[obj.id] = _.assign({}, obj, {
-          isLoaded: false,
-        });
-      }
-    }
-
-    return _.assign({}, updatedState);
-
   case 'FETCH_START':
     return _.assign({}, state, {
       [action.payload]: _.assign({}, defaultState, state[action.payload], {

+ 72 - 0
client/src/components/explorer/reducers/nodes.test.js

@@ -0,0 +1,72 @@
+import * as actions from '../actions';
+import _ from 'lodash';
+import rootReducer from './index';
+import nodes from './nodes';
+
+describe('nodes', () => {
+  const initialState = {
+    isError: false,
+    isFetching: false,
+    isLoaded: false,
+    children: {
+      items: [],
+      count: 0,
+      isFetching: false
+    }
+  };
+
+  const fetchingState = {
+    "any": {
+      isFetching: true,
+      isError: false,
+      isLoaded: false,
+      children: {
+        items: [],
+        count: 0,
+        isFetching: false
+      }
+    }
+  };
+
+  const fetchingChildren = {
+    isError: false,
+    isFetching: false,
+    isLoaded: false,
+    children: {
+      items: [],
+      count: 0,
+      isFetching: false
+    },
+    "any": {
+      isFetching: true,
+      children: {
+        items: [],
+        count: 0,
+        isFetching: true
+      }
+    }
+  };
+
+  it('exists', () => {
+    expect(nodes).toBeDefined();
+  });
+
+  it('returns empty state on no action and no input state', () => {
+    expect(nodes(undefined, undefined)).toEqual({});
+  });
+  it('returns initial state on no action and initial state input', () => {
+    expect(nodes(initialState, undefined)).toEqual(initialState);
+  });
+  it('starts fetching children', () => {
+    expect(nodes(initialState, {type: 'FETCH_CHILDREN_START', payload: 'any'})).toEqual(fetchingChildren);
+  });
+  it('resets the tree', () => {
+    expect(nodes({}, {type: 'RESET_TREE'})).toEqual(initialState);
+  });
+  it('starts fetching', () => {
+    expect(nodes({}, {type: 'FETCH_START', payload: 'any'})).toEqual(fetchingState)
+  });
+  it('makes a fetch success', () => {
+    expect(nodes({'any': 'any'}, {type: 'FETCH_SUCCESS'})).toEqual({'any': 'any'})
+  })
+});

+ 36 - 0
client/src/components/explorer/reducers/transport.test.js

@@ -0,0 +1,36 @@
+import * as actions from '../actions';
+import _ from 'lodash';
+import rootReducer from './index';
+import transport from './transport';
+
+describe('transport', () => {
+  const initialState = {
+    error: null,
+    showMessage: false,
+  };
+
+  it('exists', () => {
+    expect(transport).toBeDefined();
+  });
+
+  it('returns the initial state', () => {
+    expect(transport(undefined, {})).toEqual(initialState);
+  });
+
+  it('returns error message and flag', () => {
+    const action = actions.fetchFailure(new Error('Test error'));
+    expect(transport(initialState, action)).toEqual({
+      error: 'Test error',
+      showMessage: true,
+    });
+  });
+
+  it('clears previous error message and flag', () => {
+    const action = actions.clearError();
+    const errorState = {
+      error: 'Test error',
+      showMessage: true,
+    };
+    expect(transport(errorState, action)).toEqual(initialState);
+  });
+});

+ 20 - 37
client/src/components/explorer/style.scss

@@ -1,5 +1,5 @@
 $c-explorer-bg: #4C4E4D;
-$c-explorer-secondary: #aaa;
+$c-explorer-secondary: #cacaca;
 $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
 
 .c-explorer, .c-explorer * {
@@ -31,7 +31,7 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
     padding: .5rem 1rem;
     white-space: nowrap;
     overflow: hidden;
-    width: 80%;
+    width: 100%;
     float: left;
 }
 
@@ -44,34 +44,6 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
     }
 }
 
-.c-explorer__filter {
-    float: right;
-    width: 50px;
-    margin-top: .5rem;
-}
-
-.c-filter {
-    display: inline-block;
-    vertical-align: middle;
-    padding: 0 .25em;
-    border: solid 1px rgba(255,255,255,0.1);
-    border-radius: 2px;
-    line-height: 1;
-    margin-left: .25rem;
-    cursor: pointer;
-    &:hover {
-        background: rgba(0,0,0,0.5);
-        border-color: rgba(0,0,0,0.5);
-        color: $color-white;
-    }
-}
-
-.c-filter--active {
-    color: $color-white;
-    border-color: rgba(255, 255, 255, .5);
-}
-
-
 .c-explorer__back {
     margin-right: .25rem;
     float: left;
@@ -126,6 +98,7 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
 
 .c-explorer__item {
     display: block;
+    position: relative;
 
     &:hover {
         background: rgba(0, 0, 0, 0.25);
@@ -134,25 +107,35 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
 }
 
 .c-explorer__see-more {
-    cursor: pointer;
-    padding: .5rem 1rem;
+    padding: 1rem;
     background: rgba(0,0,0,0.2);
-    color: $color-white;
+    color: $c-explorer-secondary;
+    display: block;
 
     &:hover {
+        color: $c-explorer-secondary;
         background: rgba(0,0,0,0.4);
     }
 }
 
+.c-explorer__see-more__title {
+    color: $color-white;
+}
+
 .c-explorer__children {
     display: inline-block;
-    border-radius: 50rem;
-    border: solid 1px #aaa;
     color: $color-white;
     line-height: 1;
-    padding: .5em .3em .5em .5em;
+    padding: .7em .3em .7em .7em;
     float: right;
     cursor: pointer;
+    display: inline-block;
+    position: absolute;
+    right: 0;
+    top: 0;
+    bottom: 0;
+    font-size: 2em;
+
 
     &:hover {
         background: rgba(0,0,0,0.5);
@@ -162,7 +145,7 @@ $c-explorer-easing: cubic-bezier(0.075, 0.820, 0.165, 1.000);
 
 .c-status {
     background: $color-grey-1;
-    color: #ddd;
+    color: $c-explorer-secondary;
     text-transform: uppercase;
     letter-spacing: .03rem;
     font-size: 10px;

+ 0 - 7
client/src/config/config.js

@@ -1,10 +1,3 @@
 export const PAGES_ROOT_ID = 'root';
 
 export const EXPLORER_ANIM_DURATION = 220;
-
-// TODO Add back in when we want to support explorer that displays pages
-// without children (API call without has_children=1).
-export const EXPLORER_FILTERS = [
-  { id: 1, label: 'A', filter: null },
-  { id: 2, label: 'B', filter: 'has_children=1' }
-];

+ 0 - 6
client/src/config/config.test.js

@@ -1,7 +1,6 @@
 import {
   PAGES_ROOT_ID,
   EXPLORER_ANIM_DURATION,
-  EXPLORER_FILTERS,
 } from './config';
 
 describe('config', () => {
@@ -17,9 +16,4 @@ describe('config', () => {
     });
   });
 
-  describe('EXPLORER_FILTERS', () => {
-    it('exists', () => {
-      expect(EXPLORER_FILTERS).toBeDefined();
-    });
-  });
 });

+ 1 - 1
client/src/config/wagtail.js

@@ -2,4 +2,4 @@ export const ADMIN_API = global.wagtailConfig.ADMIN_API;
 export const STRINGS = global.wagtailConfig.STRINGS;
 export const ADMIN_URLS = global.wagtailConfig.ADMIN_URLS;
 
-export const DATE_FORMAT = 'DD.MM.YYYY';
+export const DATE_FORMAT = global.wagtailConfig.DATE_FORMATTING.DATE_FORMAT;

+ 4 - 0
client/tests/stubs.js

@@ -13,6 +13,10 @@ global.wagtailConfig = {
   ADMIN_URLS: {
     PAGES: '/admin/pages/',
   },
+  DATE_FORMATTING: {
+    DATE_FORMAT: 'MMM. D, YYYY',
+    SHORT_DATE_FORMAT: 'DD/MM/YYYY',
+  },
   STRINGS: {
     EXPLORER: 'Explorer',
     LOADING: 'Loading...',

File diff suppressed because it is too large
+ 123 - 917
npm-shrinkwrap.json


+ 7 - 7
package.json

@@ -23,14 +23,14 @@
     ]
   },
   "devDependencies": {
-    "babel-cli": "^6.5.1",
-    "babel-core": "^6.5.2",
+    "babel-cli": "^6.22.2",
+    "babel-core": "^6.22.1",
     "babel-jest": "^18.0.0",
-    "babel-loader": "^6.2.3",
-    "babel-plugin-lodash": "^3.2.9",
-    "babel-polyfill": "^6.5.0",
-    "babel-preset-es2015": "^6.5.0",
-    "babel-preset-react": "^6.5.0",
+    "babel-loader": "^6.2.10",
+    "babel-plugin-lodash": "^3.2.11",
+    "babel-polyfill": "^6.22.0",
+    "babel-preset-es2015": "^6.22.0",
+    "babel-preset-react": "^6.22.0",
     "enzyme": "^2.3.0",
     "enzyme-to-json": "^1.4.5",
     "eslint": "^2.9.0",

+ 10 - 0
wagtail/wagtailadmin/templates/wagtailadmin/admin_base.html

@@ -24,12 +24,22 @@
                 IMAGES: '{% url "wagtailadmin_api_v1:images:listing" %}'
             };
 
+            // We are using Moment.js formatting syntax for now,
+            // TODO: Use django settings defaults and find a way
+            // to parse them in moment.js
+            wagtailConfig.DATE_FORMATTING = {
+                DATE_FORMAT: 'MMM. D, YYYY',
+                SHORT_DATE_FORMAT: 'DD/MM/YYYY'
+            };
+
             wagtailConfig.STRINGS = {
+                PAGE: "{% trans 'Page' %}",
                 PAGES: "{% trans 'Pages' %}",
                 LOADING: "{% trans 'Loading...' %}",
                 NO_RESULTS: "{% trans 'No results' %}",
                 SEE_CHILDREN: "{% trans 'See Children' %}",
                 NO_DATE: "{% trans 'No date' %}",
+                EXPLORE_ALL_IN: "{% trans 'Explore all in' %}",
             };
 
             wagtailConfig.ADMIN_URLS = {

Some files were not shown because too many files changed in this diff