Fix scrolling sync, tweak styles
This commit is contained in:
parent
e33f3dec02
commit
e2b11ba3ff
30
packages/netlify-cms-core/src/actions/scroll.ts
Normal file
30
packages/netlify-cms-core/src/actions/scroll.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import type { AnyAction } from 'redux';
|
||||||
|
import type { ThunkDispatch } from 'redux-thunk';
|
||||||
|
import type { State } from '../types/redux';
|
||||||
|
|
||||||
|
export const SCROLL_SYNC_ENABLED = 'cms.scroll-sync-enabled';
|
||||||
|
|
||||||
|
export const TOGGLE_SCROLL = 'TOGGLE_SCROLL';
|
||||||
|
export const SET_SCROLL = 'SET_SCROLL';
|
||||||
|
|
||||||
|
export function togglingScroll() {
|
||||||
|
return {
|
||||||
|
type: TOGGLE_SCROLL,
|
||||||
|
} as const;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadScroll() {
|
||||||
|
return {
|
||||||
|
type: SET_SCROLL,
|
||||||
|
payload: localStorage.getItem(SCROLL_SYNC_ENABLED) !== 'false',
|
||||||
|
} as const;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function toggleScroll() {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
return async (dispatch: ThunkDispatch<State, undefined, AnyAction>, _getState: () => State) => {
|
||||||
|
return dispatch(togglingScroll());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ScrollAction = ReturnType<typeof togglingScroll | typeof loadScroll>;
|
@ -140,7 +140,7 @@ export function searchEntries(searchTerm: string, searchCollections: string[], p
|
|||||||
try {
|
try {
|
||||||
const response: SearchResponse = await searchPromise;
|
const response: SearchResponse = await searchPromise;
|
||||||
return dispatch(searchSuccess(response.entries, response.pagination));
|
return dispatch(searchSuccess(response.entries, response.pagination));
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
return dispatch(searchFailure(error));
|
return dispatch(searchFailure(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -177,7 +177,7 @@ export function query(
|
|||||||
try {
|
try {
|
||||||
const response: QueryResponse = await queryPromise;
|
const response: QueryResponse = await queryPromise;
|
||||||
return dispatch(querySuccess(namespace, response.hits));
|
return dispatch(querySuccess(namespace, response.hits));
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
return dispatch(queryFailure(error));
|
return dispatch(queryFailure(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -87,7 +87,7 @@ export function checkBackendStatus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispatch(statusSuccess(status));
|
dispatch(statusSuccess(status));
|
||||||
} catch (error) {
|
} catch (error: any) {
|
||||||
dispatch(statusFailure(error));
|
dispatch(statusFailure(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -36,12 +36,12 @@ TopBarProgress.config({
|
|||||||
|
|
||||||
const AppRoot = styled.div`
|
const AppRoot = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
min-height: 100vh;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const AppWrapper = styled.div`
|
const AppWrapper = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
min-height: 100vh;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const AppMainContainer = styled.div`
|
const AppMainContainer = styled.div`
|
||||||
@ -96,6 +96,7 @@ class App extends React.Component {
|
|||||||
useMediaLibrary: PropTypes.bool,
|
useMediaLibrary: PropTypes.bool,
|
||||||
openMediaLibrary: PropTypes.func.isRequired,
|
openMediaLibrary: PropTypes.func.isRequired,
|
||||||
showMediaButton: PropTypes.bool,
|
showMediaButton: PropTypes.bool,
|
||||||
|
scrollSyncEnabled: PropTypes.bool.isRequired,
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -164,6 +165,7 @@ class App extends React.Component {
|
|||||||
openMediaLibrary,
|
openMediaLibrary,
|
||||||
t,
|
t,
|
||||||
showMediaButton,
|
showMediaButton,
|
||||||
|
scrollSyncEnabled,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
if (config === null) {
|
if (config === null) {
|
||||||
@ -186,7 +188,7 @@ class App extends React.Component {
|
|||||||
const hasWorkflow = publishMode === EDITORIAL_WORKFLOW;
|
const hasWorkflow = publishMode === EDITORIAL_WORKFLOW;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollSync>
|
<ScrollSync enabled={scrollSyncEnabled}>
|
||||||
<AppRoot id="cms-root">
|
<AppRoot id="cms-root">
|
||||||
<AppWrapper className="cms-wrapper">
|
<AppWrapper className="cms-wrapper">
|
||||||
<Notifs CustomComponent={Toast} />
|
<Notifs CustomComponent={Toast} />
|
||||||
@ -269,12 +271,13 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
const { auth, config, collections, globalUI, mediaLibrary } = state;
|
const { auth, config, collections, globalUI, mediaLibrary, scroll } = state;
|
||||||
const user = auth.user;
|
const user = auth.user;
|
||||||
const isFetching = globalUI.isFetching;
|
const isFetching = globalUI.isFetching;
|
||||||
const publishMode = config.publish_mode;
|
const publishMode = config.publish_mode;
|
||||||
const useMediaLibrary = !mediaLibrary.get('externalLibrary');
|
const useMediaLibrary = !mediaLibrary.get('externalLibrary');
|
||||||
const showMediaButton = mediaLibrary.get('showMediaButton');
|
const showMediaButton = mediaLibrary.get('showMediaButton');
|
||||||
|
const scrollSyncEnabled = scroll.isScrolling;
|
||||||
return {
|
return {
|
||||||
auth,
|
auth,
|
||||||
config,
|
config,
|
||||||
@ -284,6 +287,7 @@ function mapStateToProps(state) {
|
|||||||
publishMode,
|
publishMode,
|
||||||
showMediaButton,
|
showMediaButton,
|
||||||
useMediaLibrary,
|
useMediaLibrary,
|
||||||
|
scrollSyncEnabled,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,39 @@
|
|||||||
|
import { debounce } from 'lodash';
|
||||||
|
import { Loader } from 'netlify-cms-ui-default';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { Loader } from 'netlify-cms-ui-default';
|
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { debounce } from 'lodash';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { history, navigateToCollection, navigateToNewEntry } from '../../routing/history';
|
|
||||||
import { logoutUser } from '../../actions/auth';
|
import { logoutUser } from '../../actions/auth';
|
||||||
|
import { loadDeployPreview } from '../../actions/deploys';
|
||||||
import {
|
import {
|
||||||
loadEntry,
|
deleteUnpublishedEntry,
|
||||||
loadEntries,
|
|
||||||
createDraftDuplicateFromEntry,
|
|
||||||
createEmptyDraft,
|
|
||||||
discardDraft,
|
|
||||||
changeDraftField,
|
|
||||||
changeDraftFieldValidation,
|
|
||||||
persistEntry,
|
|
||||||
deleteEntry,
|
|
||||||
persistLocalBackup,
|
|
||||||
loadLocalBackup,
|
|
||||||
retrieveLocalBackup,
|
|
||||||
deleteLocalBackup,
|
|
||||||
} from '../../actions/entries';
|
|
||||||
import {
|
|
||||||
updateUnpublishedEntryStatus,
|
|
||||||
publishUnpublishedEntry,
|
publishUnpublishedEntry,
|
||||||
unpublishPublishedEntry,
|
unpublishPublishedEntry,
|
||||||
deleteUnpublishedEntry,
|
updateUnpublishedEntryStatus,
|
||||||
} from '../../actions/editorialWorkflow';
|
} from '../../actions/editorialWorkflow';
|
||||||
import { loadDeployPreview } from '../../actions/deploys';
|
import {
|
||||||
import { selectEntry, selectUnpublishedEntry, selectDeployPreview } from '../../reducers';
|
changeDraftField,
|
||||||
|
changeDraftFieldValidation,
|
||||||
|
createDraftDuplicateFromEntry,
|
||||||
|
createEmptyDraft,
|
||||||
|
deleteEntry,
|
||||||
|
deleteLocalBackup,
|
||||||
|
discardDraft,
|
||||||
|
loadEntries,
|
||||||
|
loadEntry,
|
||||||
|
loadLocalBackup,
|
||||||
|
persistEntry,
|
||||||
|
persistLocalBackup,
|
||||||
|
retrieveLocalBackup,
|
||||||
|
} from '../../actions/entries';
|
||||||
|
import { loadScroll, toggleScroll } from '../../actions/scroll';
|
||||||
|
import { EDITORIAL_WORKFLOW, status } from '../../constants/publishModes';
|
||||||
|
import { selectDeployPreview, selectEntry, selectUnpublishedEntry } from '../../reducers';
|
||||||
import { selectFields } from '../../reducers/collections';
|
import { selectFields } from '../../reducers/collections';
|
||||||
import { status, EDITORIAL_WORKFLOW } from '../../constants/publishModes';
|
import { history, navigateToCollection, navigateToNewEntry } from '../../routing/history';
|
||||||
import EditorInterface from './EditorInterface';
|
import EditorInterface from './EditorInterface';
|
||||||
import withWorkflow from './withWorkflow';
|
import withWorkflow from './withWorkflow';
|
||||||
|
|
||||||
@ -79,6 +80,9 @@ export class Editor extends React.Component {
|
|||||||
loadLocalBackup: PropTypes.func,
|
loadLocalBackup: PropTypes.func,
|
||||||
persistLocalBackup: PropTypes.func.isRequired,
|
persistLocalBackup: PropTypes.func.isRequired,
|
||||||
deleteLocalBackup: PropTypes.func,
|
deleteLocalBackup: PropTypes.func,
|
||||||
|
toggleScroll: PropTypes.func.isRequired,
|
||||||
|
scrollSyncEnabled: PropTypes.bool.isRequired,
|
||||||
|
loadScroll: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -356,6 +360,9 @@ export class Editor extends React.Component {
|
|||||||
slug,
|
slug,
|
||||||
t,
|
t,
|
||||||
editorBackLink,
|
editorBackLink,
|
||||||
|
toggleScroll,
|
||||||
|
scrollSyncEnabled,
|
||||||
|
loadScroll,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const isPublished = !newEntry && !unpublishedEntry;
|
const isPublished = !newEntry && !unpublishedEntry;
|
||||||
@ -405,6 +412,9 @@ export class Editor extends React.Component {
|
|||||||
deployPreview={deployPreview}
|
deployPreview={deployPreview}
|
||||||
loadDeployPreview={opts => loadDeployPreview(collection, slug, entry, isPublished, opts)}
|
loadDeployPreview={opts => loadDeployPreview(collection, slug, entry, isPublished, opts)}
|
||||||
editorBackLink={editorBackLink}
|
editorBackLink={editorBackLink}
|
||||||
|
toggleScroll={toggleScroll}
|
||||||
|
scrollSyncEnabled={scrollSyncEnabled}
|
||||||
|
loadScroll={loadScroll}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -412,7 +422,7 @@ export class Editor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state, ownProps) {
|
function mapStateToProps(state, ownProps) {
|
||||||
const { collections, entryDraft, auth, config, entries, globalUI } = state;
|
const { collections, entryDraft, auth, config, entries, globalUI, scroll } = state;
|
||||||
const slug = ownProps.match.params[0];
|
const slug = ownProps.match.params[0];
|
||||||
const collection = collections.get(ownProps.match.params.name);
|
const collection = collections.get(ownProps.match.params.name);
|
||||||
const collectionName = collection.get('name');
|
const collectionName = collection.get('name');
|
||||||
@ -444,6 +454,8 @@ function mapStateToProps(state, ownProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const scrollSyncEnabled = scroll.isScrolling;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
collection,
|
collection,
|
||||||
collections,
|
collections,
|
||||||
@ -466,6 +478,7 @@ function mapStateToProps(state, ownProps) {
|
|||||||
publishedEntry,
|
publishedEntry,
|
||||||
unPublishedEntry,
|
unPublishedEntry,
|
||||||
editorBackLink,
|
editorBackLink,
|
||||||
|
scrollSyncEnabled,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,6 +502,8 @@ const mapDispatchToProps = {
|
|||||||
unpublishPublishedEntry,
|
unpublishPublishedEntry,
|
||||||
deleteUnpublishedEntry,
|
deleteUnpublishedEntry,
|
||||||
logoutUser,
|
logoutUser,
|
||||||
|
toggleScroll,
|
||||||
|
loadScroll,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withWorkflow(translate()(Editor)));
|
export default connect(mapStateToProps, mapDispatchToProps)(withWorkflow(translate()(Editor)));
|
||||||
|
@ -21,7 +21,6 @@ import { FILES } from '../../constants/collectionTypes';
|
|||||||
import { getFileFromSlug } from '../../reducers/collections';
|
import { getFileFromSlug } from '../../reducers/collections';
|
||||||
|
|
||||||
const PREVIEW_VISIBLE = 'cms.preview-visible';
|
const PREVIEW_VISIBLE = 'cms.preview-visible';
|
||||||
const SCROLL_SYNC_ENABLED = 'cms.scroll-sync-enabled';
|
|
||||||
const I18N_VISIBLE = 'cms.i18n-visible';
|
const I18N_VISIBLE = 'cms.i18n-visible';
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
@ -103,6 +102,7 @@ const Editor = styled.div`
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background-color: ${colorsRaw.white};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const PreviewPaneContainer = styled.div`
|
const PreviewPaneContainer = styled.div`
|
||||||
@ -152,10 +152,15 @@ function isPreviewEnabled(collection, entry) {
|
|||||||
class EditorInterface extends Component {
|
class EditorInterface extends Component {
|
||||||
state = {
|
state = {
|
||||||
previewVisible: localStorage.getItem(PREVIEW_VISIBLE) !== 'false',
|
previewVisible: localStorage.getItem(PREVIEW_VISIBLE) !== 'false',
|
||||||
scrollSyncEnabled: localStorage.getItem(SCROLL_SYNC_ENABLED) !== 'false',
|
|
||||||
i18nVisible: localStorage.getItem(I18N_VISIBLE) !== 'false',
|
i18nVisible: localStorage.getItem(I18N_VISIBLE) !== 'false',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.props.loadScroll();
|
||||||
|
}
|
||||||
|
|
||||||
handleOnPersist = async (opts = {}) => {
|
handleOnPersist = async (opts = {}) => {
|
||||||
const { createNew = false, duplicate = false } = opts;
|
const { createNew = false, duplicate = false } = opts;
|
||||||
await this.controlPaneRef.switchToDefaultLocale();
|
await this.controlPaneRef.switchToDefaultLocale();
|
||||||
@ -177,9 +182,8 @@ class EditorInterface extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleToggleScrollSync = () => {
|
handleToggleScrollSync = () => {
|
||||||
const newScrollSyncEnabled = !this.state.scrollSyncEnabled;
|
const { toggleScroll } = this.props;
|
||||||
this.setState({ scrollSyncEnabled: newScrollSyncEnabled });
|
toggleScroll();
|
||||||
localStorage.setItem(SCROLL_SYNC_ENABLED, newScrollSyncEnabled);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleToggleI18n = () => {
|
handleToggleI18n = () => {
|
||||||
@ -222,11 +226,10 @@ class EditorInterface extends Component {
|
|||||||
deployPreview,
|
deployPreview,
|
||||||
draftKey,
|
draftKey,
|
||||||
editorBackLink,
|
editorBackLink,
|
||||||
|
scrollSyncEnabled,
|
||||||
t,
|
t,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { scrollSyncEnabled } = this.state;
|
|
||||||
|
|
||||||
const previewEnabled = isPreviewEnabled(collection, entry);
|
const previewEnabled = isPreviewEnabled(collection, entry);
|
||||||
|
|
||||||
const collectionI18nEnabled = hasI18n(collection);
|
const collectionI18nEnabled = hasI18n(collection);
|
||||||
@ -255,7 +258,7 @@ class EditorInterface extends Component {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const editor2 = (
|
const editor2 = (
|
||||||
<ControlPaneContainer overFlow={!this.state.scrollSyncEnabled}>
|
<ControlPaneContainer overFlow={!this.props.scrollSyncEnabled}>
|
||||||
<EditorControlPane {...editorProps} locale={locales?.[1]} t={t} />
|
<EditorControlPane {...editorProps} locale={locales?.[1]} t={t} />
|
||||||
</ControlPaneContainer>
|
</ControlPaneContainer>
|
||||||
);
|
);
|
||||||
@ -265,7 +268,6 @@ class EditorInterface extends Component {
|
|||||||
: entry;
|
: entry;
|
||||||
|
|
||||||
const editorWithPreview = (
|
const editorWithPreview = (
|
||||||
<ScrollSync enabled={this.state.scrollSyncEnabled}>
|
|
||||||
<>
|
<>
|
||||||
<ReactSplitPaneGlobalStyles />
|
<ReactSplitPaneGlobalStyles />
|
||||||
<StyledSplitPane>
|
<StyledSplitPane>
|
||||||
@ -281,11 +283,10 @@ class EditorInterface extends Component {
|
|||||||
</PreviewPaneContainer>
|
</PreviewPaneContainer>
|
||||||
</StyledSplitPane>
|
</StyledSplitPane>
|
||||||
</>
|
</>
|
||||||
</ScrollSync>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const editorWithEditor = (
|
const editorWithEditor = (
|
||||||
<ScrollSync enabled={this.state.scrollSyncEnabled}>
|
<ScrollSync enabled={this.props.scrollSyncEnabled}>
|
||||||
<div>
|
<div>
|
||||||
<StyledSplitPane>
|
<StyledSplitPane>
|
||||||
<ScrollSyncPane>{editor}</ScrollSyncPane>
|
<ScrollSyncPane>{editor}</ScrollSyncPane>
|
||||||
@ -406,6 +407,9 @@ EditorInterface.propTypes = {
|
|||||||
deployPreview: PropTypes.object,
|
deployPreview: PropTypes.object,
|
||||||
loadDeployPreview: PropTypes.func.isRequired,
|
loadDeployPreview: PropTypes.func.isRequired,
|
||||||
draftKey: PropTypes.string.isRequired,
|
draftKey: PropTypes.string.isRequired,
|
||||||
|
toggleScroll: PropTypes.func.isRequired,
|
||||||
|
scrollSyncEnabled: PropTypes.bool.isRequired,
|
||||||
|
loadScroll: PropTypes.func.isRequired,
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ export class ErrorBoundary extends React.Component {
|
|||||||
return this.props.children;
|
return this.props.children;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ErrorBoundaryContainer>
|
<ErrorBoundaryContainer key="error-boundary-container">
|
||||||
<h1>{t('ui.errorBoundary.title')}</h1>
|
<h1>{t('ui.errorBoundary.title')}</h1>
|
||||||
<p>
|
<p>
|
||||||
<span>{t('ui.errorBoundary.details')}</span>
|
<span>{t('ui.errorBoundary.details')}</span>
|
||||||
@ -190,17 +190,15 @@ export class ErrorBoundary extends React.Component {
|
|||||||
<p>
|
<p>
|
||||||
{t('ui.errorBoundary.privacyWarning')
|
{t('ui.errorBoundary.privacyWarning')
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map((item, index) => (
|
.map((item, index) => [
|
||||||
<>
|
<PrivacyWarning key={`private-warning-${index}`}>{item}</PrivacyWarning>,
|
||||||
<PrivacyWarning key={index}>{item}</PrivacyWarning>
|
<br key={`break-${index}`} />,
|
||||||
<br />
|
])}
|
||||||
</>
|
|
||||||
))}
|
|
||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
<h2>{t('ui.errorBoundary.detailsHeading')}</h2>
|
<h2>{t('ui.errorBoundary.detailsHeading')}</h2>
|
||||||
<p>{errorMessage}</p>
|
<p>{errorMessage}</p>
|
||||||
{backup && showBackup && <RecoveredEntry entry={backup} t={t} />}
|
{backup && showBackup && <RecoveredEntry key="backup" entry={backup} t={t} />}
|
||||||
</ErrorBoundaryContainer>
|
</ErrorBoundaryContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import mediaLibrary from './mediaLibrary';
|
|||||||
import deploys, * as fromDeploys from './deploys';
|
import deploys, * as fromDeploys from './deploys';
|
||||||
import globalUI from './globalUI';
|
import globalUI from './globalUI';
|
||||||
import status from './status';
|
import status from './status';
|
||||||
|
import scroll from './scroll';
|
||||||
|
|
||||||
import type { Status } from '../constants/publishModes';
|
import type { Status } from '../constants/publishModes';
|
||||||
import type { State, Collection } from '../types/redux';
|
import type { State, Collection } from '../types/redux';
|
||||||
@ -33,6 +34,7 @@ const reducers = {
|
|||||||
deploys,
|
deploys,
|
||||||
globalUI,
|
globalUI,
|
||||||
status,
|
status,
|
||||||
|
scroll,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default reducers;
|
export default reducers;
|
||||||
|
28
packages/netlify-cms-core/src/reducers/scroll.ts
Normal file
28
packages/netlify-cms-core/src/reducers/scroll.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { produce } from 'immer';
|
||||||
|
|
||||||
|
import { SCROLL_SYNC_ENABLED, SET_SCROLL, TOGGLE_SCROLL } from '../actions/scroll';
|
||||||
|
|
||||||
|
import type { ScrollAction } from '../actions/scroll';
|
||||||
|
|
||||||
|
export type ScrollState = {
|
||||||
|
isScrolling: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultState: ScrollState = {
|
||||||
|
isScrolling: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const status = produce((state: ScrollState, action: ScrollAction) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case TOGGLE_SCROLL:
|
||||||
|
state.isScrolling = !state.isScrolling;
|
||||||
|
localStorage.setItem(SCROLL_SYNC_ENABLED, `${state.isScrolling}`);
|
||||||
|
break;
|
||||||
|
case SET_SCROLL:
|
||||||
|
state.isScrolling = action.payload;
|
||||||
|
localStorage.setItem(SCROLL_SYNC_ENABLED, `${state.isScrolling}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, defaultState);
|
||||||
|
|
||||||
|
export default status;
|
@ -1,15 +1,16 @@
|
|||||||
|
import type { List, Map, OrderedMap, Set } from 'immutable';
|
||||||
import type { Action } from 'redux';
|
import type { Action } from 'redux';
|
||||||
import type { StaticallyTypedRecord } from './immutable';
|
|
||||||
import type { Map, List, OrderedMap, Set } from 'immutable';
|
|
||||||
import type { FILES, FOLDER } from '../constants/collectionTypes';
|
|
||||||
import type { MediaFile as BackendMediaFile } from '../backend';
|
import type { MediaFile as BackendMediaFile } from '../backend';
|
||||||
import type { Auth } from '../reducers/auth';
|
import type { FILES, FOLDER } from '../constants/collectionTypes';
|
||||||
import type { Status } from '../reducers/status';
|
|
||||||
import type { Medias } from '../reducers/medias';
|
|
||||||
import type { Deploys } from '../reducers/deploys';
|
|
||||||
import type { Search } from '../reducers/search';
|
|
||||||
import type { GlobalUI } from '../reducers/globalUI';
|
|
||||||
import type { formatExtensions } from '../formats/formats';
|
import type { formatExtensions } from '../formats/formats';
|
||||||
|
import type { Auth } from '../reducers/auth';
|
||||||
|
import type { Deploys } from '../reducers/deploys';
|
||||||
|
import type { GlobalUI } from '../reducers/globalUI';
|
||||||
|
import type { Medias } from '../reducers/medias';
|
||||||
|
import type { ScrollState } from '../reducers/scroll';
|
||||||
|
import type { Search } from '../reducers/search';
|
||||||
|
import type { Status } from '../reducers/status';
|
||||||
|
import type { StaticallyTypedRecord } from './immutable';
|
||||||
|
|
||||||
export type CmsBackendType =
|
export type CmsBackendType =
|
||||||
| 'azure'
|
| 'azure'
|
||||||
@ -699,6 +700,7 @@ export interface State {
|
|||||||
search: Search;
|
search: Search;
|
||||||
notifs: { message: { key: string }; kind: string; id: number }[];
|
notifs: { message: { key: string }; kind: string; id: number }[];
|
||||||
status: Status;
|
status: Status;
|
||||||
|
scroll: ScrollState;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Integration {
|
export interface Integration {
|
||||||
|
@ -17,8 +17,8 @@ const StyledDropdownButton = styled(DropdownButton)`
|
|||||||
${buttons.button};
|
${buttons.button};
|
||||||
${buttons.default};
|
${buttons.default};
|
||||||
display: block;
|
display: block;
|
||||||
padding-left: 20px;
|
padding-left: 20px!important;
|
||||||
padding-right: 40px;
|
padding-right: 40px!important;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
|
@ -562,6 +562,11 @@ function GlobalStyles() {
|
|||||||
textarea {
|
textarea {
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ol-viewport {
|
||||||
|
position: absolute!important;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
/>
|
/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user