feat: add the ability to choose default collection (#3029)
Co-authored-by: Tom Moor <tom@getoutline.com> Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import Collection from "~/models/Collection";
|
||||
import Button from "~/components/Button";
|
||||
import Flex from "~/components/Flex";
|
||||
import HelpText from "~/components/HelpText";
|
||||
import useCurrentTeam from "~/hooks/useCurrentTeam";
|
||||
import useToasts from "~/hooks/useToasts";
|
||||
import { homePath } from "~/utils/routeHelpers";
|
||||
|
||||
@@ -16,6 +17,7 @@ type Props = {
|
||||
|
||||
function CollectionDelete({ collection, onSubmit }: Props) {
|
||||
const [isDeleting, setIsDeleting] = React.useState(false);
|
||||
const team = useCurrentTeam();
|
||||
const { showToast } = useToasts();
|
||||
const history = useHistory();
|
||||
const { t } = useTranslation();
|
||||
@@ -26,8 +28,8 @@ function CollectionDelete({ collection, onSubmit }: Props) {
|
||||
|
||||
try {
|
||||
await collection.delete();
|
||||
history.push(homePath());
|
||||
onSubmit();
|
||||
history.push(homePath());
|
||||
} catch (err) {
|
||||
showToast(err.message, {
|
||||
type: "error",
|
||||
@@ -36,7 +38,7 @@ function CollectionDelete({ collection, onSubmit }: Props) {
|
||||
setIsDeleting(false);
|
||||
}
|
||||
},
|
||||
[showToast, onSubmit, collection, history]
|
||||
[collection, history, onSubmit, showToast]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -53,6 +55,19 @@ function CollectionDelete({ collection, onSubmit }: Props) {
|
||||
}}
|
||||
/>
|
||||
</HelpText>
|
||||
{team.defaultCollectionId === collection.id ? (
|
||||
<HelpText>
|
||||
<Trans
|
||||
defaults="Also, <em>{{collectionName}}</em> is being used as the start view – deleting it will reset the start view to the Home page."
|
||||
values={{
|
||||
collectionName: collection.name,
|
||||
}}
|
||||
components={{
|
||||
em: <strong />,
|
||||
}}
|
||||
/>
|
||||
</HelpText>
|
||||
) : null}
|
||||
<Button type="submit" disabled={isDeleting} autoFocus danger>
|
||||
{isDeleting ? `${t("Deleting")}…` : t("I’m sure – Delete")}
|
||||
</Button>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Trans, useTranslation } from "react-i18next";
|
||||
import { useLocation, Link, Redirect } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { setCookie } from "tiny-cookie";
|
||||
import { Config } from "~/stores/AuthStore";
|
||||
import ButtonLarge from "~/components/ButtonLarge";
|
||||
import Fade from "~/components/Fade";
|
||||
import Flex from "~/components/Flex";
|
||||
@@ -22,8 +23,7 @@ import { changeLanguage, detectLanguage } from "~/utils/language";
|
||||
import Notices from "./Notices";
|
||||
import Provider from "./Provider";
|
||||
|
||||
// @ts-expect-error ts-migrate(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message
|
||||
function Header({ config }) {
|
||||
function Header({ config }: { config: Config }) {
|
||||
const { t } = useTranslation();
|
||||
const isHosted = env.DEPLOYMENT === "hosted";
|
||||
const isSubdomain = !!config.hostname;
|
||||
@@ -84,6 +84,10 @@ function Login() {
|
||||
}
|
||||
}, [query]);
|
||||
|
||||
if (auth.authenticated && auth.team?.defaultCollectionId) {
|
||||
return <Redirect to={`/collection/${auth.team?.defaultCollectionId}`} />;
|
||||
}
|
||||
|
||||
if (auth.authenticated) {
|
||||
return <Redirect to="/home" />;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useRef, useState } from "react";
|
||||
import * as React from "react";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
import Button from "~/components/Button";
|
||||
import DefaultCollectionInputSelect from "~/components/DefaultCollectionInputSelect";
|
||||
import Heading from "~/components/Heading";
|
||||
import HelpText from "~/components/HelpText";
|
||||
import Input from "~/components/Input";
|
||||
@@ -23,6 +24,9 @@ function Details() {
|
||||
const [name, setName] = useState(team.name);
|
||||
const [subdomain, setSubdomain] = useState(team.subdomain);
|
||||
const [avatarUrl, setAvatarUrl] = useState<string>(team.avatarUrl);
|
||||
const [defaultCollectionId, setDefaultCollectionId] = useState<string | null>(
|
||||
team.defaultCollectionId
|
||||
);
|
||||
|
||||
const handleSubmit = React.useCallback(
|
||||
async (event?: React.SyntheticEvent) => {
|
||||
@@ -35,6 +39,7 @@ function Details() {
|
||||
name,
|
||||
avatarUrl,
|
||||
subdomain,
|
||||
defaultCollectionId,
|
||||
});
|
||||
showToast(t("Settings saved"), {
|
||||
type: "success",
|
||||
@@ -45,7 +50,7 @@ function Details() {
|
||||
});
|
||||
}
|
||||
},
|
||||
[auth, showToast, name, avatarUrl, subdomain, t]
|
||||
[auth, name, avatarUrl, subdomain, defaultCollectionId, showToast, t]
|
||||
);
|
||||
|
||||
const handleNameChange = React.useCallback(
|
||||
@@ -79,7 +84,13 @@ function Details() {
|
||||
[showToast, t]
|
||||
);
|
||||
|
||||
const onSelectCollection = React.useCallback(async (value: string) => {
|
||||
const defaultCollectionId = value === "home" ? null : value;
|
||||
setDefaultCollectionId(defaultCollectionId);
|
||||
}, []);
|
||||
|
||||
const isValid = form.current && form.current.checkValidity();
|
||||
|
||||
return (
|
||||
<Scene title={t("Details")} icon={<TeamIcon color="currentColor" />}>
|
||||
<Heading>{t("Details")}</Heading>
|
||||
@@ -128,6 +139,10 @@ function Details() {
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<DefaultCollectionInputSelect
|
||||
onSelectCollection={onSelectCollection}
|
||||
defaultCollectionId={defaultCollectionId}
|
||||
/>
|
||||
<Button type="submit" disabled={auth.isSaving || !isValid}>
|
||||
{auth.isSaving ? `${t("Saving")}…` : t("Save")}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user