Просмотр исходного кода

feat(sampling): Improve activate toggle [TET-340] (#38426)

Matej Minar 2 лет назад
Родитель
Сommit
7770722238

+ 55 - 0
static/app/views/settings/project/server-side-sampling/rule.spec.tsx

@@ -0,0 +1,55 @@
+import {render, screen} from 'sentry-test/reactTestingLibrary';
+
+import {SamplingRuleOperator} from 'sentry/types/sampling';
+
+import {Rule} from './rule';
+import {uniformRule} from './testUtils';
+
+export const samplingBreakdownTitle = 'Transaction Breakdown';
+
+describe('Server-Side Sampling - Rule', function () {
+  it('renders toggle placeholders', function () {
+    render(
+      <Rule
+        operator={SamplingRuleOperator.IF}
+        hideGrabButton={false}
+        rule={uniformRule}
+        onEditRule={() => {}}
+        onDeleteRule={() => {}}
+        onActivate={() => {}}
+        noPermission={false}
+        upgradeSdkForProjects={[]}
+        listeners={undefined}
+        dragging={false}
+        sorting={false}
+        loadingRecommendedSdkUpgrades
+      />
+    );
+
+    expect(screen.getByTestId('loading-placeholder')).toBeInTheDocument();
+    expect(screen.queryByLabelText('Activate Rule')).not.toBeInTheDocument();
+  });
+
+  it('can be deactivated even with unsupported SDKs', function () {
+    render(
+      <Rule
+        operator={SamplingRuleOperator.IF}
+        hideGrabButton={false}
+        rule={{...uniformRule, active: true}}
+        onEditRule={() => {}}
+        onDeleteRule={() => {}}
+        onActivate={() => {}}
+        noPermission={false}
+        upgradeSdkForProjects={['javascript']}
+        listeners={undefined}
+        dragging={false}
+        sorting={false}
+        loadingRecommendedSdkUpgrades={false}
+      />
+    );
+
+    expect(screen.queryByTestId('loading-placeholder')).not.toBeInTheDocument();
+    expect(screen.getByLabelText('Deactivate Rule')).toBeInTheDocument();
+    expect(screen.getByRole('checkbox', {name: 'Deactivate Rule'})).toBeEnabled();
+  });
+});

+ 45 - 29
static/app/views/settings/project/server-side-sampling/rule.tsx

@@ -8,6 +8,7 @@ import GuideAnchor from 'sentry/components/assistant/guideAnchor';
 import Button from 'sentry/components/button';
 import DropdownLink from 'sentry/components/dropdownLink';
 import NewBooleanField from 'sentry/components/forms/booleanField';
+import Placeholder from 'sentry/components/placeholder';
 import Tooltip from 'sentry/components/tooltip';
 import {IconDownload, IconEllipsis} from 'sentry/icons';
 import {IconGrabbable} from 'sentry/icons/iconGrabbable';
@@ -27,6 +28,11 @@ type Props = {
    */
   hideGrabButton: boolean;
   listeners: DraggableSyntheticListeners;
+  /**
+   * While loading we show a placeholder in place of the "Active" toggle
+   * Without this we can't know if they are able to activate the rule or not
+   */
+  loadingRecommendedSdkUpgrades: boolean;
   noPermission: boolean;
   onActivate: () => void;
   onDeleteRule: () => void;
@@ -53,11 +59,12 @@ export function Rule({
   grabAttributes,
   hideGrabButton,
   upgradeSdkForProjects,
+  loadingRecommendedSdkUpgrades,
 }: Props) {
   const isUniform = isUniformRule(rule);
   const canDelete = !noPermission && !isUniform;
-  const canActivate = !noPermission && !upgradeSdkForProjects.length;
-  const canDrag = !isUniform && !noPermission;
+  const canDrag = !noPermission && !isUniform;
+  const canActivate = !noPermission && (!upgradeSdkForProjects.length || rule.active);
 
   return (
     <Fragment>
@@ -122,34 +129,38 @@ export function Rule({
         <SampleRate>{formatPercentage(rule.sampleRate)}</SampleRate>
       </RateColumn>
       <ActiveColumn>
-        <GuideAnchor
-          target="sampling_rule_toggle"
-          onFinish={onActivate}
-          disabled={!canActivate || !isUniform}
-        >
-          <Tooltip
-            disabled={canActivate}
-            title={
-              !canActivate
-                ? tn(
-                    'To enable the rule, the recommended sdk version have to be updated',
-                    'To enable the rule, the recommended sdk versions have to be updated',
-                    upgradeSdkForProjects.length
-                  )
-                : undefined
-            }
+        {loadingRecommendedSdkUpgrades ? (
+          <ActivateTogglePlaceholder />
+        ) : (
+          <GuideAnchor
+            target="sampling_rule_toggle"
+            onFinish={onActivate}
+            disabled={!canActivate || !isUniform}
           >
-            <ActiveToggle
-              inline={false}
-              hideControlState
-              aria-label={rule.active ? t('Deactivate Rule') : t('Activate Rule')}
-              onClick={onActivate}
-              name="active"
-              disabled={!canActivate}
-              value={rule.active}
-            />
-          </Tooltip>
-        </GuideAnchor>
+            <Tooltip
+              disabled={canActivate}
+              title={
+                !canActivate
+                  ? tn(
+                      'To enable the rule, the recommended sdk version have to be updated',
+                      'To enable the rule, the recommended sdk versions have to be updated',
+                      upgradeSdkForProjects.length
+                    )
+                  : undefined
+              }
+            >
+              <ActiveToggle
+                inline={false}
+                hideControlState
+                aria-label={rule.active ? t('Deactivate Rule') : t('Activate Rule')}
+                onClick={onActivate}
+                name="active"
+                disabled={!canActivate}
+                value={rule.active}
+              />
+            </Tooltip>
+          </GuideAnchor>
+        )}
       </ActiveColumn>
       <Column>
         <EllipisDropDownButton
@@ -290,6 +301,11 @@ const ActiveToggle = styled(NewBooleanField)`
   justify-content: center;
 `;
 
+const ActivateTogglePlaceholder = styled(Placeholder)`
+  height: 24px;
+  margin-top: ${space(0.5)};
+`;
+
 const ConditionName = styled('div')`
   color: ${p => p.theme.gray400};
 `;

+ 6 - 1
static/app/views/settings/project/server-side-sampling/serverSideSampling.tsx

@@ -121,7 +121,11 @@ export function ServerSideSampling({project}: Props) {
 
   const {projectStats48h} = useProjectStats();
 
-  const {recommendedSdkUpgrades, isProjectIncompatible} = useRecommendedSdkUpgrades({
+  const {
+    recommendedSdkUpgrades,
+    isProjectIncompatible,
+    loading: loadingRecommendedSdkUpgrades,
+  } = useRecommendedSdkUpgrades({
     orgSlug: organization.slug,
     projectId: project.id,
   });
@@ -551,6 +555,7 @@ export function ServerSideSampling({project}: Props) {
                       grabAttributes={attributes}
                       dragging={dragging}
                       sorting={sorting}
+                      loadingRecommendedSdkUpgrades={loadingRecommendedSdkUpgrades}
                     />
                   </RulesPanelLayout>
                 );