💩(chat) add frontend feature flags (#29)

* 💩(chat) add frontend feature flags

This introduce the use of feature flags:
 - flags can be globally enabled or disabled from the backend
 - when dynamic, it queries Posthog to get the value

* (chat) add frontend feature flags

disable buttons for feature flags

---------

Co-authored-by: Eléonore Voisin <elevoisin@gmail.com>
This commit is contained in:
BEY Quentin
2025-09-29 10:42:10 +02:00
committed by GitHub
parent 5c4b1ff388
commit 934098a1c2
4 changed files with 56 additions and 2 deletions
+2 -1
View File
@@ -8,10 +8,11 @@ and this project adheres to
## [Unreleased]
- 🎨(front) change list attachment in chat
- ✅(chat) add frontend feature flags #29
### Changed
- 🎨(front) change list attachment in chat
- 🎨(front) move emplacement for attachment
- 🎨(ui) retour ui sources files
- ✨(ui) fix retour global ui
@@ -11,9 +11,20 @@ interface ThemeCustomization {
translations?: Resource;
}
export enum FeatureFlagState {
ENABLED = 'enabled',
DISABLED = 'disabled',
DYNAMIC = 'dynamic',
}
interface FeatureFlags {
[key: string]: FeatureFlagState;
}
export interface ConfigResponse {
CRISP_WEBSITE_ID?: string;
ENVIRONMENT: string;
FEATURE_FLAGS: FeatureFlags;
FRONTEND_CSS_URL?: string;
FRONTEND_HOMEPAGE_FEATURE_ENABLED?: boolean;
FRONTEND_THEME?: Theme;
@@ -3,6 +3,8 @@ import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Box, Icon, Text } from '@/components';
import { FeatureFlagState, useConfig } from '@/core';
import { useAnalytics } from '@/libs';
import { useResponsiveStore } from '@/stores';
import { AttachmentList } from './AttachmentList';
@@ -44,6 +46,10 @@ export const InputChat = ({
const [isDragActive, setIsDragActive] = useState(false);
const { isDesktop, isMobile } = useResponsiveStore();
const [currentSuggestionIndex, setCurrentSuggestionIndex] = useState(0);
const { data: conf } = useConfig();
const { isFeatureFlagActivated } = useAnalytics();
const [fileUploadEnabled, setFileUploadEnabled] = useState(false);
const [webSearchEnabled, setWebSearchEnabled] = useState(false);
const [isResetting, setIsResetting] = useState(false);
const suggestions = [
@@ -53,6 +59,29 @@ export const InputChat = ({
t('Find recent news about...'),
];
useEffect(() => {
if (!conf?.FEATURE_FLAGS) {
setWebSearchEnabled(false);
setFileUploadEnabled(false);
return;
}
const isFeatureEnabled = (featureKey: string): boolean => {
const configValue = conf.FEATURE_FLAGS[featureKey];
if (!configValue) {
return false;
} else if (configValue === FeatureFlagState.DISABLED) {
return false;
} else if (configValue === FeatureFlagState.ENABLED) {
return true;
} else {
return isFeatureFlagActivated(featureKey);
}
};
setWebSearchEnabled(isFeatureEnabled('web-search'));
setFileUploadEnabled(isFeatureEnabled('document-upload'));
}, [conf, isFeatureFlagActivated]);
useEffect(() => {
if (messagesLength === 0) {
const interval = setInterval(() => {
@@ -140,7 +169,7 @@ export const InputChat = ({
onSubmit={handleSubmit}
onDragOver={(e) => {
e.preventDefault();
setIsDragActive(true);
setIsDragActive(fileUploadEnabled);
}}
onDragLeave={(e) => {
e.preventDefault();
@@ -149,6 +178,9 @@ export const InputChat = ({
onDrop={(e) => {
e.preventDefault();
setIsDragActive(false);
if (!fileUploadEnabled) {
return;
}
if (e.dataTransfer.files?.length) {
setFiles((prev) => {
const dt = new DataTransfer();
@@ -337,6 +369,7 @@ export const InputChat = ({
<Button
size="small"
type="button"
disabled={!fileUploadEnabled}
onClick={() => fileInputRef.current?.click()}
aria-label={t('Add attach file')}
className="c__button--neutral attach-file-button"
@@ -355,6 +388,7 @@ export const InputChat = ({
</Text>
)}
</Button>
{onToggleWebSearch && (
<Box
$margin={{ left: '4px' }}
@@ -382,6 +416,7 @@ export const InputChat = ({
<Button
size="small"
type="button"
disabled={!webSearchEnabled}
onClick={onToggleWebSearch}
aria-label={t('Research on the web')}
className="c__button--neutral research-web-button"
@@ -97,6 +97,13 @@ nextjs-portal {
padding: 9px !important;
}
.c__button--neutral.research-web-button:disabled,
.c__button--neutral.attach-file-button:disabled {
background-color: inherit !important;
opacity: 0.4;
cursor: not-allowed !important;
}
.c__button--neutral.action-chat-button .action-chat-button-icon,
.c__button--neutral.research-web-button .c__button__icon span,
.c__button--neutral.attach-file-button .c__button__icon span {