Skip to content

Commit

Permalink
feat: Wire up favicon form (#2680)
Browse files Browse the repository at this point in the history
* feat: Allow custom types in ImgInput

* feat: Wire up favicon form

* feat: Update favicon on preview and unpublished if present
  • Loading branch information
DafyddLlyr authored Jan 19, 2024
1 parent 2b700f6 commit f791959
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 23 deletions.
2 changes: 1 addition & 1 deletion editor.planx.uk/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" id="favicon"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,47 @@
import Link from "@mui/material/Link";
import Typography from "@mui/material/Typography";
import { Team, TeamTheme } from "@opensystemslab/planx-core/types";
import { useFormik } from "formik";
import React from "react";
import { useStore } from "pages/FlowEditor/lib/store";
import React, { useEffect, useState } from "react";
import ImgInput from "ui/editor/ImgInput";
import InputDescription from "ui/editor/InputDescription";
import InputRow from "ui/shared/InputRow";
import InputRowItem from "ui/shared/InputRowItem";
import InputRowLabel from "ui/shared/InputRowLabel";
import PublicFileUploadButton from "ui/shared/PublicFileUploadButton";

import { EXAMPLE_COLOUR, SettingsForm } from ".";
import { SettingsForm } from ".";

export const FaviconForm: React.FC = () => {
const formik = useFormik<{
textLinkColor: string;
}>({
initialValues: {
textLinkColor: EXAMPLE_COLOUR,
type FormValues = Pick<TeamTheme, "favicon">;

export const FaviconForm: React.FC<{ team: Team, onSuccess: () => void }> = ({ team, onSuccess }) => {
useEffect(() => {
setInitialValues({ favicon: team.theme?.favicon || "" });
}, [team]);

const [initialValues, setInitialValues] = useState<FormValues>({
favicon: "",
});

const formik = useFormik<FormValues>({
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 (
<SettingsForm
formik={formik}
Expand All @@ -39,8 +60,16 @@ export const FaviconForm: React.FC = () => {
input={
<InputRow>
<InputRowLabel>Favicon:</InputRowLabel>
<InputRowItem width={50}>
<PublicFileUploadButton />
<InputRowItem width={formik.values.favicon ? 90 : 50}>
<ImgInput
img={formik.values.favicon || undefined}
onChange={updateFavicon}
acceptedFileTypes={{
"image/png": [".png"],
"image/x-icon": [".ico"],
"image/vnd.microsoft.icon": [".ico"],
}}
/>
</InputRowItem>
<Typography
color="text.secondary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Snackbar from "@mui/material/Snackbar";
import { styled } from "@mui/material/styles";
import Typography from "@mui/material/Typography";
import { Team } from "@opensystemslab/planx-core/types";
import { FormikProps, getIn } from "formik";
import { FormikProps } from "formik";
import { hasFeatureFlag } from "lib/featureFlags";
import { useStore } from "pages/FlowEditor/lib/store";
import React, { useEffect, useState } from "react";
Expand Down Expand Up @@ -139,7 +139,7 @@ const DesignSettings: React.FC = () => {
<ThemeAndLogoForm team={team} onSuccess={() => setOpen(true)} />
<ButtonForm team={team} onSuccess={() => setOpen(true)} />
<TextLinkForm team={team} onSuccess={() => setOpen(true)} />
<FaviconForm />
<FaviconForm team={team} onSuccess={() => setOpen(true)} />
<Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
<Alert
onClose={handleClose}
Expand Down
10 changes: 8 additions & 2 deletions editor.planx.uk/src/pages/FlowEditor/lib/store/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const teamStore: StateCreator<
notifyPersonalisation: undefined,
boundaryBBox: undefined,

setTeam: (team) =>
setTeam: (team) => {
set({
teamId: team.id,
teamTheme: team.theme,
Expand All @@ -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,
Expand Down
5 changes: 4 additions & 1 deletion editor.planx.uk/src/ui/editor/ImgInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<HTMLButtonElement | null>(null);

Expand Down Expand Up @@ -88,6 +90,7 @@ export default function ImgInput({
onChange && onChange(newUrl);
}}
disabled={!useStore.getState().canUserEditTeam(teamSlug)}
acceptedFileTypes={acceptedFileTypes}
/>
</ImageUploadContainer>
</Tooltip>
Expand Down
15 changes: 11 additions & 4 deletions editor.planx.uk/src/ui/shared/PublicFileUploadButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, ImageFileExtensions[]>;

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 {
Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -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") {
Expand Down

0 comments on commit f791959

Please sign in to comment.