Merge branch 'main' into next
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
|
||||||
"useWorkspaces": true,
|
"useWorkspaces": true,
|
||||||
"version": "1.2.10"
|
"version": "1.2.12"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@staticcms/app",
|
"name": "@staticcms/app",
|
||||||
"version": "1.2.10",
|
"version": "1.2.12",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Static CMS application.",
|
"description": "Static CMS application.",
|
||||||
"repository": "https://github.com/StaticJsCMS/static-cms",
|
"repository": "https://github.com/StaticJsCMS/static-cms",
|
||||||
@ -35,7 +35,7 @@
|
|||||||
"@babel/eslint-parser": "7.19.1",
|
"@babel/eslint-parser": "7.19.1",
|
||||||
"@babel/runtime": "7.21.0",
|
"@babel/runtime": "7.21.0",
|
||||||
"@emotion/babel-preset-css-prop": "11.10.0",
|
"@emotion/babel-preset-css-prop": "11.10.0",
|
||||||
"@staticcms/core": "^1.2.10",
|
"@staticcms/core": "^1.2.12",
|
||||||
"buffer": "6.0.3",
|
"buffer": "6.0.3",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
@ -57,11 +57,11 @@
|
|||||||
"@babel/preset-typescript": "7.21.0",
|
"@babel/preset-typescript": "7.21.0",
|
||||||
"@emotion/eslint-plugin": "11.10.0",
|
"@emotion/eslint-plugin": "11.10.0",
|
||||||
"@emotion/jest": "11.10.5",
|
"@emotion/jest": "11.10.5",
|
||||||
"@types/node": "16.18.12",
|
"@types/node": "16.18.13",
|
||||||
"@types/react": "18.0.28",
|
"@types/react": "18.0.28",
|
||||||
"@types/react-dom": "18.0.11",
|
"@types/react-dom": "18.0.11",
|
||||||
"@typescript-eslint/eslint-plugin": "5.53.0",
|
"@typescript-eslint/eslint-plugin": "5.54.0",
|
||||||
"@typescript-eslint/parser": "5.53.0",
|
"@typescript-eslint/parser": "5.54.0",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"babel-loader": "9.1.2",
|
"babel-loader": "9.1.2",
|
||||||
"babel-plugin-emotion": "11.0.0",
|
"babel-plugin-emotion": "11.0.0",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@staticcms/core",
|
"name": "@staticcms/core",
|
||||||
"version": "1.2.10",
|
"version": "1.2.12",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Static CMS core application.",
|
"description": "Static CMS core application.",
|
||||||
"repository": "https://github.com/StaticJsCMS/static-cms",
|
"repository": "https://github.com/StaticJsCMS/static-cms",
|
||||||
@ -54,7 +54,7 @@
|
|||||||
"@codemirror/language": "6.6.0",
|
"@codemirror/language": "6.6.0",
|
||||||
"@codemirror/language-data": "6.1.0",
|
"@codemirror/language-data": "6.1.0",
|
||||||
"@codemirror/legacy-modes": "6.3.1",
|
"@codemirror/legacy-modes": "6.3.1",
|
||||||
"@codemirror/lint": "6.1.1",
|
"@codemirror/lint": "6.2.0",
|
||||||
"@codemirror/search": "6.2.3",
|
"@codemirror/search": "6.2.3",
|
||||||
"@codemirror/state": "6.2.0",
|
"@codemirror/state": "6.2.0",
|
||||||
"@codemirror/theme-one-dark": "6.1.1",
|
"@codemirror/theme-one-dark": "6.1.1",
|
||||||
@ -76,9 +76,9 @@
|
|||||||
"@reduxjs/toolkit": "1.9.3",
|
"@reduxjs/toolkit": "1.9.3",
|
||||||
"@styled-icons/fluentui-system-regular": "10.47.0",
|
"@styled-icons/fluentui-system-regular": "10.47.0",
|
||||||
"@styled-icons/remix-editor": "10.46.0",
|
"@styled-icons/remix-editor": "10.46.0",
|
||||||
"@udecode/plate": "19.6.0",
|
"@udecode/plate": "19.7.0",
|
||||||
"@udecode/plate-juice": "19.5.0",
|
"@udecode/plate-juice": "19.7.0",
|
||||||
"@udecode/plate-serializer-md": "19.5.0",
|
"@udecode/plate-serializer-md": "19.7.0",
|
||||||
"@uiw/codemirror-extensions-langs": "4.19.9",
|
"@uiw/codemirror-extensions-langs": "4.19.9",
|
||||||
"@uiw/react-codemirror": "4.19.9",
|
"@uiw/react-codemirror": "4.19.9",
|
||||||
"ajv": "8.12.0",
|
"ajv": "8.12.0",
|
||||||
@ -144,7 +144,7 @@
|
|||||||
"slate": "0.91.4",
|
"slate": "0.91.4",
|
||||||
"slate-history": "0.86.0",
|
"slate-history": "0.86.0",
|
||||||
"slate-hyperscript": "0.77.0",
|
"slate-hyperscript": "0.77.0",
|
||||||
"slate-react": "0.91.5",
|
"slate-react": "0.91.6",
|
||||||
"stream-browserify": "3.0.0",
|
"stream-browserify": "3.0.0",
|
||||||
"styled-components": "5.3.6",
|
"styled-components": "5.3.6",
|
||||||
"symbol-observable": "4.0.0",
|
"symbol-observable": "4.0.0",
|
||||||
@ -193,7 +193,7 @@
|
|||||||
"@types/jwt-decode": "2.2.1",
|
"@types/jwt-decode": "2.2.1",
|
||||||
"@types/lodash": "4.14.191",
|
"@types/lodash": "4.14.191",
|
||||||
"@types/minimatch": "5.1.2",
|
"@types/minimatch": "5.1.2",
|
||||||
"@types/node": "16.18.12",
|
"@types/node": "16.18.13",
|
||||||
"@types/node-fetch": "2.6.2",
|
"@types/node-fetch": "2.6.2",
|
||||||
"@types/react": "18.0.28",
|
"@types/react": "18.0.28",
|
||||||
"@types/react-color": "3.0.6",
|
"@types/react-color": "3.0.6",
|
||||||
@ -203,8 +203,8 @@
|
|||||||
"@types/styled-components": "5.1.26",
|
"@types/styled-components": "5.1.26",
|
||||||
"@types/url-join": "4.0.1",
|
"@types/url-join": "4.0.1",
|
||||||
"@types/uuid": "9.0.1",
|
"@types/uuid": "9.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "5.53.0",
|
"@typescript-eslint/eslint-plugin": "5.54.0",
|
||||||
"@typescript-eslint/parser": "5.53.0",
|
"@typescript-eslint/parser": "5.54.0",
|
||||||
"axios": "1.3.4",
|
"axios": "1.3.4",
|
||||||
"babel-core": "7.0.0-bridge.0",
|
"babel-core": "7.0.0-bridge.0",
|
||||||
"babel-loader": "9.1.2",
|
"babel-loader": "9.1.2",
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
/* eslint-disable import/prefer-default-export */
|
|
||||||
export const createHashHistory = jest.fn();
|
|
@ -1,18 +0,0 @@
|
|||||||
import { history } from '../routing/history';
|
|
||||||
import { getCollectionUrl, getNewEntryUrl } from '../lib/urlHelper';
|
|
||||||
|
|
||||||
export function searchCollections(query: string, collection?: string) {
|
|
||||||
if (collection) {
|
|
||||||
history.push(`/collections/${collection}/search/${query}`);
|
|
||||||
} else {
|
|
||||||
history.push(`/search/${query}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function showCollection(collectionName: string) {
|
|
||||||
history.push(getCollectionUrl(collectionName));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createNewEntry(collectionName: string) {
|
|
||||||
history.push(getNewEntryUrl(collectionName));
|
|
||||||
}
|
|
@ -48,7 +48,6 @@ import {
|
|||||||
selectIsFetching,
|
selectIsFetching,
|
||||||
selectPublishedSlugs,
|
selectPublishedSlugs,
|
||||||
} from '../reducers/selectors/entries';
|
} from '../reducers/selectors/entries';
|
||||||
import { navigateToEntry } from '../routing/history';
|
|
||||||
import { addSnackbar } from '../store/slices/snackbars';
|
import { addSnackbar } from '../store/slices/snackbars';
|
||||||
import { createAssetProxy } from '../valueObjects/AssetProxy';
|
import { createAssetProxy } from '../valueObjects/AssetProxy';
|
||||||
import createEntry from '../valueObjects/createEntry';
|
import createEntry from '../valueObjects/createEntry';
|
||||||
@ -56,6 +55,7 @@ import { addAssets, getAsset } from './media';
|
|||||||
import { loadMedia, waitForMediaLibraryToLoad } from './mediaLibrary';
|
import { loadMedia, waitForMediaLibraryToLoad } from './mediaLibrary';
|
||||||
import { waitUntil } from './waitUntil';
|
import { waitUntil } from './waitUntil';
|
||||||
|
|
||||||
|
import type { NavigateFunction } from 'react-router-dom';
|
||||||
import type { AnyAction } from 'redux';
|
import type { AnyAction } from 'redux';
|
||||||
import type { ThunkDispatch } from 'redux-thunk';
|
import type { ThunkDispatch } from 'redux-thunk';
|
||||||
import type { Backend } from '../backend';
|
import type { Backend } from '../backend';
|
||||||
@ -950,7 +950,7 @@ export function getSerializedEntry(collection: Collection, entry: Entry): Entry
|
|||||||
return serializedEntry;
|
return serializedEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function persistEntry(collection: Collection) {
|
export function persistEntry(collection: Collection, navigate: NavigateFunction) {
|
||||||
return async (dispatch: ThunkDispatch<RootState, {}, AnyAction>, getState: () => RootState) => {
|
return async (dispatch: ThunkDispatch<RootState, {}, AnyAction>, getState: () => RootState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const entryDraft = state.entryDraft;
|
const entryDraft = state.entryDraft;
|
||||||
@ -1039,7 +1039,7 @@ export function persistEntry(collection: Collection) {
|
|||||||
}
|
}
|
||||||
if (entry.slug !== newSlug) {
|
if (entry.slug !== newSlug) {
|
||||||
await dispatch(loadEntry(collection, newSlug));
|
await dispatch(loadEntry(collection, newSlug));
|
||||||
navigateToEntry(collection.name, newSlug);
|
navigate(`/collections/${collection.name}/entries/${newSlug}`);
|
||||||
} else {
|
} else {
|
||||||
await dispatch(loadEntry(collection, newSlug, true));
|
await dispatch(loadEntry(collection, newSlug, true));
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,23 @@ import { styled } from '@mui/material/styles';
|
|||||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Navigate, Route, Routes, useLocation, useParams } from 'react-router-dom';
|
import {
|
||||||
|
Navigate,
|
||||||
|
Route,
|
||||||
|
Routes,
|
||||||
|
useLocation,
|
||||||
|
useNavigate,
|
||||||
|
useParams,
|
||||||
|
useSearchParams,
|
||||||
|
} from 'react-router-dom';
|
||||||
import { ScrollSync } from 'react-scroll-sync';
|
import { ScrollSync } from 'react-scroll-sync';
|
||||||
import TopBarProgress from 'react-topbar-progress-indicator';
|
import TopBarProgress from 'react-topbar-progress-indicator';
|
||||||
|
|
||||||
import { loginUser as loginUserAction } from '@staticcms/core/actions/auth';
|
import { loginUser as loginUserAction } from '@staticcms/core/actions/auth';
|
||||||
import { discardDraft as discardDraftAction } from '@staticcms/core/actions/entries';
|
import { discardDraft } from '@staticcms/core/actions/entries';
|
||||||
import { currentBackend } from '@staticcms/core/backend';
|
import { currentBackend } from '@staticcms/core/backend';
|
||||||
import { colors, GlobalStyles } from '@staticcms/core/components/UI/styles';
|
import { colors, GlobalStyles } from '@staticcms/core/components/UI/styles';
|
||||||
import { history } from '@staticcms/core/routing/history';
|
import { useAppDispatch } from '@staticcms/core/store/hooks';
|
||||||
import { getDefaultPath } from '../../lib/util/collection.util';
|
import { getDefaultPath } from '../../lib/util/collection.util';
|
||||||
import CollectionRoute from '../collection/CollectionRoute';
|
import CollectionRoute from '../collection/CollectionRoute';
|
||||||
import EditorRoute from '../editor/EditorRoute';
|
import EditorRoute from '../editor/EditorRoute';
|
||||||
@ -82,8 +90,10 @@ const App = ({
|
|||||||
useMediaLibrary,
|
useMediaLibrary,
|
||||||
t,
|
t,
|
||||||
scrollSyncEnabled,
|
scrollSyncEnabled,
|
||||||
discardDraft,
|
|
||||||
}: TranslatedProps<AppProps>) => {
|
}: TranslatedProps<AppProps>) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const configError = useCallback(
|
const configError = useCallback(
|
||||||
(error?: string) => {
|
(error?: string) => {
|
||||||
return (
|
return (
|
||||||
@ -140,22 +150,28 @@ const App = ({
|
|||||||
base_url={config.config.backend.base_url}
|
base_url={config.config.backend.base_url}
|
||||||
authEndpoint={config.config.backend.auth_endpoint}
|
authEndpoint={config.config.backend.auth_endpoint}
|
||||||
config={config.config}
|
config={config.config}
|
||||||
clearHash={() => history.replace('/')}
|
clearHash={() => navigate('/', { replace: true })}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}, [AuthComponent, auth.error, auth.isFetching, config.config, handleLogin, t]);
|
}, [AuthComponent, auth.error, auth.isFetching, config.config, handleLogin, navigate, t]);
|
||||||
|
|
||||||
const defaultPath = useMemo(() => getDefaultPath(collections), [collections]);
|
const defaultPath = useMemo(() => getDefaultPath(collections), [collections]);
|
||||||
|
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!/\/collections\/[a-zA-Z0-9_-]+\/entries\/[a-zA-Z0-9_-]+/g.test(pathname)) {
|
if (
|
||||||
discardDraft();
|
/\/collections\/[a-zA-Z0-9_-]+\/entries\/[a-zA-Z0-9_-]+/g.test(pathname) ||
|
||||||
|
(/\/collections\/[a-zA-Z0-9_-]+\/new/g.test(pathname) &&
|
||||||
|
searchParams.get('duplicate') === 'true')
|
||||||
|
) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, [pathname]);
|
dispatch(discardDraft());
|
||||||
|
}, [dispatch, pathname, searchParams]);
|
||||||
|
|
||||||
const content = useMemo(() => {
|
const content = useMemo(() => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@ -265,7 +281,6 @@ function mapStateToProps(state: RootState) {
|
|||||||
|
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
loginUser: loginUserAction,
|
loginUser: loginUserAction,
|
||||||
discardDraft: discardDraftAction,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
||||||
|
@ -12,13 +12,13 @@ import Toolbar from '@mui/material/Toolbar';
|
|||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
||||||
import { createNewEntry } from '@staticcms/core/actions/collections';
|
|
||||||
import { openMediaLibrary as openMediaLibraryAction } from '@staticcms/core/actions/mediaLibrary';
|
import { openMediaLibrary as openMediaLibraryAction } from '@staticcms/core/actions/mediaLibrary';
|
||||||
import { checkBackendStatus as checkBackendStatusAction } from '@staticcms/core/actions/status';
|
import { checkBackendStatus as checkBackendStatusAction } from '@staticcms/core/actions/status';
|
||||||
import { buttons, colors } from '@staticcms/core/components/UI/styles';
|
import { buttons, colors } from '@staticcms/core/components/UI/styles';
|
||||||
import { stripProtocol } from '@staticcms/core/lib/urlHelper';
|
import { stripProtocol, getNewEntryUrl } from '@staticcms/core/lib/urlHelper';
|
||||||
import NavLink from '../UI/NavLink';
|
import NavLink from '../UI/NavLink';
|
||||||
import SettingsDropdown from '../UI/SettingsDropdown';
|
import SettingsDropdown from '../UI/SettingsDropdown';
|
||||||
|
|
||||||
@ -82,9 +82,7 @@ const Header = ({
|
|||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleCreatePostClick = useCallback((collectionName: string) => {
|
const navigate = useNavigate();
|
||||||
createNewEntry(collectionName);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const creatableCollections = useMemo(
|
const creatableCollections = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -148,7 +146,7 @@ const Header = ({
|
|||||||
{creatableCollections.map(collection => (
|
{creatableCollections.map(collection => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={collection.name}
|
key={collection.name}
|
||||||
onClick={() => handleCreatePostClick(collection.name)}
|
onClick={() => navigate(getNewEntryUrl(collection.name))}
|
||||||
>
|
>
|
||||||
{collection.label_singular || collection.label}
|
{collection.label_singular || collection.label}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
@ -83,6 +83,10 @@ const CollectionView = ({
|
|||||||
}, [collection]);
|
}, [collection]);
|
||||||
|
|
||||||
const newEntryUrl = useMemo(() => {
|
const newEntryUrl = useMemo(() => {
|
||||||
|
if (!collectionName || !collection) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
let url = 'fields' in collection && collection.create ? getNewEntryUrl(collectionName) : '';
|
let url = 'fields' in collection && collection.create ? getNewEntryUrl(collectionName) : '';
|
||||||
if (url && filterTerm) {
|
if (url && filterTerm) {
|
||||||
url = getNewEntryUrl(collectionName);
|
url = getNewEntryUrl(collectionName);
|
||||||
@ -90,6 +94,7 @@ const CollectionView = ({
|
|||||||
url = `${newEntryUrl}?path=${filterTerm}`;
|
url = `${newEntryUrl}?path=${filterTerm}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
}, [collection, collectionName, filterTerm]);
|
}, [collection, collectionName, filterTerm]);
|
||||||
|
|
||||||
@ -120,6 +125,10 @@ const CollectionView = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!collection) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EntriesCollection
|
<EntriesCollection
|
||||||
collection={collection}
|
collection={collection}
|
||||||
@ -142,21 +151,21 @@ const CollectionView = ({
|
|||||||
|
|
||||||
const onSortClick = useCallback(
|
const onSortClick = useCallback(
|
||||||
async (key: string, direction?: SortDirection) => {
|
async (key: string, direction?: SortDirection) => {
|
||||||
await sortByField(collection, key, direction);
|
collection && (await sortByField(collection, key, direction));
|
||||||
},
|
},
|
||||||
[collection, sortByField],
|
[collection, sortByField],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onFilterClick = useCallback(
|
const onFilterClick = useCallback(
|
||||||
async (filter: ViewFilter) => {
|
async (filter: ViewFilter) => {
|
||||||
await filterByField(collection, filter);
|
collection && (await filterByField(collection, filter));
|
||||||
},
|
},
|
||||||
[collection, filterByField],
|
[collection, filterByField],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onGroupClick = useCallback(
|
const onGroupClick = useCallback(
|
||||||
async (group: ViewGroup) => {
|
async (group: ViewGroup) => {
|
||||||
await groupByField(collection, group);
|
collection && (await groupByField(collection, group));
|
||||||
},
|
},
|
||||||
[collection, groupByField],
|
[collection, groupByField],
|
||||||
);
|
);
|
||||||
@ -176,7 +185,7 @@ const CollectionView = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultSort = collection.sortable_fields?.default;
|
const defaultSort = collection?.sortable_fields?.default;
|
||||||
if (!defaultSort || !defaultSort.field) {
|
if (!defaultSort || !defaultSort.field) {
|
||||||
if (!readyToLoad) {
|
if (!readyToLoad) {
|
||||||
setReadyToLoad(true);
|
setReadyToLoad(true);
|
||||||
@ -220,7 +229,7 @@ const CollectionView = ({
|
|||||||
<>
|
<>
|
||||||
<SearchResultContainer>
|
<SearchResultContainer>
|
||||||
<SearchResultHeading>
|
<SearchResultHeading>
|
||||||
{t(searchResultKey, { searchTerm, collection: collection.label })}
|
{t(searchResultKey, { searchTerm, collection: collection?.label })}
|
||||||
</SearchResultHeading>
|
</SearchResultHeading>
|
||||||
</SearchResultContainer>
|
</SearchResultContainer>
|
||||||
<CollectionControls viewStyle={viewStyle} onChangeViewStyle={changeViewStyle} t={t} />
|
<CollectionControls viewStyle={viewStyle} onChangeViewStyle={changeViewStyle} t={t} />
|
||||||
@ -254,7 +263,7 @@ const CollectionView = ({
|
|||||||
interface CollectionViewOwnProps {
|
interface CollectionViewOwnProps {
|
||||||
isSearchResults?: boolean;
|
isSearchResults?: boolean;
|
||||||
isSingleSearchResult?: boolean;
|
isSingleSearchResult?: boolean;
|
||||||
name: string;
|
name?: string;
|
||||||
searchTerm?: string;
|
searchTerm?: string;
|
||||||
filterTerm?: string;
|
filterTerm?: string;
|
||||||
}
|
}
|
||||||
@ -270,13 +279,13 @@ function mapStateToProps(state: RootState, ownProps: TranslatedProps<CollectionV
|
|||||||
filterTerm = '',
|
filterTerm = '',
|
||||||
t,
|
t,
|
||||||
} = ownProps;
|
} = ownProps;
|
||||||
const collection: Collection = name ? collections[name] : collections[0];
|
const collection = (name ? collections[name] : collections[0]) as Collection | undefined;
|
||||||
const sort = selectEntriesSort(state, collection.name);
|
const sort = selectEntriesSort(state, collection?.name);
|
||||||
const sortableFields = selectSortableFields(collection, t);
|
const sortableFields = selectSortableFields(collection, t);
|
||||||
const viewFilters = selectViewFilters(collection);
|
const viewFilters = selectViewFilters(collection);
|
||||||
const viewGroups = selectViewGroups(collection);
|
const viewGroups = selectViewGroups(collection);
|
||||||
const filter = selectEntriesFilter(state, collection.name);
|
const filter = selectEntriesFilter(state, collection?.name);
|
||||||
const group = selectEntriesGroup(state, collection.name);
|
const group = selectEntriesGroup(state, collection?.name);
|
||||||
const viewStyle = selectViewStyle(state);
|
const viewStyle = selectViewStyle(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -28,11 +28,11 @@ const CollectionRoute = ({
|
|||||||
|
|
||||||
const defaultPath = useMemo(() => getDefaultPath(collections), [collections]);
|
const defaultPath = useMemo(() => getDefaultPath(collections), [collections]);
|
||||||
|
|
||||||
if (!name || !collection) {
|
if (!searchTerm && (!name || !collection)) {
|
||||||
return <Navigate to={defaultPath} />;
|
return <Navigate to={defaultPath} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('files' in collection && collection.files?.length === 1) {
|
if (collection && 'files' in collection && collection.files?.length === 1) {
|
||||||
return <Navigate to={`/collections/${collection.name}/entries/${collection.files[0].name}`} />;
|
return <Navigate to={`/collections/${collection.name}/entries/${collection.files[0].name}`} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ const EntriesSearch = ({
|
|||||||
searchEntries,
|
searchEntries,
|
||||||
clearSearch,
|
clearSearch,
|
||||||
}: EntriesSearchProps) => {
|
}: EntriesSearchProps) => {
|
||||||
|
console.log('collections', collections);
|
||||||
const collectionNames = useMemo(() => Object.keys(collections), [collections]);
|
const collectionNames = useMemo(() => Object.keys(collections), [collections]);
|
||||||
|
|
||||||
const getCursor = useCallback(() => {
|
const getCursor = useCallback(() => {
|
||||||
@ -80,6 +81,7 @@ function mapStateToProps(state: RootState, ownProps: EntriesSearchOwnProps) {
|
|||||||
const isFetching = state.search.isFetching;
|
const isFetching = state.search.isFetching;
|
||||||
const page = state.search.page;
|
const page = state.search.page;
|
||||||
const entries = selectSearchedEntries(state, collectionNames);
|
const entries = selectSearchedEntries(state, collectionNames);
|
||||||
|
console.log('searched entries', entries);
|
||||||
return { isFetching, page, collections, viewStyle, entries, searchTerm };
|
return { isFetching, page, collections, viewStyle, entries, searchTerm };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ import ListItemText from '@mui/material/ListItemText';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { searchCollections } from '@staticcms/core/actions/collections';
|
|
||||||
import { colors } from '@staticcms/core/components/UI/styles';
|
import { colors } from '@staticcms/core/components/UI/styles';
|
||||||
import { getAdditionalLinks, getIcon } from '@staticcms/core/lib/registry';
|
import { getAdditionalLinks, getIcon } from '@staticcms/core/lib/registry';
|
||||||
import NavLink from '../UI/NavLink';
|
import NavLink from '../UI/NavLink';
|
||||||
@ -48,6 +48,15 @@ const Sidebar = ({
|
|||||||
t,
|
t,
|
||||||
filterTerm,
|
filterTerm,
|
||||||
}: TranslatedProps<SidebarProps>) => {
|
}: TranslatedProps<SidebarProps>) => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
function searchCollections(query: string, collection?: string) {
|
||||||
|
if (collection) {
|
||||||
|
navigate(`/collections/${collection}/search/${query}`);
|
||||||
|
} else {
|
||||||
|
navigate(`/search/${query}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const collectionLinks = useMemo(
|
const collectionLinks = useMemo(
|
||||||
() =>
|
() =>
|
||||||
Object.values(collections)
|
Object.values(collections)
|
||||||
|
@ -1,31 +1,28 @@
|
|||||||
|
import { createHashHistory } from 'history';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { logoutUser as logoutUserAction } from '@staticcms/core/actions/auth';
|
import { logoutUser } from '@staticcms/core/actions/auth';
|
||||||
import {
|
import {
|
||||||
createDraftDuplicateFromEntry as createDraftDuplicateFromEntryAction,
|
createDraftDuplicateFromEntry,
|
||||||
createEmptyDraft as createEmptyDraftAction,
|
createEmptyDraft,
|
||||||
deleteDraftLocalBackup as deleteDraftLocalBackupAction,
|
deleteDraftLocalBackup,
|
||||||
deleteEntry as deleteEntryAction,
|
deleteEntry,
|
||||||
deleteLocalBackup as deleteLocalBackupAction,
|
deleteLocalBackup,
|
||||||
discardDraft as discardDraftAction,
|
loadEntry,
|
||||||
loadEntries as loadEntriesAction,
|
loadLocalBackup,
|
||||||
loadEntry as loadEntryAction,
|
persistEntry,
|
||||||
loadLocalBackup as loadLocalBackupAction,
|
persistLocalBackup,
|
||||||
persistEntry as persistEntryAction,
|
retrieveLocalBackup,
|
||||||
persistLocalBackup as persistLocalBackupAction,
|
|
||||||
retrieveLocalBackup as retrieveLocalBackupAction,
|
|
||||||
} from '@staticcms/core/actions/entries';
|
} from '@staticcms/core/actions/entries';
|
||||||
import {
|
import { loadScroll, toggleScroll } from '@staticcms/core/actions/scroll';
|
||||||
loadScroll as loadScrollAction,
|
|
||||||
toggleScroll as toggleScrollAction,
|
|
||||||
} from '@staticcms/core/actions/scroll';
|
|
||||||
import { selectFields } from '@staticcms/core/lib/util/collection.util';
|
import { selectFields } from '@staticcms/core/lib/util/collection.util';
|
||||||
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
import { useWindowEvent } from '@staticcms/core/lib/util/window.util';
|
||||||
import { selectEntry } from '@staticcms/core/reducers/selectors/entries';
|
import { selectEntry } from '@staticcms/core/reducers/selectors/entries';
|
||||||
import { history, navigateToCollection, navigateToNewEntry } from '@staticcms/core/routing/history';
|
import { useAppDispatch } from '@staticcms/core/store/hooks';
|
||||||
import confirm from '../UI/Confirm';
|
import confirm from '../UI/Confirm';
|
||||||
import Loader from '../UI/Loader';
|
import Loader from '../UI/Loader';
|
||||||
import EditorInterface from './EditorInterface';
|
import EditorInterface from './EditorInterface';
|
||||||
@ -38,10 +35,10 @@ import type {
|
|||||||
} from '@staticcms/core/interface';
|
} from '@staticcms/core/interface';
|
||||||
import type { RootState } from '@staticcms/core/store';
|
import type { RootState } from '@staticcms/core/store';
|
||||||
import type { Blocker } from 'history';
|
import type { Blocker } from 'history';
|
||||||
import type { ComponentType } from 'react';
|
import type { ComponentType, FC } from 'react';
|
||||||
import type { ConnectedProps } from 'react-redux';
|
import type { ConnectedProps } from 'react-redux';
|
||||||
|
|
||||||
const Editor = ({
|
const Editor: FC<TranslatedProps<EditorProps>> = ({
|
||||||
entry,
|
entry,
|
||||||
entryDraft,
|
entryDraft,
|
||||||
fields,
|
fields,
|
||||||
@ -50,34 +47,25 @@ const Editor = ({
|
|||||||
hasChanged,
|
hasChanged,
|
||||||
displayUrl,
|
displayUrl,
|
||||||
isModification,
|
isModification,
|
||||||
logoutUser,
|
|
||||||
draftKey,
|
draftKey,
|
||||||
t,
|
|
||||||
editorBackLink,
|
editorBackLink,
|
||||||
toggleScroll,
|
|
||||||
scrollSyncEnabled,
|
scrollSyncEnabled,
|
||||||
loadScroll,
|
|
||||||
showDelete,
|
showDelete,
|
||||||
slug,
|
slug,
|
||||||
localBackup,
|
localBackup,
|
||||||
persistLocalBackup,
|
t,
|
||||||
loadEntry,
|
}) => {
|
||||||
persistEntry,
|
|
||||||
deleteEntry,
|
|
||||||
loadLocalBackup,
|
|
||||||
retrieveLocalBackup,
|
|
||||||
deleteLocalBackup,
|
|
||||||
deleteDraftLocalBackup,
|
|
||||||
createDraftDuplicateFromEntry,
|
|
||||||
createEmptyDraft,
|
|
||||||
discardDraft,
|
|
||||||
}: TranslatedProps<EditorProps>) => {
|
|
||||||
const [version, setVersion] = useState(0);
|
const [version, setVersion] = useState(0);
|
||||||
|
|
||||||
|
const history = createHashHistory();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const createBackup = useMemo(
|
const createBackup = useMemo(
|
||||||
() =>
|
() =>
|
||||||
debounce(function (entry: Entry, collection: Collection) {
|
debounce(function (entry: Entry, collection: Collection) {
|
||||||
persistLocalBackup(entry, collection);
|
dispatch(persistLocalBackup(entry, collection));
|
||||||
}, 2000),
|
}, 2000),
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
[],
|
[],
|
||||||
@ -86,9 +74,9 @@ const Editor = ({
|
|||||||
const deleteBackup = useCallback(() => {
|
const deleteBackup = useCallback(() => {
|
||||||
createBackup.cancel();
|
createBackup.cancel();
|
||||||
if (slug) {
|
if (slug) {
|
||||||
deleteLocalBackup(collection, slug);
|
dispatch(deleteLocalBackup(collection, slug));
|
||||||
}
|
}
|
||||||
deleteDraftLocalBackup();
|
dispatch(deleteDraftLocalBackup());
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [collection, createBackup, slug]);
|
}, [collection, createBackup, slug]);
|
||||||
|
|
||||||
@ -105,29 +93,29 @@ const Editor = ({
|
|||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
await persistEntry(collection);
|
await dispatch(persistEntry(collection, navigate));
|
||||||
setVersion(version + 1);
|
setVersion(version + 1);
|
||||||
|
|
||||||
deleteBackup();
|
deleteBackup();
|
||||||
|
|
||||||
if (createNew) {
|
if (createNew) {
|
||||||
navigateToNewEntry(collection.name);
|
|
||||||
if (duplicate && entryDraft.entry) {
|
if (duplicate && entryDraft.entry) {
|
||||||
createDraftDuplicateFromEntry(entryDraft.entry);
|
dispatch(createDraftDuplicateFromEntry(entryDraft.entry));
|
||||||
|
navigate(`/collections/${collection.name}/new`, { replace: true });
|
||||||
|
} else {
|
||||||
|
setSubmitted(false);
|
||||||
|
setTimeout(() => {
|
||||||
|
dispatch(createEmptyDraft(collection, location.search));
|
||||||
|
setVersion(version + 1);
|
||||||
|
navigate(`/collections/${collection.name}/new`, { replace: true });
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}, 100);
|
}, 100);
|
||||||
},
|
},
|
||||||
[
|
[collection, deleteBackup, dispatch, entryDraft.entry, navigate, version],
|
||||||
collection,
|
|
||||||
createDraftDuplicateFromEntry,
|
|
||||||
deleteBackup,
|
|
||||||
entryDraft.entry,
|
|
||||||
persistEntry,
|
|
||||||
version,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDuplicateEntry = useCallback(() => {
|
const handleDuplicateEntry = useCallback(() => {
|
||||||
@ -135,9 +123,9 @@ const Editor = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateToNewEntry(collection.name);
|
dispatch(createDraftDuplicateFromEntry(entryDraft.entry));
|
||||||
createDraftDuplicateFromEntry(entryDraft.entry);
|
navigate(`/collections/${collection.name}/new?duplicate=true`, { replace: true });
|
||||||
}, [collection.name, createDraftDuplicateFromEntry, entryDraft.entry]);
|
}, [collection.name, dispatch, entryDraft.entry, navigate]);
|
||||||
|
|
||||||
const handleDeleteEntry = useCallback(async () => {
|
const handleDeleteEntry = useCallback(async () => {
|
||||||
if (entryDraft.hasChanged) {
|
if (entryDraft.hasChanged) {
|
||||||
@ -161,15 +149,15 @@ const Editor = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!slug) {
|
if (!slug) {
|
||||||
return navigateToCollection(collection.name);
|
return navigate(`/collections/${collection.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
await deleteEntry(collection, slug);
|
await dispatch(deleteEntry(collection, slug));
|
||||||
deleteBackup();
|
deleteBackup();
|
||||||
return navigateToCollection(collection.name);
|
return navigate(`/collections/${collection.name}`);
|
||||||
}, 0);
|
}, 0);
|
||||||
}, [collection, deleteBackup, deleteEntry, entryDraft.hasChanged, slug]);
|
}, [collection, deleteBackup, dispatch, entryDraft.hasChanged, navigate, slug]);
|
||||||
|
|
||||||
const [prevLocalBackup, setPrevLocalBackup] = useState<
|
const [prevLocalBackup, setPrevLocalBackup] = useState<
|
||||||
| {
|
| {
|
||||||
@ -187,7 +175,7 @@ const Editor = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (confirmLoadBackupBody) {
|
if (confirmLoadBackupBody) {
|
||||||
loadLocalBackup();
|
dispatch(loadLocalBackup());
|
||||||
setVersion(version + 1);
|
setVersion(version + 1);
|
||||||
} else {
|
} else {
|
||||||
deleteBackup();
|
deleteBackup();
|
||||||
@ -198,7 +186,7 @@ const Editor = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setPrevLocalBackup(localBackup);
|
setPrevLocalBackup(localBackup);
|
||||||
}, [deleteBackup, loadLocalBackup, localBackup, prevLocalBackup, version]);
|
}, [deleteBackup, dispatch, localBackup, prevLocalBackup, version]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hasChanged && entryDraft.entry) {
|
if (hasChanged && entryDraft.entry) {
|
||||||
@ -211,32 +199,22 @@ const Editor = ({
|
|||||||
}, [collection, createBackup, entryDraft.entry, hasChanged]);
|
}, [collection, createBackup, entryDraft.entry, hasChanged]);
|
||||||
|
|
||||||
const [prevCollection, setPrevCollection] = useState<Collection | null>(null);
|
const [prevCollection, setPrevCollection] = useState<Collection | null>(null);
|
||||||
const [preSlug, setPrevSlug] = useState<string | undefined | null>(null);
|
const [prevSlug, setPrevSlug] = useState<string | undefined | null>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!slug && preSlug !== slug) {
|
if (!slug && prevSlug !== slug) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
createEmptyDraft(collection, location.search);
|
dispatch(createEmptyDraft(collection, location.search));
|
||||||
});
|
});
|
||||||
} else if (slug && (prevCollection !== collection || preSlug !== slug)) {
|
} else if (slug && (prevCollection !== collection || prevSlug !== slug)) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
retrieveLocalBackup(collection, slug);
|
dispatch(retrieveLocalBackup(collection, slug));
|
||||||
loadEntry(collection, slug);
|
dispatch(loadEntry(collection, slug));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setPrevCollection(collection);
|
setPrevCollection(collection);
|
||||||
setPrevSlug(slug);
|
setPrevSlug(slug);
|
||||||
}, [
|
}, [collection, entryDraft.entry, prevSlug, prevCollection, slug, dispatch]);
|
||||||
collection,
|
|
||||||
createEmptyDraft,
|
|
||||||
discardDraft,
|
|
||||||
entryDraft.entry,
|
|
||||||
loadEntry,
|
|
||||||
preSlug,
|
|
||||||
prevCollection,
|
|
||||||
retrieveLocalBackup,
|
|
||||||
slug,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const leaveMessage = useMemo(() => t('editor.editor.onLeavePage'), [t]);
|
const leaveMessage = useMemo(() => t('editor.editor.onLeavePage'), [t]);
|
||||||
|
|
||||||
@ -284,7 +262,19 @@ const Editor = ({
|
|||||||
return () => {
|
return () => {
|
||||||
unblock();
|
unblock();
|
||||||
};
|
};
|
||||||
}, [collection.name, deleteBackup, discardDraft, navigationBlocker]);
|
}, [collection.name, history, navigationBlocker]);
|
||||||
|
|
||||||
|
const handleLogout = useCallback(() => {
|
||||||
|
dispatch(logoutUser());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const handleToggleScroll = useCallback(async () => {
|
||||||
|
await dispatch(toggleScroll());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const handleLoadScroll = useCallback(async () => {
|
||||||
|
await dispatch(loadScroll());
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
if (entry && entry.error) {
|
if (entry && entry.error) {
|
||||||
return (
|
return (
|
||||||
@ -313,11 +303,11 @@ const Editor = ({
|
|||||||
displayUrl={displayUrl}
|
displayUrl={displayUrl}
|
||||||
isNewEntry={!slug}
|
isNewEntry={!slug}
|
||||||
isModification={isModification}
|
isModification={isModification}
|
||||||
onLogoutClick={logoutUser}
|
onLogoutClick={handleLogout}
|
||||||
editorBackLink={editorBackLink}
|
editorBackLink={editorBackLink}
|
||||||
toggleScroll={toggleScroll}
|
toggleScroll={handleToggleScroll}
|
||||||
scrollSyncEnabled={scrollSyncEnabled}
|
scrollSyncEnabled={scrollSyncEnabled}
|
||||||
loadScroll={loadScroll}
|
loadScroll={handleLoadScroll}
|
||||||
submitted={submitted}
|
submitted={submitted}
|
||||||
t={t}
|
t={t}
|
||||||
/>
|
/>
|
||||||
@ -378,25 +368,7 @@ function mapStateToProps(state: RootState, ownProps: CollectionViewOwnProps) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = {
|
const connector = connect(mapStateToProps);
|
||||||
loadEntry: loadEntryAction,
|
|
||||||
loadEntries: loadEntriesAction,
|
|
||||||
loadLocalBackup: loadLocalBackupAction,
|
|
||||||
deleteDraftLocalBackup: deleteDraftLocalBackupAction,
|
|
||||||
retrieveLocalBackup: retrieveLocalBackupAction,
|
|
||||||
persistLocalBackup: persistLocalBackupAction,
|
|
||||||
deleteLocalBackup: deleteLocalBackupAction,
|
|
||||||
createDraftDuplicateFromEntry: createDraftDuplicateFromEntryAction,
|
|
||||||
createEmptyDraft: createEmptyDraftAction,
|
|
||||||
discardDraft: discardDraftAction,
|
|
||||||
persistEntry: persistEntryAction,
|
|
||||||
deleteEntry: deleteEntryAction,
|
|
||||||
logoutUser: logoutUserAction,
|
|
||||||
toggleScroll: toggleScrollAction,
|
|
||||||
loadScroll: loadScrollAction,
|
|
||||||
};
|
|
||||||
|
|
||||||
const connector = connect(mapStateToProps, mapDispatchToProps);
|
|
||||||
export type EditorProps = ConnectedProps<typeof connector>;
|
export type EditorProps = ConnectedProps<typeof connector>;
|
||||||
|
|
||||||
export default connector(translate()(Editor) as ComponentType<EditorProps>);
|
export default connector(translate()(Editor) as ComponentType<EditorProps>);
|
||||||
|
@ -137,7 +137,7 @@ interface EditorInterfaceProps {
|
|||||||
isModification: boolean;
|
isModification: boolean;
|
||||||
onLogoutClick: () => void;
|
onLogoutClick: () => void;
|
||||||
editorBackLink: string;
|
editorBackLink: string;
|
||||||
toggleScroll: () => Promise<{ readonly type: 'TOGGLE_SCROLL' }>;
|
toggleScroll: () => Promise<void>;
|
||||||
scrollSyncEnabled: boolean;
|
scrollSyncEnabled: boolean;
|
||||||
loadScroll: () => void;
|
loadScroll: () => void;
|
||||||
submitted: boolean;
|
submitted: boolean;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { styled } from '@mui/material/styles';
|
import { styled } from '@mui/material/styles';
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import Frame from 'react-frame-component';
|
import Frame from 'react-frame-component';
|
||||||
import { translate } from 'react-polyglot';
|
import { translate } from 'react-polyglot';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
@ -132,7 +132,7 @@ const PreviewPane = (props: TranslatedProps<EditorPreviewPaneProps>) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReactDOM.createPortal(
|
return createPortal(
|
||||||
<StyledPreviewContent className="preview-content">
|
<StyledPreviewContent className="preview-content">
|
||||||
{!entry || !entry.data ? null : (
|
{!entry || !entry.data ? null : (
|
||||||
<ErrorBoundary config={config}>
|
<ErrorBoundary config={config}>
|
||||||
|
@ -156,9 +156,13 @@ export function selectDefaultSortableFields(collection: Collection, backend: Bac
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function selectSortableFields(
|
export function selectSortableFields(
|
||||||
collection: Collection,
|
collection: Collection | undefined,
|
||||||
t: (key: string) => string,
|
t: (key: string) => string,
|
||||||
): SortableField[] {
|
): SortableField[] {
|
||||||
|
if (!collection) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
const fields = (collection.sortable_fields?.fields ?? [])
|
const fields = (collection.sortable_fields?.fields ?? [])
|
||||||
.map(key => {
|
.map(key => {
|
||||||
if (key === COMMIT_DATE) {
|
if (key === COMMIT_DATE) {
|
||||||
@ -177,12 +181,12 @@ export function selectSortableFields(
|
|||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectViewFilters(collection: Collection) {
|
export function selectViewFilters(collection?: Collection) {
|
||||||
return collection.view_filters;
|
return collection?.view_filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectViewGroups(collection: Collection) {
|
export function selectViewGroups(collection?: Collection) {
|
||||||
return collection.view_groups;
|
return collection?.view_groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectFieldsComments(collection: Collection, entryMap: Entry) {
|
export function selectFieldsComments(collection: Collection, entryMap: Entry) {
|
||||||
|
@ -21,7 +21,7 @@ const de: LocalePhrasesRoot = {
|
|||||||
content: 'Inhalt',
|
content: 'Inhalt',
|
||||||
workflow: 'Arbeitsablauf',
|
workflow: 'Arbeitsablauf',
|
||||||
media: 'Medien',
|
media: 'Medien',
|
||||||
quickAdd: 'Schnell-Erstellung',
|
quickAdd: 'Schnellerstellung',
|
||||||
},
|
},
|
||||||
app: {
|
app: {
|
||||||
errorHeader: 'Fehler beim Laden der CMS-Konfiguration.',
|
errorHeader: 'Fehler beim Laden der CMS-Konfiguration.',
|
||||||
@ -36,8 +36,8 @@ const de: LocalePhrasesRoot = {
|
|||||||
},
|
},
|
||||||
collection: {
|
collection: {
|
||||||
sidebar: {
|
sidebar: {
|
||||||
collections: 'Inhaltstypen',
|
collections: 'Bereiche',
|
||||||
allCollections: 'Allen Inhaltstypen',
|
allCollections: 'Allen Bereichen',
|
||||||
searchAll: 'Alles durchsuchen',
|
searchAll: 'Alles durchsuchen',
|
||||||
searchIn: 'Suchen in',
|
searchIn: 'Suchen in',
|
||||||
},
|
},
|
||||||
@ -231,6 +231,10 @@ const de: LocalePhrasesRoot = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
ui: {
|
ui: {
|
||||||
|
common: {
|
||||||
|
yes: 'Ja',
|
||||||
|
no: 'Nein',
|
||||||
|
},
|
||||||
default: {
|
default: {
|
||||||
goBackToSite: 'Zurück zur Seite',
|
goBackToSite: 'Zurück zur Seite',
|
||||||
},
|
},
|
||||||
|
@ -6,16 +6,28 @@ import type { CollectionViewStyle } from '@staticcms/core/constants/collectionVi
|
|||||||
import type { Entry, Group, GroupMap, Sort } from '@staticcms/core/interface';
|
import type { Entry, Group, GroupMap, Sort } from '@staticcms/core/interface';
|
||||||
import type { RootState } from '@staticcms/core/store';
|
import type { RootState } from '@staticcms/core/store';
|
||||||
|
|
||||||
export function selectEntriesSort(entries: RootState, collection: string) {
|
export function selectEntriesSort(entries: RootState, collection?: string) {
|
||||||
|
if (!collection) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const sort = entries.entries.sort as Sort | undefined;
|
const sort = entries.entries.sort as Sort | undefined;
|
||||||
return sort?.[collection];
|
return sort?.[collection];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectEntriesFilter = (collectionName: string) => (entries: RootState) => {
|
export const selectEntriesFilter = (collectionName?: string) => (entries: RootState) => {
|
||||||
return entries.entries.filter?.[collectionName];
|
if (!collectionName) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return entries.entries.filter?.[collectionName] ?? {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function selectEntriesGroup(entries: RootState, collection: string) {
|
export function selectEntriesGroup(entries: RootState, collection?: string) {
|
||||||
|
if (!collection) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
const group = entries.entries.group as Group | undefined;
|
const group = entries.entries.group as Group | undefined;
|
||||||
return group?.[collection] || {};
|
return group?.[collection] || {};
|
||||||
}
|
}
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
import { createHashHistory } from 'history';
|
|
||||||
|
|
||||||
const history = createHashHistory();
|
|
||||||
|
|
||||||
export function navigateToCollection(collectionName: string) {
|
|
||||||
return history.push(`/collections/${collectionName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function navigateToNewEntry(collectionName: string) {
|
|
||||||
return history.replace(`/collections/${collectionName}/new`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function navigateToEntry(collectionName: string, slug: string) {
|
|
||||||
return history.replace(`/collections/${collectionName}/entries/${slug}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { history };
|
|
@ -38,13 +38,13 @@
|
|||||||
"@next/bundle-analyzer": "13.2.1",
|
"@next/bundle-analyzer": "13.2.1",
|
||||||
"@next/eslint-plugin-next": "13.2.1",
|
"@next/eslint-plugin-next": "13.2.1",
|
||||||
"@types/js-yaml": "4.0.5",
|
"@types/js-yaml": "4.0.5",
|
||||||
"@types/node": "16.18.12",
|
"@types/node": "16.18.13",
|
||||||
"@types/prettier": "2.7.2",
|
"@types/prettier": "2.7.2",
|
||||||
"@types/prismjs": "1.26.0",
|
"@types/prismjs": "1.26.0",
|
||||||
"@types/react": "18.0.28",
|
"@types/react": "18.0.28",
|
||||||
"@types/react-dom": "18.0.11",
|
"@types/react-dom": "18.0.11",
|
||||||
"@typescript-eslint/eslint-plugin": "5.53.0",
|
"@typescript-eslint/eslint-plugin": "5.54.0",
|
||||||
"@typescript-eslint/parser": "5.53.0",
|
"@typescript-eslint/parser": "5.54.0",
|
||||||
"babel-eslint": "10.1.0",
|
"babel-eslint": "10.1.0",
|
||||||
"eslint": "8.35.0",
|
"eslint": "8.35.0",
|
||||||
"eslint-config-next": "13.2.1",
|
"eslint-config-next": "13.2.1",
|
||||||
|
Reference in New Issue
Block a user