Skip to content

Commit

Permalink
feat: make feedback available for OSS (#5748)
Browse files Browse the repository at this point in the history
  • Loading branch information
sjaanus authored Jan 3, 2024
1 parent 1556a51 commit a73d87a
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -335,7 +327,6 @@ const FeatureToggleListTableComponent: VFC = () => {
/>
<ConditionallyRender
condition={
!isOss() &&
!hasSubmittedFeedback &&
featureSearchFeedback
}
Expand Down
77 changes: 62 additions & 15 deletions frontend/src/component/feedbackNew/FeedbackComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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,
Expand All @@ -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();
};

Expand All @@ -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}
Expand Down Expand Up @@ -233,7 +278,7 @@ export const FeedbackComponent = () => {
<input
type='hidden'
name='userType'
value={feedbackData.userType}
value={getUserType()}
/>
<FormTitle>{feedbackData.title}</FormTitle>
<StyledScoreContainer>
Expand Down Expand Up @@ -273,7 +318,8 @@ export const FeedbackComponent = () => {
size='small'
InputLabelProps={{
style: {
fontSize: '14px',
fontSize:
theme.fontSizes.smallBody,
},
}}
/>
Expand All @@ -290,7 +336,8 @@ export const FeedbackComponent = () => {
rows={3}
InputLabelProps={{
style: {
fontSize: '14px',
fontSize:
theme.fontSizes.smallBody,
},
}}
variant='outlined'
Expand Down
13 changes: 7 additions & 6 deletions frontend/src/component/feedbackNew/FeedbackContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
13 changes: 8 additions & 5 deletions frontend/src/component/feedbackNew/FeedbackProvider.tsx
Original file line number Diff line number Diff line change
@@ -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);
};
Expand All @@ -29,7 +32,7 @@ export const FeedbackProvider: FC = ({ children }) => {
}}
>
{children}
<FeedbackComponent />
<FeedbackComponentWrapper />
</FeedbackContext.Provider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
};
2 changes: 1 addition & 1 deletion src/lib/__snapshots__/create-config.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/lib/middleware/secure-headers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types/experimental.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion src/server-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ process.nextTick(async () => {
stripHeadersOnAPI: true,
celebrateUnleash: true,
increaseUnleashWidth: true,
featureSearchFeedback: true,
},
},
authentication: {
Expand Down

0 comments on commit a73d87a

Please sign in to comment.