fix: survey background image upload issue (#2222)

Co-authored-by: pandeymangg <anshuman.pandey9999@gmail.com>
This commit is contained in:
Dhruwang Jariwala
2024-03-13 14:43:05 +05:30
committed by GitHub
parent 92d88271d7
commit 65a152e518
6 changed files with 71 additions and 56 deletions

View File

@@ -5,7 +5,7 @@ interface AnimatedSurveyBgProps {
background: string;
}
export default function AnimatedSurveyBg({ handleBgChange, background }: AnimatedSurveyBgProps) {
export const AnimatedSurveyBg = ({ handleBgChange, background }: AnimatedSurveyBgProps) => {
const [animation, setAnimation] = useState(background || "/animated-bgs/4K/1_4k.mp4");
const [hoveredVideo, setHoveredVideo] = useState<number | null>(null);
@@ -103,4 +103,4 @@ export default function AnimatedSurveyBg({ handleBgChange, background }: Animate
</div>
</div>
);
}
};

View File

@@ -2,13 +2,13 @@ import { useState } from "react";
import { ColorPicker } from "@formbricks/ui/ColorPicker";
interface ColorSurveyBgBgProps {
interface ColorSurveyBgProps {
handleBgChange: (bg: string, bgType: string) => void;
colours: string[];
background: string;
}
export default function ColorSurveyBg({ handleBgChange, colours, background }: ColorSurveyBgBgProps) {
export const ColorSurveyBg = ({ handleBgChange, colours, background }: ColorSurveyBgProps) => {
const [color, setColor] = useState(background || "#ffff");
const handleBg = (x: string) => {
@@ -35,4 +35,4 @@ export default function ColorSurveyBg({ handleBgChange, colours, background }: C
</div>
</div>
);
}
};

View File

@@ -1,23 +1,12 @@
import FileInput from "@formbricks/ui/FileInput";
interface ImageSurveyBgBgProps {
interface ImageSurveyBgProps {
environmentId: string;
handleBgChange: (url: string, bgType: string) => void;
background: string;
}
export default function ImageSurveyBg({ environmentId, handleBgChange, background }: ImageSurveyBgBgProps) {
const isUrl = (str: string) => {
try {
new URL(str);
return true;
} catch (error) {
return false;
}
};
const fileUrl = isUrl(background ?? "") ? background ?? "" : "";
export const ImageSurveyBg = ({ environmentId, handleBgChange, background }: ImageSurveyBgProps) => {
return (
<div className="mt-2 w-full">
<div className="flex w-full items-center justify-center">
@@ -32,9 +21,10 @@ export default function ImageSurveyBg({ environmentId, handleBgChange, backgroun
handleBgChange("", "image");
}
}}
fileUrl={fileUrl}
fileUrl={background}
maxSizeInMB={2}
/>
</div>
</div>
);
}
};

View File

@@ -2,9 +2,9 @@ import { useEffect, useState } from "react";
import { TSurvey } from "@formbricks/types/surveys";
import AnimatedSurveyBg from "./AnimatedSurveyBg";
import ColorSurveyBg from "./ColorSurveyBg";
import ImageSurveyBg from "./ImageSurveyBg";
import { AnimatedSurveyBg } from "./AnimatedSurveyBg";
import { ColorSurveyBg } from "./ColorSurveyBg";
import { ImageSurveyBg } from "./ImageSurveyBg";
interface SurveyBgSelectorTabProps {
localSurvey: TSurvey;

View File

@@ -9,7 +9,7 @@ import toast from "react-hot-toast";
import { cn } from "@formbricks/lib/cn";
import { TAllowedFileExtension } from "@formbricks/types/common";
import { uploadFile } from "./lib/fileUpload";
import { getAllowedFiles, uploadFile } from "./lib/fileUpload";
const allowedFileTypesForPreview = ["png", "jpeg", "jpg", "webp"];
const isImage = (name: string) => {
@@ -23,6 +23,7 @@ interface FileInputProps {
fileUrl?: string | string[];
multiple?: boolean;
imageFit?: "cover" | "contain";
maxSizeInMB?: number;
}
interface SelectedFile {
@@ -39,6 +40,7 @@ const FileInput: React.FC<FileInputProps> = ({
fileUrl,
multiple = false,
imageFit = "cover",
maxSizeInMB,
}) => {
const [selectedFiles, setSelectedFiles] = useState<SelectedFile[]>([]);
@@ -48,19 +50,9 @@ const FileInput: React.FC<FileInputProps> = ({
toast.error("Only one file is allowed");
}
const allowedFiles = files.filter(
(file) =>
file &&
file.type &&
allowedFileExtensions.includes(file.name.split(".").pop() as TAllowedFileExtension)
);
if (allowedFiles.length < files.length) {
if (allowedFiles.length === 0) {
toast.error("No files are supported");
return;
}
toast.error("Some files are not supported");
const allowedFiles = getAllowedFiles(files, allowedFileExtensions, maxSizeInMB);
if (allowedFiles.length === 0) {
return;
}
setSelectedFiles(
@@ -85,7 +77,7 @@ const FileInput: React.FC<FileInputProps> = ({
const uploadedUrls: string[] = [];
uploadedFiles.forEach((file) => {
if (file.status === "fulfilled") {
uploadedUrls.push(file.value.url);
uploadedUrls.push(encodeURI(file.value.url));
}
});
@@ -125,21 +117,9 @@ const FileInput: React.FC<FileInputProps> = ({
};
const handleUploadMore = async (files: File[]) => {
let filesToUpload: File[] = files;
const allowedFiles = filesToUpload.filter(
(file) =>
file &&
file.type &&
allowedFileExtensions.includes(file.name.split(".").pop() as TAllowedFileExtension)
);
if (allowedFiles.length < filesToUpload.length) {
if (allowedFiles.length === 0) {
toast.error("No files are supported");
return;
}
toast.error("Some files are not supported");
const allowedFiles = getAllowedFiles(files, allowedFileExtensions, maxSizeInMB);
if (allowedFiles.length === 0) {
return;
}
setSelectedFiles((prevFiles) => [
@@ -165,7 +145,7 @@ const FileInput: React.FC<FileInputProps> = ({
const uploadedUrls: string[] = [];
uploadedFiles.forEach((file) => {
if (file.status === "fulfilled") {
uploadedUrls.push(file.value.url);
uploadedUrls.push(encodeURI(file.value.url));
}
});
@@ -199,6 +179,7 @@ const FileInput: React.FC<FileInputProps> = ({
src={file.url}
alt={file.name}
fill
sizes="100%"
style={{ objectFit: "cover" }}
quality={100}
className={!file.uploaded ? "opacity-50" : ""}
@@ -253,6 +234,7 @@ const FileInput: React.FC<FileInputProps> = ({
src={selectedFiles[0].url}
alt={selectedFiles[0].name}
fill
sizes="100%"
style={{ objectFit: imageFit }}
quality={100}
className={!selectedFiles[0].uploaded ? "opacity-50" : ""}

View File

@@ -1,6 +1,10 @@
"use client";
const uploadFile = async (
import { toast } from "react-hot-toast";
import { TAllowedFileExtension } from "@formbricks/types/common";
export const uploadFile = async (
file: File | Blob,
allowedFileExtensions: string[] | undefined,
environmentId: string | undefined
@@ -93,4 +97,43 @@ const uploadFile = async (
}
};
export { uploadFile };
export const getAllowedFiles = (
files: File[],
allowedFileExtensions: string[],
maxSizeInMB?: number
): File[] => {
const sizeExceedFiles: string[] = [];
const unsupportedExtensionFiles: string[] = [];
const allowedFiles = files.filter((file) => {
if (!file || !file.type) {
return false;
}
const extension = file.name.split(".").pop();
const fileSizeInMB = file.size / 1000000; // Kb -> Mb
if (!allowedFileExtensions.includes(extension as TAllowedFileExtension)) {
unsupportedExtensionFiles.push(file.name);
return false; // Exclude file if extension not allowed
} else if (maxSizeInMB && fileSizeInMB > maxSizeInMB) {
sizeExceedFiles.push(file.name);
return false; // Exclude files larger than the maximum size
}
return true;
});
// Constructing toast messages based on the issues found
let toastMessage = "";
if (sizeExceedFiles.length > 0) {
toastMessage += `Files exceeding size limit (${maxSizeInMB} MB): ${sizeExceedFiles.join(", ")}. `;
}
if (unsupportedExtensionFiles.length > 0) {
toastMessage += `Unsupported file types: ${unsupportedExtensionFiles.join(", ")}.`;
}
if (toastMessage) {
toast.error(toastMessage);
}
return allowedFiles;
};