fix: persistent view style (#4138)
This commit is contained in:
parent
5baa20bf67
commit
017883f0dc
@ -73,6 +73,8 @@ export const ENTRY_DELETE_FAILURE = 'ENTRY_DELETE_FAILURE';
|
||||
export const ADD_DRAFT_ENTRY_MEDIA_FILE = 'ADD_DRAFT_ENTRY_MEDIA_FILE';
|
||||
export const REMOVE_DRAFT_ENTRY_MEDIA_FILE = 'REMOVE_DRAFT_ENTRY_MEDIA_FILE';
|
||||
|
||||
export const CHANGE_VIEW_STYLE = 'CHANGE_VIEW_STYLE';
|
||||
|
||||
/*
|
||||
* Simple Action Creators (Internal)
|
||||
* We still need to export them for tests
|
||||
@ -240,6 +242,15 @@ export function filterByField(collection: Collection, filter: ViewFilter) {
|
||||
};
|
||||
}
|
||||
|
||||
export function changeViewStyle(viewStyle: string) {
|
||||
return {
|
||||
type: CHANGE_VIEW_STYLE,
|
||||
payload: {
|
||||
style: viewStyle,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function entryPersisting(collection: Collection, entry: EntryMap) {
|
||||
return {
|
||||
type: ENTRY_PERSIST_REQUEST,
|
||||
|
@ -11,10 +11,9 @@ import CollectionTop from './CollectionTop';
|
||||
import EntriesCollection from './Entries/EntriesCollection';
|
||||
import EntriesSearch from './Entries/EntriesSearch';
|
||||
import CollectionControls from './CollectionControls';
|
||||
import { sortByField, filterByField } from '../../actions/entries';
|
||||
import { sortByField, filterByField, changeViewStyle } from '../../actions/entries';
|
||||
import { selectSortableFields, selectViewFilters } from '../../reducers/collections';
|
||||
import { selectEntriesSort, selectEntriesFilter } from '../../reducers/entries';
|
||||
import { VIEW_STYLE_LIST } from '../../constants/collectionViews';
|
||||
import { selectEntriesSort, selectEntriesFilter, selectViewStyle } from '../../reducers/entries';
|
||||
|
||||
const CollectionContainer = styled.div`
|
||||
margin: ${lengths.pageMargin};
|
||||
@ -46,18 +45,10 @@ export class Collection extends React.Component {
|
||||
onSortClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
state = {
|
||||
viewStyle: VIEW_STYLE_LIST,
|
||||
};
|
||||
|
||||
renderEntriesCollection = () => {
|
||||
const { collection, filterTerm } = this.props;
|
||||
const { collection, filterTerm, viewStyle } = this.props;
|
||||
return (
|
||||
<EntriesCollection
|
||||
collection={collection}
|
||||
viewStyle={this.state.viewStyle}
|
||||
filterTerm={filterTerm}
|
||||
/>
|
||||
<EntriesCollection collection={collection} viewStyle={viewStyle} filterTerm={filterTerm} />
|
||||
);
|
||||
};
|
||||
|
||||
@ -71,12 +62,6 @@ export class Collection extends React.Component {
|
||||
);
|
||||
};
|
||||
|
||||
handleChangeViewStyle = viewStyle => {
|
||||
if (this.state.viewStyle !== viewStyle) {
|
||||
this.setState({ viewStyle });
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
collection,
|
||||
@ -93,6 +78,8 @@ export class Collection extends React.Component {
|
||||
t,
|
||||
onFilterClick,
|
||||
filter,
|
||||
onChangeViewStyle,
|
||||
viewStyle,
|
||||
} = this.props;
|
||||
|
||||
let newEntryUrl = collection.get('create') ? getNewEntryUrl(collectionName) : '';
|
||||
@ -125,8 +112,8 @@ export class Collection extends React.Component {
|
||||
<>
|
||||
<CollectionTop collection={collection} newEntryUrl={newEntryUrl} />
|
||||
<CollectionControls
|
||||
viewStyle={this.state.viewStyle}
|
||||
onChangeViewStyle={this.handleChangeViewStyle}
|
||||
viewStyle={viewStyle}
|
||||
onChangeViewStyle={onChangeViewStyle}
|
||||
sortableFields={sortableFields}
|
||||
onSortClick={onSortClick}
|
||||
sort={sort}
|
||||
@ -153,6 +140,7 @@ function mapStateToProps(state, ownProps) {
|
||||
const sortableFields = selectSortableFields(collection, t);
|
||||
const viewFilters = selectViewFilters(collection);
|
||||
const filter = selectEntriesFilter(state.entries, collection.get('name'));
|
||||
const viewStyle = selectViewStyle(state.entries);
|
||||
|
||||
return {
|
||||
collection,
|
||||
@ -165,12 +153,14 @@ function mapStateToProps(state, ownProps) {
|
||||
sortableFields,
|
||||
viewFilters,
|
||||
filter,
|
||||
viewStyle,
|
||||
};
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
sortByField,
|
||||
filterByField,
|
||||
changeViewStyle,
|
||||
};
|
||||
|
||||
const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
@ -180,6 +170,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
|
||||
onSortClick: (key, direction) =>
|
||||
dispatchProps.sortByField(stateProps.collection, key, direction),
|
||||
onFilterClick: filter => dispatchProps.filterByField(stateProps.collection, filter),
|
||||
onChangeViewStyle: viewStyle => dispatchProps.changeViewStyle(viewStyle),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -30,12 +30,10 @@ exports[`Collection should render connected component 1`] = `
|
||||
filter="Map {}"
|
||||
sortablefields=""
|
||||
viewfilters=""
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [] }"
|
||||
filterterm=""
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
@ -66,12 +64,9 @@ exports[`Collection should render with collection with create url 1`] = `
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
newentryurl="/collections/pages/new"
|
||||
/>
|
||||
<mock-collection-controls
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
<mock-collection-controls />
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
@ -103,13 +98,10 @@ exports[`Collection should render with collection with create url and path 1`] =
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
newentryurl="/collections/pages/new?path=dir1/dir2"
|
||||
/>
|
||||
<mock-collection-controls
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
<mock-collection-controls />
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": true }"
|
||||
filterterm="dir1/dir2"
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
@ -140,12 +132,9 @@ exports[`Collection should render with collection without create url 1`] = `
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
newentryurl=""
|
||||
/>
|
||||
<mock-collection-controls
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
<mock-collection-controls />
|
||||
<mock-entries-collection
|
||||
collection="Map { \\"name\\": \\"pages\\", \\"sortableFields\\": List [], \\"view_filters\\": List [], \\"create\\": false }"
|
||||
viewstyle="VIEW_STYLE_LIST"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
FILTER_ENTRIES_REQUEST,
|
||||
FILTER_ENTRIES_SUCCESS,
|
||||
FILTER_ENTRIES_FAILURE,
|
||||
CHANGE_VIEW_STYLE,
|
||||
} from '../actions/entries';
|
||||
import { SEARCH_ENTRIES_SUCCESS } from '../actions/search';
|
||||
import {
|
||||
@ -42,12 +43,14 @@ import {
|
||||
FilterMap,
|
||||
EntriesFilterRequestPayload,
|
||||
EntriesFilterFailurePayload,
|
||||
ChangeViewStylePayload,
|
||||
} from '../types/redux';
|
||||
import { folderFormatter } from '../lib/formatters';
|
||||
import { isAbsolutePath, basename } from 'netlify-cms-lib-util';
|
||||
import { trim, once, sortBy, set, orderBy } from 'lodash';
|
||||
import { selectSortDataPath } from './collections';
|
||||
import { stringTemplate } from 'netlify-cms-lib-widgets';
|
||||
import { VIEW_STYLE_LIST } from '../constants/collectionViews';
|
||||
|
||||
const { keyToPathArray } = stringTemplate;
|
||||
|
||||
@ -58,6 +61,7 @@ let page: number;
|
||||
let slug: string;
|
||||
|
||||
const storageSortKey = 'netlify-cms.entries.sort';
|
||||
const viewStyleKey = 'netlify-cms.entries.viewStyle';
|
||||
type StorageSortObject = SortObject & { index: number };
|
||||
type StorageSort = { [collection: string]: { [key: string]: StorageSortObject } };
|
||||
|
||||
@ -107,8 +111,30 @@ const persistSort = (sort: Sort | undefined) => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadViewStyle = once(() => {
|
||||
const viewStyle = localStorage.getItem(viewStyleKey);
|
||||
if (viewStyle) {
|
||||
return viewStyle;
|
||||
}
|
||||
|
||||
localStorage.setItem(viewStyleKey, VIEW_STYLE_LIST);
|
||||
return VIEW_STYLE_LIST;
|
||||
});
|
||||
|
||||
const clearViewStyle = () => {
|
||||
localStorage.removeItem(viewStyleKey);
|
||||
};
|
||||
|
||||
const persistViewStyle = (viewStyle: string | undefined) => {
|
||||
if (viewStyle) {
|
||||
localStorage.setItem(viewStyleKey, viewStyle);
|
||||
} else {
|
||||
clearViewStyle();
|
||||
}
|
||||
};
|
||||
|
||||
const entries = (
|
||||
state = Map({ entities: Map(), pages: Map(), sort: loadSort() }),
|
||||
state = Map({ entities: Map(), pages: Map(), sort: loadSort(), viewStyle: loadViewStyle() }),
|
||||
action: EntriesAction,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
@ -272,6 +298,16 @@ const entries = (
|
||||
return newState;
|
||||
}
|
||||
|
||||
case CHANGE_VIEW_STYLE: {
|
||||
const payload = (action.payload as unknown) as ChangeViewStylePayload;
|
||||
const { style } = payload;
|
||||
const newState = state.withMutations(map => {
|
||||
map.setIn(['viewStyle'], style);
|
||||
});
|
||||
persistViewStyle(newState.get('viewStyle') as string);
|
||||
return newState;
|
||||
}
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@ -308,6 +344,10 @@ export const selectEntriesFilterFields = (entries: Entries, collection: string)
|
||||
return values;
|
||||
};
|
||||
|
||||
export const selectViewStyle = (entries: Entries) => {
|
||||
return entries.get('viewStyle');
|
||||
};
|
||||
|
||||
export const selectEntry = (state: Entries, collection: string, slug: string) =>
|
||||
state.getIn(['entities', `${collection}.${slug}`]);
|
||||
|
||||
|
@ -75,6 +75,7 @@ export type Entries = StaticallyTypedRecord<{
|
||||
entities: Entities & EntitiesObject;
|
||||
sort: Sort;
|
||||
filter: Filter;
|
||||
viewStyle: string;
|
||||
}>;
|
||||
|
||||
export type Deploys = StaticallyTypedRecord<{}>;
|
||||
@ -348,6 +349,10 @@ export interface EntriesFilterFailurePayload {
|
||||
error: Error;
|
||||
}
|
||||
|
||||
export interface ChangeViewStylePayload {
|
||||
style: string;
|
||||
}
|
||||
|
||||
export interface EntriesMoveSuccessPayload extends EntryPayload {
|
||||
entries: EntryObject[];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user