1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

feat: make feedback available for OSS (#5748)

This commit is contained in:
Jaanus Sellin 2024-01-03 15:08:01 +02:00 committed by GitHub
parent 1556a51e37
commit a73d87a943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 66 deletions

View File

@ -84,7 +84,7 @@ const FeatureToggleListTableComponent: VFC = () => {
const [showExportDialog, setShowExportDialog] = useState(false);
const { setToastApiError } = useToast();
const { uiConfig, isPro, isOss, isEnterprise } = useUiConfig();
const { uiConfig } = useUiConfig();
const featureSearchFeedback = useUiFlag('featureSearchFeedback');
const stateConfig = {
@ -275,16 +275,8 @@ const FeatureToggleListTableComponent: VFC = () => {
}
const createFeedbackContext = () => {
const userType = isPro()
? 'pro'
: isOss()
? 'oss'
: isEnterprise()
? 'enterprise'
: 'unknown';
openFeedback({
category: feedbackCategory,
userType,
title: 'How easy was it to use search and filters?',
positiveLabel: 'What do you like most about search and filters?',
areasForImprovementsLabel:
@ -335,7 +327,6 @@ const FeatureToggleListTableComponent: VFC = () => {
/>
<ConditionallyRender
condition={
!isOss() &&
!hasSubmittedFeedback &&
featureSearchFeedback
}

View File

@ -14,6 +14,10 @@ import useToast from 'hooks/useToast';
import { ProvideFeedbackSchema } from '../../openapi';
import { useUserFeedbackApi } from 'hooks/api/actions/useUserFeedbackApi/useUserFeedbackApi';
import { useUserSubmittedFeedback } from 'hooks/useSubmittedFeedback';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { IToast } from 'interfaces/toast';
import { useTheme } from '@mui/material/styles';
import { FeedbackData } from './FeedbackContext';
export const ParentContainer = styled('div')(({ theme }) => ({
position: 'relative',
@ -155,12 +159,34 @@ const StyledCloseButton = styled(IconButton)(({ theme }) => ({
color: theme.palette.background.paper,
}));
export const FeedbackComponent = () => {
export const FeedbackComponentWrapper = () => {
const { feedbackData, showFeedback, closeFeedback } = useFeedback();
if (!feedbackData) return null;
return (
<FeedbackComponent
feedbackData={feedbackData}
showFeedback={showFeedback}
closeFeedback={closeFeedback}
/>
);
};
interface IFeedbackComponent {
feedbackData: FeedbackData;
showFeedback: boolean;
closeFeedback: () => void;
}
export const FeedbackComponent = ({
feedbackData,
showFeedback,
closeFeedback,
}: IFeedbackComponent) => {
const { setToastData } = useToast();
const theme = useTheme();
const { isPro, isOss, isEnterprise } = useUiConfig();
const { addFeedback } = useUserFeedbackApi();
const { setHasSubmittedFeedback } = useUserSubmittedFeedback(
feedbackData.category,
@ -184,19 +210,22 @@ export const FeedbackComponent = () => {
const formData = new FormData(event.currentTarget);
const data = Object.fromEntries(formData);
let toastType: IToast['type'] = 'error';
let toastTitle = 'Feedback not sent';
if (isProvideFeedbackSchema(data)) {
await addFeedback(data as ProvideFeedbackSchema);
setToastData({
title: 'Feedback sent',
type: 'success',
});
setHasSubmittedFeedback(true);
} else {
setToastData({
title: 'Feedback not sent',
type: 'error',
});
try {
await addFeedback(data as ProvideFeedbackSchema);
toastTitle = 'Feedback sent';
toastType = 'success';
setHasSubmittedFeedback(true);
} catch (e) {}
}
setToastData({
title: toastTitle,
type: toastType,
});
closeFeedback();
};
@ -206,6 +235,22 @@ export const FeedbackComponent = () => {
setSelectedScore(event.target.value);
};
const getUserType = () => {
if (isPro()) {
return 'pro';
}
if (isOss()) {
return 'oss';
}
if (isEnterprise()) {
return 'enterprise';
}
return 'unknown';
};
return (
<ConditionallyRender
condition={showFeedback}
@ -233,7 +278,7 @@ export const FeedbackComponent = () => {
<input
type='hidden'
name='userType'
value={feedbackData.userType}
value={getUserType()}
/>
<FormTitle>{feedbackData.title}</FormTitle>
<StyledScoreContainer>
@ -273,7 +318,8 @@ export const FeedbackComponent = () => {
size='small'
InputLabelProps={{
style: {
fontSize: '14px',
fontSize:
theme.fontSizes.smallBody,
},
}}
/>
@ -290,7 +336,8 @@ export const FeedbackComponent = () => {
rows={3}
InputLabelProps={{
style: {
fontSize: '14px',
fontSize:
theme.fontSizes.smallBody,
},
}}
variant='outlined'

View File

@ -3,21 +3,22 @@ import { ProvideFeedbackSchema } from '../../openapi';
import { IFeedbackCategory } from 'hooks/useSubmittedFeedback';
interface IFeedbackContext {
feedbackData: IFeedbackData | undefined;
openFeedback: (data: IFeedbackData) => void;
feedbackData: FeedbackData | undefined;
openFeedback: (data: FeedbackData) => void;
closeFeedback: () => void;
showFeedback: boolean;
setShowFeedback: (visible: boolean) => void;
}
type IFeedbackText = {
interface IFeedbackText {
title: string;
positiveLabel: string;
areasForImprovementsLabel: string;
};
}
export type IFeedbackData = Pick<ProvideFeedbackSchema, 'userType'> &
IFeedbackText & { category: IFeedbackCategory };
export type FeedbackData = IFeedbackText & {
category: IFeedbackCategory;
};
export const FeedbackContext = createContext<IFeedbackContext | undefined>(
undefined,

View File

@ -1,14 +1,17 @@
import { FeedbackComponent } from './FeedbackComponent';
import { FeedbackContext, IFeedbackData } from './FeedbackContext';
import {
FeedbackComponent,
FeedbackComponentWrapper,
} from './FeedbackComponent';
import { FeedbackContext, FeedbackData } from './FeedbackContext';
import { FC, useState } from 'react';
export const FeedbackProvider: FC = ({ children }) => {
const [feedbackData, setFeedbackData] = useState<IFeedbackData | undefined>(
const [feedbackData, setFeedbackData] = useState<FeedbackData | undefined>(
undefined,
);
const [showFeedback, setShowFeedback] = useState(false);
const openFeedback = (data: IFeedbackData) => {
const openFeedback = (data: FeedbackData) => {
setFeedbackData(data);
setShowFeedback(true);
};
@ -29,7 +32,7 @@ export const FeedbackProvider: FC = ({ children }) => {
}}
>
{children}
<FeedbackComponent />
<FeedbackComponentWrapper />
</FeedbackContext.Provider>
);
};

View File

@ -2,41 +2,20 @@ import useAPI from '../useApi/useApi';
import { ProvideFeedbackSchema } from '../../../../openapi';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
const ENDPOINT = 'feedback';
const ENDPOINT = 'https://app.unleash-hosted.com/hosted/feedback';
export const useUserFeedbackApi = () => {
const { uiConfig } = useUiConfig();
const { loading, makeRequest, createRequest, errors } = useAPI({
propagateErrors: true,
});
const addFeedback = async (feedbackSchema: ProvideFeedbackSchema) => {
if (uiConfig.feedbackUriPath !== undefined) {
await fetch(uiConfig.feedbackUriPath, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(feedbackSchema),
});
} else {
const requestId = 'addFeedback';
const req = createRequest(
ENDPOINT,
{
method: 'POST',
body: JSON.stringify(feedbackSchema),
},
requestId,
);
const response = await makeRequest(req.caller, req.id);
return response.json();
}
await fetch(uiConfig.feedbackUriPath || ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(feedbackSchema),
});
};
return {
addFeedback,
errors,
loading,
};
};

View File

@ -84,7 +84,7 @@ exports[`should create default config 1`] = `
"embedProxy": true,
"embedProxyFrontend": true,
"featureSearchAPI": false,
"featureSearchFeedback": false,
"featureSearchFeedback": true,
"featureSearchFeedbackPosting": false,
"featureSearchFrontend": false,
"featuresExportImport": true,

View File

@ -53,6 +53,7 @@ const secureHeaders: (config: IUnleashConfig) => RequestHandler = (config) => {
'plausible.getunleash.io',
'gravatar.com',
'europe-west3-metrics-304612.cloudfunctions.net',
'app.unleash-hosted.com',
...config.additionalCspAllowedDomains.connectSrc,
],
mediaSrc: [

View File

@ -155,7 +155,7 @@ const flags: IFlags = {
),
featureSearchFeedback: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_SEARCH_FEEDBACK,
false,
true,
),
featureSearchFeedbackPosting: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_FEATURE_SEARCH_FEEDBACK_POSTING,

View File

@ -47,7 +47,6 @@ process.nextTick(async () => {
stripHeadersOnAPI: true,
celebrateUnleash: true,
increaseUnleashWidth: true,
featureSearchFeedback: true,
},
},
authentication: {