Skip to content
Closed
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
7 changes: 2 additions & 5 deletions frontend/web/components/modals/CreateSegment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
} from 'common/services/useSegment'
import Utils from 'common/utils/utils'
import AssociatedSegmentOverrides from 'components/segments/AssociatedSegmentOverrides'
import { SegmentMembershipTotalBadge } from 'components/segments/SegmentMembershipBadge'
import { SegmentMembershipTabCount } from 'components/segments/SegmentMembershipBadge'
import Button from 'components/base/forms/Button'
import InfoMessage from 'components/InfoMessage'
import InputGroup from 'components/base/forms/InputGroup'
Expand Down Expand Up @@ -588,10 +588,7 @@ const CreateSegment: FC<CreateSegmentType> = ({
tabLabel={
<>
Identities
<SegmentMembershipTotalBadge
compact
memberships={segment.memberships}
/>
<SegmentMembershipTabCount memberships={segment.memberships} />
</>
}
>
Expand Down
19 changes: 11 additions & 8 deletions frontend/web/components/modals/CreateSegmentUsersTabContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import {
identitySegmentService,
useGetIdentitySegmentsQuery,
} from 'common/services/useIdentitySegment'
import { useGetEnvironmentsQuery } from 'common/services/useEnvironment'
import { getStore } from 'common/store'
import ProjectStore from 'common/stores/project-store'
import { SegmentMembershipEnvBadge } from 'components/segments/SegmentMembershipBadge'
import { SegmentMembershipEnvCount } from 'components/segments/SegmentMembershipBadge'

interface CreateSegmentUsersTabContentProps {
projectId: string | number
Expand Down Expand Up @@ -99,6 +99,10 @@ const CreateSegmentUsersTabContent: React.FC<
setPage,
setSearchInput,
}) => {
const { data: envsData } = useGetEnvironmentsQuery({
projectId: `${projectId}`,
})

const membershipByEnvId = React.useMemo(() => {
const map = new Map<number, SegmentMembership>()
;(memberships ?? []).forEach((m) => map.set(m.environment, m))
Expand All @@ -111,12 +115,12 @@ const CreateSegmentUsersTabContent: React.FC<
? membershipByEnvId.get(environment.id)
: undefined
return (
<span className='d-flex align-items-center'>
<span className='d-flex align-items-center justify-content-between flex-grow-1'>
<span>{label}</span>
{environment && membership && (
<SegmentMembershipEnvBadge
<SegmentMembershipEnvCount
membership={membership}
environment={environment}
envApiKey={environment.api_key}
/>
)}
</span>
Expand All @@ -125,10 +129,9 @@ const CreateSegmentUsersTabContent: React.FC<

const selectedMembership = React.useMemo(() => {
if (!environmentId) return null
const envs = (ProjectStore.getEnvs() as Environment[] | null) || []
const env = envs.find((e) => e.api_key === environmentId)
const env = envsData?.results.find((e) => e.api_key === environmentId)
return env ? membershipByEnvId.get(env.id) ?? null : null
}, [environmentId, membershipByEnvId])
}, [environmentId, envsData?.results, membershipByEnvId])

return (
<>
Expand Down
96 changes: 36 additions & 60 deletions frontend/web/components/segments/SegmentMembershipBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,89 +1,65 @@
import React, { FC } from 'react'

import { Environment, SegmentMembership } from 'common/types/responses'
import ProjectStore from 'common/stores/project-store'
import { SegmentMembership } from 'common/types/responses'
import UsersIcon from 'components/icons/UsersIcon'

const shortAgo = (iso: string): string => {
const diffSec = Math.max(0, Math.round((Date.now() - new Date(iso).getTime()) / 1000))
if (diffSec < 60) return `${diffSec}s ago`
const diffMin = Math.round(diffSec / 60)
if (diffMin < 60) return `${diffMin}m ago`
const diffHr = Math.round(diffMin / 60)
if (diffHr < 24) return `${diffHr}h ago`
return `${Math.round(diffHr / 24)}d ago`
}
const sumCounts = (memberships: SegmentMembership[]): number =>
memberships.reduce((sum, m) => sum + m.count, 0)

const identityNoun = (count: number): string =>
count === 1 ? 'identity' : 'identities'

type ChipProps = {
count: number
ago?: string
dataTest?: string
compact?: boolean
type TotalProps = {
memberships: SegmentMembership[] | undefined
}

const Chip: FC<ChipProps> = ({ ago, compact, count, dataTest }) => {
const noun = count === 1 ? 'identity' : 'identities'
export const SegmentMembershipTotalBadge: FC<TotalProps> = ({
memberships,
}) => {
if (!memberships?.length) {
return null
}
const total = sumCounts(memberships)
return (
<span
className='chip chip--xs bg-primary text-white ms-3'
style={{ border: 'none', alignSelf: 'center', verticalAlign: 'middle' }}
data-test={dataTest}
className='chip chip--xs chip--filled ms-2'
data-test='segment-membership-total'
>
<UsersIcon className='chip-svg-icon' />
<span>
{count}
{compact ? '' : ` ${noun}`}
{ago ? ` ~${ago}` : ''}
{total} {identityNoun(total)}
</span>
</span>
)
}

type TotalProps = {
memberships: SegmentMembership[] | undefined
compact?: boolean
}

export const SegmentMembershipTotalBadge: FC<TotalProps> = ({
compact,
memberships,
}) => {
export const SegmentMembershipTabCount: FC<TotalProps> = ({ memberships }) => {
if (!memberships?.length) {
return null
}
const total = memberships.reduce((sum, m) => sum + m.count, 0)
const latest = memberships.reduce(
(acc, m) => (!acc || m.last_synced_at > acc ? m.last_synced_at : acc),
'',
)
return (
<Chip
compact={compact}
count={total}
ago={latest ? shortAgo(latest) : undefined}
dataTest='segment-membership-total'
/>
<span
className='ms-2 text-muted fw-normal'
data-test='segment-membership-total'
>
({sumCounts(memberships)})
</span>
)
}

type EnvProps = {
membership: SegmentMembership
environment?: Environment
envApiKey: string
}

export const SegmentMembershipEnvBadge: FC<EnvProps> = ({
environment,
export const SegmentMembershipEnvCount: FC<EnvProps> = ({
envApiKey,
membership,
}) => {
const envs = (ProjectStore.getEnvs() as Environment[] | null) || []
const env = environment ?? envs.find((e) => e.id === membership.environment)
if (!env) {
return null
}
return (
<Chip
count={membership.count}
dataTest={`segment-membership-${env.api_key}`}
/>
)
}
}) => (
<span
className='text-muted fs-small ms-auto ps-2'
data-test={`segment-membership-${envApiKey}`}
>
{membership.count} {identityNoun(membership.count)}
</span>
)
7 changes: 6 additions & 1 deletion frontend/web/styles/components/_chip.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
.chip {
display: flex;
align-items: center;
align-self: flex-start;
align-self: flex-start !important;
background-color: $primary-alfa-8;
border: 1px solid $primary-alfa-24;
padding: 5px 12px;
Expand All @@ -38,6 +38,11 @@
font-weight: normal;
text-wrap: nowrap;
color: $primary600;
&--filled {
background-color: $primary;
border-color: $primary;
color: $white;
}
&-secondary {
background-color: $bg-light300;
color: $text-icon-grey;
Expand Down
Loading