diff --git a/editor.planx.uk/public/index.html b/editor.planx.uk/public/index.html
index 9e84e83265..448f2a6f58 100644
--- a/editor.planx.uk/public/index.html
+++ b/editor.planx.uk/public/index.html
@@ -2,7 +2,7 @@
-
+
{
- const formik = useFormik<{
- textLinkColor: string;
- }>({
- initialValues: {
- textLinkColor: EXAMPLE_COLOUR,
+type FormValues = Pick;
+
+export const FaviconForm: React.FC<{ team: Team, onSuccess: () => void }> = ({ team, onSuccess }) => {
+ useEffect(() => {
+ setInitialValues({ favicon: team.theme?.favicon || "" });
+ }, [team]);
+
+ const [initialValues, setInitialValues] = useState({
+ favicon: "",
+ });
+
+ const formik = useFormik({
+ initialValues,
+ validateOnBlur: false,
+ validateOnChange: false,
+ enableReinitialize: true,
+ onSubmit: async (values, { resetForm }) => {
+ const isSuccess = await useStore.getState().updateTeamTheme(values);
+ if (isSuccess) {
+ onSuccess();
+ // Reset "dirty" status to disable Save & Reset buttons
+ resetForm({ values });
+ }
},
- onSubmit: () => {},
- validate: () => {},
});
+ const updateFavicon = (newFile: string | undefined) => newFile
+ ? formik.setFieldValue("favicon", newFile)
+ : formik.setFieldValue("favicon", null);
+
return (
{
input={
Favicon:
-
-
+
+
{
setOpen(true)} />
setOpen(true)} />
setOpen(true)} />
-
+ setOpen(true)} />
+ setTeam: (team) => {
set({
teamId: team.id,
teamTheme: team.theme,
@@ -50,7 +50,13 @@ export const teamStore: StateCreator<
teamSlug: team.slug,
notifyPersonalisation: team.notifyPersonalisation,
boundaryBBox: team.boundaryBBox,
- }),
+ });
+
+ if (team.theme?.favicon) {
+ const favicon = document.getElementById("favicon") as HTMLLinkElement;
+ favicon.href = team.theme.favicon;
+ }
+ },
getTeam: () => ({
id: get().teamId,
diff --git a/editor.planx.uk/src/ui/editor/ImgInput.tsx b/editor.planx.uk/src/ui/editor/ImgInput.tsx
index a5401d8ead..702121f31c 100644
--- a/editor.planx.uk/src/ui/editor/ImgInput.tsx
+++ b/editor.planx.uk/src/ui/editor/ImgInput.tsx
@@ -8,7 +8,7 @@ import Tooltip from "@mui/material/Tooltip";
import { useStore } from "pages/FlowEditor/lib/store";
import React, { useMemo, useState } from "react";
-import PublicFileUploadButton from "../shared/PublicFileUploadButton";
+import PublicFileUploadButton, { AcceptedFileTypes } from "../shared/PublicFileUploadButton";
const ImageUploadContainer = styled(Box)(() => ({
height: 50,
@@ -29,9 +29,11 @@ const StyledIconButton = styled(IconButton)(({ theme }) => ({
export default function ImgInput({
img,
onChange,
+ acceptedFileTypes,
}: {
img?: string;
onChange?: (newUrl?: string) => void;
+ acceptedFileTypes?: AcceptedFileTypes
}): FCReturn {
const [anchorEl, setAnchorEl] = useState(null);
@@ -88,6 +90,7 @@ export default function ImgInput({
onChange && onChange(newUrl);
}}
disabled={!useStore.getState().canUserEditTeam(teamSlug)}
+ acceptedFileTypes={acceptedFileTypes}
/>
diff --git a/editor.planx.uk/src/ui/shared/PublicFileUploadButton.tsx b/editor.planx.uk/src/ui/shared/PublicFileUploadButton.tsx
index 41cf283d4d..45cce3d4cb 100644
--- a/editor.planx.uk/src/ui/shared/PublicFileUploadButton.tsx
+++ b/editor.planx.uk/src/ui/shared/PublicFileUploadButton.tsx
@@ -8,10 +8,19 @@ import { uploadPublicFile } from "api/upload";
import React, { useCallback, useEffect, useState } from "react";
import { FileWithPath, useDropzone } from "react-dropzone";
+export type AcceptedFileTypes = Record;
+
+export type ImageFileExtensions = ".jpg" | ".jpeg" | ".png" | ".svg" | ".ico";
+
+export const DEFAULT_FILETYPES: AcceptedFileTypes = {
+ "image/*": [".jpg", ".jpeg", ".png", ".svg"],
+};
+
export interface Props {
onChange?: (image: string) => void;
variant?: "tooltip";
disabled?: boolean;
+ acceptedFileTypes?: AcceptedFileTypes;
}
interface RootProps extends ButtonBaseProps {
@@ -41,7 +50,7 @@ const Root = styled(ButtonBase, {
}));
export default function PublicFileUploadButton(props: Props): FCReturn {
- const { onChange, variant, disabled } = props;
+ const { onChange, variant, disabled, acceptedFileTypes } = props;
const [status, setStatus] = useState<
{ type: "none" } | { type: "loading" } | { type: "error"; msg: string }
@@ -86,9 +95,7 @@ export default function PublicFileUploadButton(props: Props): FCReturn {
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
- accept: {
- "image/*": [".jpg", ".jpeg", ".png", ".svg"],
- },
+ accept: acceptedFileTypes || DEFAULT_FILETYPES,
});
if (status.type === "loading") {