) => {
const navigate = useNavigate();
const dispatch = useAppDispatch();
const mode = useAppSelector(selectTheme);
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode,
primary: {
main: 'rgb(37 99 235)',
},
...(mode === 'dark' && {
background: {
paper: 'rgb(15 23 42)',
},
}),
},
}),
[mode],
);
const configError = useCallback(
(error?: string) => {
return (
{t('app.app.errorHeader')}
{t('app.app.configErrors')}:
{error ?? config.error}
{t('app.app.checkConfigYml')}
);
},
[config.error, t],
);
const handleLogin = useCallback(
(credentials: Credentials) => {
loginUser(credentials);
},
[loginUser],
);
const AuthComponent = useMemo(() => {
if (!config.config) {
return null;
}
const backend = currentBackend(config.config);
return backend?.authComponent();
}, [config.config]);
const authenticationPage = useMemo(() => {
if (!config.config) {
return null;
}
if (AuthComponent == null) {
return (
{t('app.app.waitingBackend')}
);
}
return (
navigate('/', { replace: true })}
t={t}
/>
);
}, [AuthComponent, auth.error, auth.isFetching, config.config, handleLogin, navigate, t]);
const defaultPath = useMemo(() => getDefaultPath(collections), [collections]);
const { pathname } = useLocation();
const [searchParams] = useSearchParams();
useEffect(() => {
if (
/\/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;
}
dispatch(discardDraft());
}, [dispatch, pathname, searchParams]);
useEffect(() => {
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (
localStorage.getItem('color-theme') === 'dark' ||
(!('color-theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark');
dispatch(changeTheme('dark'));
} else {
document.documentElement.classList.remove('dark');
dispatch(changeTheme('light'));
}
}, [dispatch]);
const [prevUser, setPrevUser] = useState(user);
useEffect(() => {
if (!prevUser && user) {
invokeEvent({
name: 'login',
data: {
login: user.login,
name: user.name ?? '',
},
});
}
setPrevUser(user);
}, [prevUser, user]);
const content = useMemo(() => {
if (!user) {
return authenticationPage;
}
return (
<>
{isFetching && }
} />
} />
} />
}
/>
} />
} />
}
/>
}
/>
}
/>
}
/>
} />
} />
} />
} />
} />
} />
>
);
}, [authenticationPage, collections, defaultPath, isFetching, user]);
useEffect(() => {
setTimeout(() => {
invokeEvent({ name: 'mounted' });
});
}, []);
if (!config.config) {
return configError(t('app.app.configNotFound'));
}
if (config.error) {
return configError();
}
if (config.isFetching) {
return {t('app.app.loadingConfig')};
}
return (
<>
>
);
};
function mapStateToProps(state: RootState) {
const { auth, config, collections, globalUI, scroll } = state;
const user = auth.user;
const isFetching = globalUI.isFetching;
const scrollSyncEnabled = scroll.isScrolling;
return {
auth,
config,
collections,
user,
isFetching,
scrollSyncEnabled,
};
}
const mapDispatchToProps = {
loginUser: loginUserAction,
};
const connector = connect(mapStateToProps, mapDispatchToProps);
export type AppProps = ConnectedProps;
export default connector(translate()(App) as ComponentType);