Skip to content

Commit 7afcdd2

Browse files
committed
feat: show selected user segments in a popover
1 parent c05e743 commit 7afcdd2

3 files changed

Lines changed: 93 additions & 46 deletions

File tree

ui/dashboard/src/@locales/en/common.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@
219219
"and": "AND",
220220
"or": "OR",
221221
"see-more": "See more",
222+
"show-count-user-segments_one": "{{count}} user segment selected",
223+
"show-count-user-segments_other": "{{count}} user segments selected",
224+
"remove-item-from-selection": "Remove {{name}} from selection",
222225
"default": "Default",
223226
"sort-by": "Sort by: {{sortBy}}",
224227
"sort-asc": "Ascending",

ui/dashboard/src/@locales/ja/common.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@
219219
"and": "AND",
220220
"or": "OR",
221221
"see-more": "もっと見る",
222+
"show-count-user-segments_one": "ユーザーセグメントを{{count}}件選択中",
223+
"show-count-user-segments_other": "ユーザーセグメントを{{count}}件選択中",
224+
"remove-item-from-selection": "{{name}}を選択から削除",
222225
"default": "デフォルト",
223226
"sort-by": "並び替え: {{sortBy}}",
224227
"sort-asc": "昇順",

ui/dashboard/src/elements/rule-clauses-form/index.tsx

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Feature, FeatureRuleClauseOperator, UserSegment } from '@types';
1515
import { truncateBySide } from 'utils/converts';
1616
import { isNotEmptyObject } from 'utils/data-type';
1717
import { cn } from 'utils/style';
18-
import { IconInfo, IconPlus, IconTrash } from '@icons';
18+
import { IconClose, IconInfo, IconPlus, IconTrash } from '@icons';
1919
import { UserMessage } from 'pages/feature-flag-details/targeting/individual-rule';
2020
import { RuleClauseType } from 'pages/feature-flag-details/targeting/types';
2121
import { FlagVariationPolygon } from 'pages/feature-flags/collection-layout/elements';
@@ -26,6 +26,7 @@ import Dropdown from 'components/dropdown';
2626
import Form from 'components/form';
2727
import Icon from 'components/icon';
2828
import Input from 'components/input';
29+
import { Popover } from 'components/popover';
2930
import { Tooltip } from 'components/tooltip';
3031
import DropdownMenuWithSearch from 'elements/dropdown-with-search';
3132
import FeatureFlagStatus from 'elements/feature-flag-status';
@@ -494,51 +495,34 @@ const RuleClausesForm = ({
494495
}}
495496
/>
496497
) : isUserSegment ? (
497-
<>
498-
<Dropdown
499-
options={segmentOptions}
500-
multiselect
501-
value={(value as string[]) || []}
502-
labelCustom={
503-
selectedSegments.length
504-
? truncateBySide(
505-
selectedSegments
506-
.map(item => item.name)
507-
.join(', '),
508-
50
509-
)
510-
: ''
511-
}
512-
onChange={val => {
513-
const current =
514-
(value as string[]) || [];
515-
const next = current.includes(
516-
val as string
517-
)
518-
? current.filter(v => v !== val)
519-
: [...current, val as string];
520-
field.onChange(next);
521-
}}
522-
onClear={() => field.onChange([])}
523-
placeholder={t('common:select-value')}
524-
disabled={!segmentOptions?.length}
525-
className="w-full [&>div>p]:truncate [&>div]:max-w-[calc(100%-36px)]"
526-
/>
527-
{selectedSegments.length > 0 && (
528-
<div className="flex flex-col w-full gap-y-1 mt-2">
529-
{selectedSegments.map(item => (
530-
<Link
531-
key={item.id}
532-
target="_blank"
533-
to={`/${currentEnvironment.urlCode}${PAGE_PATH_USER_SEGMENTS}/${item.id}`}
534-
className="typo-para-small text-primary-500 hover:underline truncate w-fit max-w-full"
535-
>
536-
{`${item.name} (${getSegmentSummary(item, t)})`}
537-
</Link>
538-
))}
539-
</div>
540-
)}
541-
</>
498+
<Dropdown
499+
options={segmentOptions}
500+
multiselect
501+
value={(value as string[]) || []}
502+
labelCustom={
503+
selectedSegments.length
504+
? truncateBySide(
505+
selectedSegments
506+
.map(item => item.name)
507+
.join(', '),
508+
50
509+
)
510+
: ''
511+
}
512+
onChange={val => {
513+
const current = (value as string[]) || [];
514+
const next = current.includes(
515+
val as string
516+
)
517+
? current.filter(v => v !== val)
518+
: [...current, val as string];
519+
field.onChange(next);
520+
}}
521+
onClear={() => field.onChange([])}
522+
placeholder={t('common:select-value')}
523+
disabled={!segmentOptions?.length}
524+
className="w-full [&>div>p]:truncate [&>div]:max-w-[calc(100%-36px)]"
525+
/>
542526
) : isFlag ? (
543527
<Dropdown
544528
options={variationOptions}
@@ -575,6 +559,63 @@ const RuleClausesForm = ({
575559
/>
576560
)}
577561
</Form.Control>
562+
{isUserSegment && selectedSegments.length > 0 && (
563+
<div className="mt-0.5">
564+
<Popover
565+
align="start"
566+
trigger={
567+
<div>
568+
<span className="typo-para-small font-medium text-primary-500">
569+
{t(
570+
'common:show-count-user-segments',
571+
{
572+
count: selectedSegments.length
573+
}
574+
)}
575+
</span>
576+
</div>
577+
}
578+
triggerCls="w-fit justify-start"
579+
className="flex flex-col w-[300px] gap-y-0.5 p-0 overflow-hidden"
580+
>
581+
<div className="flex flex-col gap-y-0.5 max-h-[220px] overflow-y-auto small-scroll p-2">
582+
{selectedSegments.map(item => (
583+
<div
584+
key={item.id}
585+
className="flex items-center w-full gap-x-1 rounded hover:bg-gray-50"
586+
>
587+
<Link
588+
target="_blank"
589+
to={`/${currentEnvironment.urlCode}${PAGE_PATH_USER_SEGMENTS}/${item.id}`}
590+
className="typo-para-small text-primary-500 hover:underline truncate flex-1 min-w-0 px-1 py-1"
591+
>
592+
{`${item.name} (${getSegmentSummary(item, t)})`}
593+
</Link>
594+
<button
595+
type="button"
596+
aria-label={t(
597+
'common:remove-item-from-selection',
598+
{ name: item.name }
599+
)}
600+
onClick={() => {
601+
const current =
602+
(value as string[]) || [];
603+
field.onChange(
604+
current.filter(
605+
v => v !== item.id
606+
)
607+
);
608+
}}
609+
className="flex-center shrink-0 size-5 mr-1 rounded text-gray-500 hover:text-gray-700 hover:bg-gray-200"
610+
>
611+
<Icon icon={IconClose} size="xxs" />
612+
</button>
613+
</div>
614+
))}
615+
</div>
616+
</Popover>
617+
</div>
618+
)}
578619
<Form.Message />
579620
</Form.Item>
580621
);

0 commit comments

Comments
 (0)