Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Advanced Custom Styling #2182

Merged
merged 139 commits into from
Mar 22, 2024
Merged

feat: Advanced Custom Styling #2182

merged 139 commits into from
Mar 22, 2024

Conversation

pandeymangg
Copy link
Contributor

What does this PR do?

Fixes # (issue)

How should this be tested?

  • Test A
  • Test B

Checklist

Required

  • Filled out the "How to test" section in this PR
  • Read How we Code at Formbricks
  • Self-reviewed my own code
  • Commented on my code in hard-to-understand bits
  • Ran pnpm build
  • Checked for warnings, there are none
  • Removed all console.logs
  • Merged the latest changes from main onto my branch with git pull origin main
  • My changes don't cause any responsiveness issues

Appreciated

  • If a UI change was made: Added a screen recording or screenshots to this PR
  • Updated the Formbricks Docs if changes were necessary

Copy link

vercel bot commented Mar 4, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

2 Ignored Deployments
Name Status Preview Comments Updated (UTC)
formbricks-cloud ⬜️ Ignored (Inspect) Visit Preview Mar 22, 2024 9:34am
formbricks-com ⬜️ Ignored (Inspect) Visit Preview Mar 22, 2024 9:34am

Copy link
Contributor

github-actions bot commented Mar 4, 2024

Thank you for following the naming conventions for pull request titles! 🙏

Copy link
Contributor

apps/web/app/(app)/environments/[environmentId]/surveys/components/Modal.tsx

Consider using the useMemo hook to memoize the scalingClasses and highlightBorderColorStyle values. This will prevent unnecessary re-renders and improve the performance of your component.
Create Issue
See the diff
Checkout the fix

    const scalingClasses = useMemo(() => calculateScaling(), [windowWidth, previewMode]);
    const highlightBorderColorStyle = useMemo(() => {
      if (!highlightBorderColor)
        return {
          overflow: "auto",
        };

      return {
        border: `2px solid ${highlightBorderColor}`,
        overflow: "auto",
      };
    }, [highlightBorderColor]);
git fetch origin && git checkout -b ReviewBot/Impro-q6ibwd8 origin/ReviewBot/Impro-q6ibwd8

Consider using a switch statement instead of multiple if-else statements for placementClass. This will make your code more readable and easier to maintain.
Create Issue
See the diff
Checkout the fix

    let placementClass = "";
    switch (placement) {
      case "bottomLeft":
        placementClass = "bottom left";
        break;
      case "bottomRight":
        placementClass = "bottom right";
        break;
      case "topLeft":
        placementClass = "top left";
        break;
      case "topRight":
        placementClass = "top right";
        break;
    }
git fetch origin && git checkout -b ReviewBot/Impro-7osgrm2 origin/ReviewBot/Impro-7osgrm2

packages/surveys/src/components/questions/OpenTextQuestion.tsx

Consider using the useCallback hook for the handleInputChange and handleInputResize functions. This will prevent unnecessary re-renders and improve the performance of your component.
Create Issue
See the diff
Checkout the fix

    const handleInputChange = useCallback((inputValue: string) => {
      onChange({ [question.id]: inputValue });
    }, [onChange, question.id]);

    const handleInputResize = useCallback((event: { target: any }) => {
      let maxHeight = 160; // 8 lines
      const textarea = event.target;
      textarea.style.height = "auto";
      const newHeight = Math.min(textarea.scrollHeight, maxHeight);
      textarea.style.height = `${newHeight}px`;
      textarea.style.overflow = newHeight >= maxHeight ? "auto" : "hidden";
    }, []);
git fetch origin && git checkout -b ReviewBot/Impro-0ko0pso origin/ReviewBot/Impro-0ko0pso

apps/web/app/(app)/environments/[environmentId]/settings/lookandfeel/components/UnifiedStyling.tsx

Consider breaking down the large UnifiedStyling component into smaller, more manageable components. This will make the code easier to read and maintain.
Create Issue
See the diff
Checkout the fix

    // Example of breaking down the component
    const UnifiedStyling = ({ product }: UnifiedStylingProps) => {
      // ...
      return (
        <div className="flex">
          <StylingSettings {...props} />
          <SurveyPreview {...props} />
        </div>
      );
    };
git fetch origin && git checkout -b ReviewBot/The-c-fxk0mwk origin/ReviewBot/The-c-fxk0mwk

Consider using the useCallback hook for the onSave function. This will prevent unnecessary re-renders and improve performance.
Create Issue
See the diff
Checkout the fix

    // Example of using useCallback
    const onSave = useCallback(async () => {
      // ...
    }, [dependencies]);
git fetch origin && git checkout -b ReviewBot/The-c-yhthwhv origin/ReviewBot/The-c-yhthwhv

Consider abstracting the color defaults into a separate constant or configuration file. This will make the code cleaner and easier to manage.
Create Issue
See the diff
Checkout the fix

    // Example of abstracting color defaults
    const COLOR_DEFAULTS = {
      brandColor: "#64748b",
      questionColor: "#2b2524",
      inputColor: "#efefef",
      inputBorderColor: "#c0c0c0",
      cardBackgroundColor: "#c0c0c0",
      highlighBorderColor: "#64748b",
    };
git fetch origin && git checkout -b ReviewBot/The-c-x70xvuv origin/ReviewBot/The-c-x70xvuv

packages/database/migrations/20240229062232_adds_styling_column_to_product_model/data-migration.ts

Instead of updating the product one by one in the loop, you can collect all the updates and perform them in a single transaction. This will significantly improve the performance of your script.
Create Issue
See the diff
Checkout the fix

    const updates = products.map(product => {
      const styling: TStyling = {
        unifiedStyling: true,
        allowStyleOverwrite: true,
        brandColor: {
          light: product.brandColor,
        },
        ...(product.highlightBorderColor && {
          highlightBorderColor: {
            light: product.highlightBorderColor,
            dark: product.highlightBorderColor,
          },
        }),
      };

      return tx.product.update({
        where: {
          id: product.id,
        },
        data: {
          styling,
        },
      });
    });

    await tx.$transaction(updates);
git fetch origin && git checkout -b ReviewBot/Impro-1v1j0hy origin/ReviewBot/Impro-1v1j0hy

It's a good practice to throw an error when the expected data is not found. This will help you to identify issues in your data or script early.
Create Issue
See the diff
Checkout the fix

    if (!products) {
      throw new Error('No products found');
    }
git fetch origin && git checkout -b ReviewBot/Impro-pxee1oh origin/ReviewBot/Impro-pxee1oh

packages/database/migrations/20240229062232_adds_styling_column_to_product_model/migration.sql

Consider adding an index to the new JSONB column to improve query performance. If you're going to query by any of the keys in the JSONB column, you should create a GIN index on it. However, keep in mind that while GIN indexes improve read performance, they can slow down write operations. Therefore, it's a trade-off that you need to consider based on your application's needs.
Create Issue
See the diff
Checkout the fix

    CREATE INDEX idx_product_styling ON "Product" USING gin ("styling");
git fetch origin && git checkout -b ReviewBot/Addin-0skghwj origin/ReviewBot/Addin-0skghwj

Consider removing the default value from the JSONB column and handle it at the application level. This way, you can avoid data redundancy and ensure consistency across your application.
Create Issue
See the diff
Checkout the fix

    ALTER TABLE "Product" ADD COLUMN "styling" JSONB;
git fetch origin && git checkout -b ReviewBot/Stori-t6elaos origin/ReviewBot/Stori-t6elaos

packages/surveys/tailwind.config.js

Consider using more descriptive names for your custom variables. This will make the code easier to read and maintain. For example, instead of "custom", you could use "fbBorderRadius". This makes it clear that this variable is a custom border radius for Facebook elements.
Create Issue
See the diff
Checkout the fix

    borderRadius: {
      fbBorderRadius: "var(--fb-border-radius)",
    },
git fetch origin && git checkout -b ReviewBot/Impro-7iiptr2 origin/ReviewBot/Impro-7iiptr2

Comment on lines 125 to 404
color={cardBackgroundColor}
setColor={setCardBackgroundColor}
description="Change the text color of the survey questions."
/>

<div className="flex flex-col gap-4">
<div className="flex items-center gap-6">
<Switch
checked={allowHighlightBorder}
onCheckedChange={(value) => {
setAllowHighlightBorder(value);
}}
disabled={!unifiedStyling}
/>
<div className="flex flex-col">
<h3 className="text-base font-semibold">Add highlight border</h3>
<p className="text-sm text-slate-800">Add on outer border to your survey card</p>
</div>
</div>

{allowHighlightBorder && (
<ColorPicker
color={highlightBorderColor}
onChange={setHighlightBorderColor}
containerClass="my-0"
/>
)}
</div>

<DarkModeColors
isDarkMode={isDarkMode}
setIsDarkMode={setIsDarkMode}
brandColor={brandColorDark}
cardBackgroundColor={cardBackgroundColorDark}
highlightBorderColor={highlightBorderColorDark}
inputBorderColor={inputBorderColorDark}
inputColor={inputColorDark}
questionColor={questionColorDark}
setBrandColor={setBrandColorDark}
setCardBackgroundColor={setCardBackgroundColorDark}
setHighlighBorderColor={setHighlightBorderColorDark}
setInputBorderColor={setInputBorderColorDark}
setInputColor={setInputColorDark}
setQuestionColor={setQuestionColorDark}
/>

<div className="flex flex-col gap-4">
<div className="flex flex-col">
<h3 className="text-base font-semibold text-slate-900">Roundness</h3>
<p className="text-sm text-slate-800">Change the border radius of the card and the inputs.</p>
</div>

<Slider
value={[roundness]}
max={16}
onValueChange={(value) => setRoundness(value[0])}
disabled={!unifiedStyling}
/>
</div>

<CardArrangement
activeCardArrangement={linkSurveysCardArrangement}
surveyType="link"
setActiveCardArrangement={setLinkSurveysCardArrangement}
/>

<CardArrangement
activeCardArrangement={inAppSurveysCardArrangement}
surveyType="web"
setActiveCardArrangement={setInAppSurveysCardArrangement}
/>
</div>

<div className="mt-8 flex items-center justify-end gap-2">
<Button variant="minimal" className="flex items-center gap-2">
Reset
<RotateCcwIcon className="h-4 w-4" />
</Button>

<Button variant="darkCTA" onClick={onSave}>
Save changes
</Button>
</div>
</div>

{/* Survey Preview */}

<div className="w-1/2 bg-slate-100 pt-4">
<div className="h-full max-h-[800px]">
<UnifiedStylingPreviewSurvey
activeQuestionId={activeQuestionId}
setActiveQuestionId={setActiveQuestionId}
survey={previewSurvey as TSurvey}
product={product}
/>
</div>
</div>
</div>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking down the large UnifiedStyling component into smaller, more manageable components. This will make the code easier to read and maintain.

Suggested change
const UnifiedStyling = ({ product }: UnifiedStylingProps) => {
const router = useRouter();
const [unifiedStyling, setUnifiedStyling] = useState(product.styling?.unifiedStyling ?? false);
const [allowStyleOverwrite, setAllowStyleOverwrite] = useState(
product.styling?.allowStyleOverwrite ?? false
);
const [brandColor, setBrandColor] = useState(
product.styling?.brandColor?.light ?? colorDefaults.brandColor
);
const [questionColor, setQuestionColor] = useState(
product.styling?.questionColor?.light ?? colorDefaults.questionColor
);
const [inputColor, setInputColor] = useState(
product.styling?.inputColor?.light ?? colorDefaults.inputColor
);
const [inputBorderColor, setInputBorderColor] = useState(
product.styling?.inputBorderColor?.light ?? colorDefaults.inputBorderColor
);
const [cardBackgroundColor, setCardBackgroundColor] = useState(
product.styling?.cardBackgroundColor?.light ?? colorDefaults.cardBackgroundColor
);
// highlight border
const [allowHighlightBorder, setAllowHighlightBorder] = useState(
!!product.styling?.highlightBorderColor?.light ?? false
);
const [highlightBorderColor, setHighlightBorderColor] = useState(
product.styling?.highlightBorderColor?.light ?? colorDefaults.highlighBorderColor
);
const [isDarkMode, setIsDarkMode] = useState(product.styling?.isDarkModeEnabled ?? false);
const [brandColorDark, setBrandColorDark] = useState(product.styling?.brandColor?.dark);
const [questionColorDark, setQuestionColorDark] = useState(product.styling?.questionColor?.dark);
const [inputColorDark, setInputColorDark] = useState(product.styling?.inputColor?.dark);
const [inputBorderColorDark, setInputBorderColorDark] = useState(product.styling?.inputBorderColor?.dark);
const [cardBackgroundColorDark, setCardBackgroundColorDark] = useState(
product.styling?.cardBackgroundColor?.dark
);
const [highlightBorderColorDark, setHighlightBorderColorDark] = useState(
product.styling?.highlightBorderColor?.dark
);
const [roundness, setRoundness] = useState(product.styling?.roundness ?? 8);
const [linkSurveysCardArrangement, setLinkSurveysCardArrangement] = useState(
product.styling?.cardArrangement?.linkSurveys ?? "casual"
);
const [inAppSurveysCardArrangement, setInAppSurveysCardArrangement] = useState(
product.styling?.cardArrangement?.inAppSurveys ?? "casual"
);
const [activeQuestionId, setActiveQuestionId] = useState<string | null>(null);
useEffect(() => {
setActiveQuestionId(previewSurvey.questions[0].id);
}, []);
useEffect(() => {
if (!unifiedStyling) {
setAllowStyleOverwrite(false);
}
}, [unifiedStyling]);
const onSave = async () => {
await updateProductAction(product.id, {
styling: {
unifiedStyling,
allowStyleOverwrite,
brandColor: {
light: brandColor,
dark: brandColorDark,
},
questionColor: {
light: questionColor,
dark: questionColorDark,
},
inputColor: {
light: inputColor,
dark: inputColorDark,
},
inputBorderColor: {
light: inputBorderColor,
dark: inputBorderColorDark,
},
cardBackgroundColor: {
light: cardBackgroundColor,
dark: cardBackgroundColorDark,
},
highlightBorderColor: allowHighlightBorder
? {
light: highlightBorderColor,
dark: highlightBorderColorDark,
}
: undefined,
isDarkModeEnabled: isDarkMode,
roundness,
cardArrangement: {
linkSurveys: linkSurveysCardArrangement,
inAppSurveys: inAppSurveysCardArrangement,
},
},
});
toast.success("Styling updated successfully.");
router.refresh();
};
return (
<div className="flex">
{/* Styling settings */}
<div className="w-1/2 pr-6">
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-4 rounded-lg bg-slate-50 p-4">
<div className="flex items-center gap-6">
<Switch
checked={unifiedStyling}
onCheckedChange={(value) => {
setUnifiedStyling(value);
}}
/>
<div className="flex flex-col">
<h3 className="text-base font-semibold">Enable unified styling</h3>
<p className="text-sm text-slate-800">Set base styles for all surveys below</p>
</div>
</div>
<div className="flex items-center gap-6">
<Switch
checked={allowStyleOverwrite}
onCheckedChange={(value) => {
setAllowStyleOverwrite(value);
}}
disabled={!unifiedStyling}
/>
<div className="flex flex-col">
<h3 className="text-base font-semibold">Allow overwriting styles</h3>
<p className="text-sm text-slate-800">
Activate if you want some surveys to be styled differently
</p>
</div>
</div>
</div>
<ColorSelectorWithLabel
label="Brand color"
color={brandColor}
setColor={setBrandColor}
description="Change the text color of the survey questions."
disabled
/>
<ColorSelectorWithLabel
label="Question color"
color={questionColor}
setColor={setQuestionColor}
description="Change the text color of the survey questions."
/>
<ColorSelectorWithLabel
label="Input color"
color={inputColor}
setColor={setInputColor}
description="Change the text color of the survey questions."
/>
<ColorSelectorWithLabel
label="Input border color"
color={inputBorderColor}
setColor={setInputBorderColor}
description="Change the text color of the survey questions."
/>
<ColorSelectorWithLabel
label="Card background color"
color={cardBackgroundColor}
setColor={setCardBackgroundColor}
description="Change the text color of the survey questions."
/>
<div className="flex flex-col gap-4">
<div className="flex items-center gap-6">
<Switch
checked={allowHighlightBorder}
onCheckedChange={(value) => {
setAllowHighlightBorder(value);
}}
disabled={!unifiedStyling}
/>
<div className="flex flex-col">
<h3 className="text-base font-semibold">Add highlight border</h3>
<p className="text-sm text-slate-800">Add on outer border to your survey card</p>
</div>
</div>
{allowHighlightBorder && (
<ColorPicker
color={highlightBorderColor}
onChange={setHighlightBorderColor}
containerClass="my-0"
/>
)}
</div>
<DarkModeColors
isDarkMode={isDarkMode}
setIsDarkMode={setIsDarkMode}
brandColor={brandColorDark}
cardBackgroundColor={cardBackgroundColorDark}
highlightBorderColor={highlightBorderColorDark}
inputBorderColor={inputBorderColorDark}
inputColor={inputColorDark}
questionColor={questionColorDark}
setBrandColor={setBrandColorDark}
setCardBackgroundColor={setCardBackgroundColorDark}
setHighlighBorderColor={setHighlightBorderColorDark}
setInputBorderColor={setInputBorderColorDark}
setInputColor={setInputColorDark}
setQuestionColor={setQuestionColorDark}
/>
<div className="flex flex-col gap-4">
<div className="flex flex-col">
<h3 className="text-base font-semibold text-slate-900">Roundness</h3>
<p className="text-sm text-slate-800">Change the border radius of the card and the inputs.</p>
</div>
<Slider
value={[roundness]}
max={16}
onValueChange={(value) => setRoundness(value[0])}
disabled={!unifiedStyling}
/>
</div>
<CardArrangement
activeCardArrangement={linkSurveysCardArrangement}
surveyType="link"
setActiveCardArrangement={setLinkSurveysCardArrangement}
/>
<CardArrangement
activeCardArrangement={inAppSurveysCardArrangement}
surveyType="web"
setActiveCardArrangement={setInAppSurveysCardArrangement}
/>
</div>
<div className="mt-8 flex items-center justify-end gap-2">
<Button variant="minimal" className="flex items-center gap-2">
Reset
<RotateCcwIcon className="h-4 w-4" />
</Button>
<Button variant="darkCTA" onClick={onSave}>
Save changes
</Button>
</div>
</div>
{/* Survey Preview */}
<div className="w-1/2 bg-slate-100 pt-4">
<div className="h-full max-h-[800px]">
<UnifiedStylingPreviewSurvey
activeQuestionId={activeQuestionId}
setActiveQuestionId={setActiveQuestionId}
survey={previewSurvey as TSurvey}
product={product}
/>
</div>
</div>
</div>
);
};
const StylingSettings = ({...props}) => {
// ... styling settings code ...
};
const SurveyPreview = ({...props}) => {
// ... survey preview code ...
};
const UnifiedStyling = ({ product }: UnifiedStylingProps) => {
// ...
return (
<div className="flex">
<StylingSettings {...props} />
<SurveyPreview {...props} />
</div>
);
};

Comment on lines 194 to 236
const onSave = async () => {
await updateProductAction(product.id, {
styling: {
unifiedStyling,
allowStyleOverwrite,
brandColor: {
light: brandColor,
dark: brandColorDark,
},
questionColor: {
light: questionColor,
dark: questionColorDark,
},
inputColor: {
light: inputColor,
dark: inputColorDark,
},
inputBorderColor: {
light: inputBorderColor,
dark: inputBorderColorDark,
},
cardBackgroundColor: {
light: cardBackgroundColor,
dark: cardBackgroundColorDark,
},
highlightBorderColor: allowHighlightBorder
? {
light: highlightBorderColor,
dark: highlightBorderColorDark,
}
: undefined,
isDarkModeEnabled: isDarkMode,
roundness,
cardArrangement: {
linkSurveys: linkSurveysCardArrangement,
inAppSurveys: inAppSurveysCardArrangement,
},
},
});

toast.success("Styling updated successfully.");
router.refresh();
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the useCallback hook for the onSave function to prevent unnecessary re-renders and improve performance.

Suggested change
const onSave = async () => {
await updateProductAction(product.id, {
styling: {
unifiedStyling,
allowStyleOverwrite,
brandColor: {
light: brandColor,
dark: brandColorDark,
},
questionColor: {
light: questionColor,
dark: questionColorDark,
},
inputColor: {
light: inputColor,
dark: inputColorDark,
},
inputBorderColor: {
light: inputBorderColor,
dark: inputBorderColorDark,
},
cardBackgroundColor: {
light: cardBackgroundColor,
dark: cardBackgroundColorDark,
},
highlightBorderColor: allowHighlightBorder
? {
light: highlightBorderColor,
dark: highlightBorderColorDark,
}
: undefined,
isDarkModeEnabled: isDarkMode,
roundness,
cardArrangement: {
linkSurveys: linkSurveysCardArrangement,
inAppSurveys: inAppSurveysCardArrangement,
},
},
});
toast.success("Styling updated successfully.");
router.refresh();
};
const onSave = useCallback(async () => {
await updateProductAction(product.id, {
styling: {
unifiedStyling,
allowStyleOverwrite,
brandColor: {
light: brandColor,
dark: brandColorDark,
},
questionColor: {
light: questionColor,
dark: questionColorDark,
},
inputColor: {
light: inputColor,
dark: inputColorDark,
},
inputBorderColor: {
light: inputBorderColor,
dark: inputBorderColorDark,
},
cardBackgroundColor: {
light: cardBackgroundColor,
dark: cardBackgroundColorDark,
},
highlightBorderColor: allowHighlightBorder
? {
light: highlightBorderColor,
dark: highlightBorderColorDark,
}
: undefined,
isDarkModeEnabled: isDarkMode,
roundness,
cardArrangement: {
linkSurveys: linkSurveysCardArrangement,
inAppSurveys: inAppSurveysCardArrangement,
},
},
});
toast.success("Styling updated successfully.");
router.refresh();
}, [unifiedStyling, allowStyleOverwrite, brandColor, brandColorDark, questionColor, questionColorDark, inputColor, inputColorDark, inputBorderColor, inputBorderColorDark, cardBackgroundColor, cardBackgroundColorDark, allowHighlightBorder, highlightBorderColor, highlightBorderColorDark, isDarkMode, roundness, linkSurveysCardArrangement, inAppSurveysCardArrangement]);

Comment on lines 25 to 32
const colorDefaults = {
brandColor: "#64748b",
questionColor: "#2b2524",
inputColor: "#efefef",
inputBorderColor: "#c0c0c0",
cardBackgroundColor: "#c0c0c0",
highlighBorderColor: "#64748b",
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Abstract the color defaults into a separate constant for cleaner and more manageable code.

Suggested change
const colorDefaults = {
brandColor: "#64748b",
questionColor: "#2b2524",
inputColor: "#efefef",
inputBorderColor: "#c0c0c0",
cardBackgroundColor: "#c0c0c0",
highlighBorderColor: "#64748b",
};
const COLOR_DEFAULTS = {
brandColor: "#64748b",
questionColor: "#2b2524",
inputColor: "#efefef",
inputBorderColor: "#c0c0c0",
cardBackgroundColor: "#c0c0c0",
highlighBorderColor: "#64748b",
};

Comment on lines 18 to 48
if (products.length) {
for (const product of products) {
if (product.styling !== null) {
// styling object already exists for this product
continue;
}

const styling: TStyling = {
unifiedStyling: true,
allowStyleOverwrite: true,
brandColor: {
light: product.brandColor,
},
...(product.highlightBorderColor && {
highlightBorderColor: {
light: product.highlightBorderColor,
dark: product.highlightBorderColor,
},
}),
};

await tx.product.update({
where: {
id: product.id,
},
data: {
styling,
},
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code is updated to collect all the updates and perform them in a single transaction, improving the performance of the data migration script.

Suggested change
if (products.length) {
for (const product of products) {
if (product.styling !== null) {
// styling object already exists for this product
continue;
}
const styling: TStyling = {
unifiedStyling: true,
allowStyleOverwrite: true,
brandColor: {
light: product.brandColor,
},
...(product.highlightBorderColor && {
highlightBorderColor: {
light: product.highlightBorderColor,
dark: product.highlightBorderColor,
},
}),
};
await tx.product.update({
where: {
id: product.id,
},
data: {
styling,
},
});
}
}
const updates = products.map(product => {
if (product.styling !== null) {
// styling object already exists for this product
return;
}
const styling: TStyling = {
unifiedStyling: true,
allowStyleOverwrite: true,
brandColor: {
light: product.brandColor,
},
...(product.highlightBorderColor && {
highlightBorderColor: {
light: product.highlightBorderColor,
dark: product.highlightBorderColor,
},
}),
};
return tx.product.update({
where: {
id: product.id,
},
data: {
styling,
},
});
});
await tx.$transaction(updates);

Comment on lines 13 to 16
if (!products) {
// something went wrong, could not find any products
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throwing an error when no products are found will help identify issues in the data or script early.

Suggested change
if (!products) {
// something went wrong, could not find any products
return;
}
if (!products || products.length === 0) {
throw new Error('No products found');
}

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Product" ADD COLUMN "styling" JSONB DEFAULT '{"unifiedStyling":true,"allowStyleOverwrite":true,"brandColor":{"light":"#64748b"}}';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the default value from the JSONB column to avoid data redundancy and ensure consistency across the application.

Suggested change
ALTER TABLE "Product" ADD COLUMN "styling" JSONB DEFAULT '{"unifiedStyling":true,"allowStyleOverwrite":true,"brandColor":{"light":"#64748b"}}';
ALTER TABLE "Product" ADD COLUMN "styling" JSONB;

Comment on lines +34 to +36
borderRadius: {
custom: "var(--fb-border-radius)",
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed the variable 'custom' to 'fbBorderRadius' for better readability and maintainability.

Suggested change
borderRadius: {
custom: "var(--fb-border-radius)",
},
borderRadius: {
fbBorderRadius: "var(--fb-border-radius)",
},

@mattinannt mattinannt self-assigned this Mar 21, 2024
Copy link
Member

@mattinannt mattinannt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pandeymangg Great job! Works great now and it's a really cool feature that gives so many new possibilities and great survey looks. 😊

@mattinannt mattinannt added this pull request to the merge queue Mar 22, 2024
Merged via the queue into main with commit fa370c6 Mar 22, 2024
12 of 14 checks passed
@mattinannt mattinannt deleted the feat/form-styling branch March 22, 2024 09:55
vidhikapadia2799 pushed a commit to vidhikapadia2799/formbricks that referenced this pull request Mar 26, 2024
Co-authored-by: Johannes <72809645+jobenjada@users.noreply.github.com>
Co-authored-by: Johannes <johannes@formbricks.com>
Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants