Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 12 additions & 29 deletions static/app/components/events/autofix/autofixFeedback.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,18 @@
import {useRef} from 'react';

import {Button} from 'sentry/components/core/button';
import FeedbackButton from 'sentry/components/feedbackButton/feedbackButton';
import {t} from 'sentry/locale';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';

function AutofixFeedback() {
const buttonRef = useRef<HTMLButtonElement>(null);
const openForm = useFeedbackForm();

if (!openForm) {
return null;
}

export default function AutofixFeedback() {
return (
<Button
ref={buttonRef}
<FeedbackButton
size="xs"
onClick={() =>
openForm({
formTitle: t('Give feedback to the devs'),
messagePlaceholder: t('How can we make Seer better for you?'),
tags: {
['feedback.source']: 'issue_details_ai_autofix',
['feedback.owner']: 'ml-ai',
},
})
}
>
{t('Give Us Feedback')}
</Button>
feedbackOptions={{
formTitle: t('Give feedback to the devs'),
messagePlaceholder: t('How can we make Seer better for you?'),
tags: {
['feedback.source']: 'issue_details_ai_autofix',
['feedback.owner']: 'ml-ai',
},
}}
/>
);
}

export default AutofixFeedback;
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@ import {
sortedFlags,
} from 'sentry/components/events/featureFlags/utils';
import {useOrganizationFlagLog} from 'sentry/components/featureFlags/hooks/useOrganizationFlagLog';
import FeedbackButton from 'sentry/components/feedbackButton/feedbackButton';
import useDrawer from 'sentry/components/globalDrawer';
import {useGroupSuspectFlagScores} from 'sentry/components/issues/suspect/useGroupSuspectFlagScores';
import useLegacyEventSuspectFlags from 'sentry/components/issues/suspect/useLegacyEventSuspectFlags';
import useSuspectFlagScoreThreshold from 'sentry/components/issues/suspect/useSuspectFlagScoreThreshold';
import {KeyValueData} from 'sentry/components/keyValueData';
import {IconMegaphone, IconSearch} from 'sentry/icons';
import {IconSearch} from 'sentry/icons';
import {t, tn} from 'sentry/locale';
import type {Event, FeatureFlag} from 'sentry/types/event';
import {IssueCategory, type Group} from 'sentry/types/group';
import type {Project} from 'sentry/types/project';
import {trackAnalytics} from 'sentry/utils/analytics';
import {MutableSearch} from 'sentry/utils/tokenizeSearch';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
import {useLocation} from 'sentry/utils/useLocation';
import useMedia from 'sentry/utils/useMedia';
import useOrganization from 'sentry/utils/useOrganization';
Expand Down Expand Up @@ -63,26 +63,19 @@ function BaseEventFeatureFlagList({event, group, project}: EventFeatureFlagSecti
const theme = useTheme();
const isXsScreen = useMedia(`(max-width: ${theme.breakpoints.xs})`);

const openForm = useFeedbackForm();
const feedbackButton =
openForm && !isXsScreen ? (
<Button
aria-label={t('Give feedback on the feature flag section')}
icon={<IconMegaphone />}
size="xs"
onClick={() =>
openForm({
messagePlaceholder: t('How can we make feature flags work better for you?'),
tags: {
['feedback.source']: 'issue_details_feature_flags',
['feedback.owner']: 'replay',
},
})
}
>
{t('Give Feedback')}
</Button>
) : null;
const feedbackButton = isXsScreen ? null : (
<FeedbackButton
aria-label={t('Give feedback on the feature flag section')}
size="xs"
feedbackOptions={{
messagePlaceholder: t('How can we make feature flags work better for you?'),
tags: {
['feedback.source']: 'issue_details_feature_flags',
['feedback.owner']: 'replay',
},
}}
/>
);

// If we're showing the suspect section at all
const enableSuspectFlags = organization.features.includes('feature-flag-suspect-flags');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
import styled from '@emotion/styled';

import {AiPrivacyTooltip} from 'sentry/components/aiPrivacyTooltip';
import {Button} from 'sentry/components/core/button';
import {Disclosure} from 'sentry/components/core/disclosure';
import {Flex} from 'sentry/components/core/layout';
import {useOrganizationSeerSetup} from 'sentry/components/events/autofix/useOrganizationSeerSetup';
import FeedbackCategories from 'sentry/components/feedback/summaryCategories/feedbackCategories';
import FeedbackSummary from 'sentry/components/feedback/summaryCategories/feedbackSummary';
import FeedbackButton from 'sentry/components/feedbackButton/feedbackButton';
import {IconThumb} from 'sentry/icons';
import {t} from 'sentry/locale';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
import useOrganization from 'sentry/utils/useOrganization';
import {useSyncedLocalStorageState} from 'sentry/utils/useSyncedLocalStorageState';

export default function FeedbackSummaryCategories() {
const organization = useOrganization();

const openForm = useFeedbackForm();

const {areAiFeaturesAllowed} = useOrganizationSeerSetup();

const [isExpanded, setIsExpanded] = useSyncedLocalStorageState(
Expand All @@ -35,27 +32,27 @@ export default function FeedbackSummaryCategories() {
}

const feedbackButton = ({type}: {type: 'positive' | 'negative'}) => {
return openForm ? (
<Button
return (
<FeedbackButton
aria-label={t('Give feedback on the AI-powered summary')}
icon={<IconThumb direction={type === 'positive' ? 'up' : 'down'} />}
title={type === 'positive' ? t('I like this') : t(`I don't like this`)}
size="xs"
onClick={() =>
openForm({
messagePlaceholder:
type === 'positive'
? t('What did you like about the AI-powered summary?')
: t('How can we make the summary work better for you?'),
tags: {
['feedback.source']: 'feedback_ai_summary',
['feedback.owner']: 'replay',
['feedback.type']: type,
},
})
}
/>
) : null;
feedbackOptions={{
messagePlaceholder:
type === 'positive'
? t('What did you like about the AI-powered summary?')
: t('How can we make the summary work better for you?'),
tags: {
['feedback.source']: 'feedback_ai_summary',
['feedback.owner']: 'replay',
['feedback.type']: type,
},
}}
>
{undefined}
Copy link
Member

Choose a reason for hiding this comment

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

undefined?

Copy link
Member Author

Choose a reason for hiding this comment

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

ya, need to override the default string :(

there's two places that do this for "👍 👎 " buttons. We could probably make that pair a helper in it's own right and improve this.

Copy link
Member Author

Choose a reason for hiding this comment

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

i'll follow up with that.

</FeedbackButton>
);
};

return (
Expand Down
17 changes: 8 additions & 9 deletions static/app/components/feedbackButton/feedbackButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {useRef} from 'react';
import {useRef, type ReactNode} from 'react';

import {Button, type ButtonProps} from 'sentry/components/core/button';
import {type UseFeedbackOptions} from 'sentry/components/feedbackButton/useFeedbackSDKIntegration';
import {IconMegaphone} from 'sentry/icons/iconMegaphone';
import {t} from 'sentry/locale';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';

interface Props extends Omit<ButtonProps, 'icon'> {
interface Props extends Omit<ButtonProps, 'children'> {
children?: ReactNode;
feedbackOptions?: UseFeedbackOptions;
}

Expand Down Expand Up @@ -49,11 +50,7 @@ interface Props extends Omit<ButtonProps, 'icon'> {
*
* @returns A Button that opens the feedback widget on click, or null if feedback is not enabled
*/
export default function FeedbackButton({
feedbackOptions,
children,
...buttonProps
}: Props) {
export default function FeedbackButton({feedbackOptions, ...buttonProps}: Props) {
const buttonRef = useRef<HTMLButtonElement>(null);
const openForm = useFeedbackForm();

Expand All @@ -62,18 +59,20 @@ export default function FeedbackButton({
return null;
}

const children = 'children' in buttonProps ? buttonProps.children : t('Give Feedback');

return (
<Button
ref={buttonRef}
size="sm"
{...buttonProps}
icon={<IconMegaphone />}
{...buttonProps}
onClick={e => {
openForm?.(feedbackOptions);
buttonProps.onClick?.(e);
}}
>
{children || t('Give Feedback')}
{children}
</Button>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
SelectOptionOrSectionWithKey,
} from 'sentry/components/core/compactSelect/types';
import InteractionStateLayer from 'sentry/components/core/interactionStateLayer';
import FeedbackButton from 'sentry/components/feedbackButton/feedbackButton';
import {Overlay} from 'sentry/components/overlay';
import {AskSeer} from 'sentry/components/searchQueryBuilder/askSeer/askSeer';
import {ASK_SEER_CONSENT_ITEM_KEY} from 'sentry/components/searchQueryBuilder/askSeer/askSeerConsentOption';
Expand All @@ -29,9 +30,7 @@ import {
} from 'sentry/components/searchQueryBuilder/tokens/filterKeyListBox/utils';
import type {Token, TokenResult} from 'sentry/components/searchSyntax/parser';
import {getKeyLabel, getKeyName} from 'sentry/components/searchSyntax/utils';
import {IconMegaphone} from 'sentry/icons';
import {t} from 'sentry/locale';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
import usePrevious from 'sentry/utils/usePrevious';

interface FilterKeyListBoxProps<T> extends CustomComboboxMenuProps<T> {
Expand Down Expand Up @@ -80,30 +79,20 @@ function ListBoxSectionButton({

function FeedbackFooter() {
const {searchSource} = useSearchQueryBuilder();
const openForm = useFeedbackForm();

if (!openForm) {
return null;
}

return (
<SectionedOverlayFooter>
<Button
<FeedbackButton
size="xs"
icon={<IconMegaphone />}
onClick={() =>
openForm({
messagePlaceholder: t('How can we make search better for you?'),
tags: {
search_source: searchSource,
['feedback.source']: 'search_query_builder',
['feedback.owner']: 'issues',
},
})
}
>
{t('Give Feedback')}
</Button>
feedbackOptions={{
messagePlaceholder: t('How can we make search better for you?'),
tags: {
search_source: searchSource,
['feedback.source']: 'search_query_builder',
['feedback.owner']: 'issues',
},
}}
/>
</SectionedOverlayFooter>
);
}
Expand Down
39 changes: 16 additions & 23 deletions static/app/views/alerts/rules/metric/details/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ import {OnDemandWarningIcon} from 'sentry/components/alerts/onDemandMetricAlert'
import {SectionHeading} from 'sentry/components/charts/styles';
import {ActorAvatar} from 'sentry/components/core/avatar/actorAvatar';
import {AlertBadge} from 'sentry/components/core/badge/alertBadge';
import {Button} from 'sentry/components/core/button';
import {DateTime} from 'sentry/components/dateTime';
import Duration from 'sentry/components/duration';
import FeedbackButton from 'sentry/components/feedbackButton/feedbackButton';
import {KeyValueTable, KeyValueTableRow} from 'sentry/components/keyValueTable';
import TimeSince from 'sentry/components/timeSince';
import {IconDiamond, IconMegaphone} from 'sentry/icons';
import {IconDiamond} from 'sentry/icons';
import {t, tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
import type {Actor} from 'sentry/types/core';
import {getSearchFilters, isOnDemandSearchKey} from 'sentry/utils/onDemandMetrics/index';
import {capitalize} from 'sentry/utils/string/capitalize';
import {isChonkTheme} from 'sentry/utils/theme/withChonk';
import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
import useOrganization from 'sentry/utils/useOrganization';
import {COMPARISON_DELTA_OPTIONS} from 'sentry/views/alerts/rules/metric/constants';
import type {Action, MetricRule} from 'sentry/views/alerts/rules/metric/types';
Expand Down Expand Up @@ -168,28 +167,22 @@ export function MetricDetailsSidebar({

const ownerId = rule.owner?.split(':')[1];
const teamActor = ownerId && {type: 'team' as Actor['type'], id: ownerId, name: ''};
const openForm = useFeedbackForm();

const feedbackButton = openForm ? (
<Button
onClick={() => {
openForm({
formTitle: 'Anomaly Detection Feedback',
messagePlaceholder: t(
'How can we make alerts using anomaly detection more useful?'
),
tags: {
['feedback.source']: 'dynamic_thresholding',
['feedback.owner']: 'ml-ai',
},
});

const feedbackButton = (
<FeedbackButton
feedbackOptions={{
formTitle: t('Anomaly Detection Feedback'),
messagePlaceholder: t(
'How can we make alerts using anomaly detection more useful?'
),
tags: {
['feedback.source']: 'dynamic_thresholding',
['feedback.owner']: 'ml-ai',
},
}}
size="xs"
icon={<IconMegaphone />}
>
Give Feedback
</Button>
) : null;
/>
);

return (
<Fragment>
Expand Down
Loading
Loading