diff --git a/package.json b/package.json
index 8a72b6de..a7c54108 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "adex-interface",
- "version": "0.69.71",
+ "version": "0.69.73",
"private": true,
"dependencies": {
"@ambire/login-sdk-core": "^0.0.21",
@@ -36,7 +36,7 @@
"@visx/scale": "^3.3.0",
"@visx/xychart": "^3.3.0",
"@visx/zoom": "^3.3.0",
- "adex-common": "github:AmbireTech/adex-common#eb2d0bd0c10ef2baed38391d59dec5055646bce4",
+ "adex-common": "github:AmbireTech/adex-common#119affb121179d181a9e4dc219121dc7a68cac04",
"blockies-ts": "^1.0.0",
"d3-geo": "^3.1.0",
"dayjs": "^1.11.10",
diff --git a/src/components/AdminPanel/AdminPanel.tsx b/src/components/AdminPanel/AdminPanel.tsx
index d31bf23f..6e1b2683 100644
--- a/src/components/AdminPanel/AdminPanel.tsx
+++ b/src/components/AdminPanel/AdminPanel.tsx
@@ -7,6 +7,7 @@ import Invoices from 'components/Billing/Invoices'
import AdminAnalytics from './AdminAnalytics'
import Accounts from './Accounts'
import SSPsAnalytics from './SSPsAnalytics'
+import DspStats from './DspStats'
// import { AccountDetails } from './AccountDetails'
const AdminPanel = () => {
@@ -28,6 +29,7 @@ const AdminPanel = () => {
Invoices
Validator Analytics
SSPs Analytics
+ DSP info
Accounts
Account details
@@ -51,6 +53,10 @@ const AdminPanel = () => {
+
+
+
+
diff --git a/src/components/AdminPanel/DspStats.tsx b/src/components/AdminPanel/DspStats.tsx
new file mode 100644
index 00000000..89453014
--- /dev/null
+++ b/src/components/AdminPanel/DspStats.tsx
@@ -0,0 +1,120 @@
+import { NumberFormatter, Stack, SimpleGrid, Fieldset } from '@mantine/core'
+import CustomTable from 'components/common/CustomTable'
+import DetailsRow from 'components/common/DetailsRow'
+import useAdmin from 'hooks/useAdmin'
+import { useEffect } from 'react'
+import { BaseDSPStats, SSPQPSStats } from 'types/dspStats'
+
+const getPercent = (total: number, part: number): string => {
+ return ` (${((part / total) * 100).toFixed(2)}%) `
+}
+
+const BaseStats = ({ dspStats }: { dspStats: BaseDSPStats }) => {
+ return (
+
+ }
+ />
+
+
+ {getPercent(dspStats.totalRequests, dspStats.ortbRequests)}
+
+
+ }
+ />
+
+
+ {getPercent(dspStats.ortbRequests, dspStats.throttledRequests)}
+
+
+ }
+ />
+
+
+ {getPercent(dspStats.ortbRequests, dspStats.bidRequestsWithNoBids)}
+
+
+ }
+ />
+
+ {getPercent(dspStats.ortbRequests, dspStats.bidRequestsBidsInTime)}
+
+
+ }
+ />
+
+
+ {getPercent(dspStats.ortbRequests, dspStats.bidRequestsWithBidsLate)}
+
+
+ }
+ />
+
+ )
+}
+
+const DspStats = () => {
+ const { dspStats, getDspStats } = useAdmin()
+
+ useEffect(() => {
+ getDspStats()
+ }, [getDspStats])
+
+ return (
+
+
+
+
+
+
+
+ )
+}
+
+export default DspStats
diff --git a/src/components/AdminPanel/SSPsAnalytics.tsx b/src/components/AdminPanel/SSPsAnalytics.tsx
index 27b4bb15..c2a39f10 100644
--- a/src/components/AdminPanel/SSPsAnalytics.tsx
+++ b/src/components/AdminPanel/SSPsAnalytics.tsx
@@ -248,7 +248,7 @@ const SSPsAnalytics = ({
size="sm"
/>
-
+
{
{isAdminPanel && (
- {
}
/>
)}
-
-
-
+
+ {
}
/>
{/* TODO: Add data for it */}
-
{/* TODO: Add data for it */}
- {
/>
}
/>
-
- {
: 'N/A'
}
/>
- {
: 'N/A'
}
/>
- {
)
}
/>
- {
)
}
/>
- {
: 'No'
}
/>
-
-
- {
inputValues={campaign.targetingInput.inputs.location}
selectData={COUNTRIES}
/>
+ {campaign.targetingInput.inputs.ssp && (
+
+ )}
@@ -443,7 +450,7 @@ const CampaignDetails = ({ isAdminPanel }: { isAdminPanel?: boolean }) => {
{campaign.adUnits.map((item: AdUnit, index: number) => {
const isLast = index === campaign.adUnits.length - 1
return (
- void }) => {
@@ -29,61 +30,55 @@ const CampaignSummary = ({ onLaunchClick }: { onLaunchClick: () => void }) => {
priceBoundsFormatted,
formattedCats,
formattedLocs,
+ formattedSSPs,
adFormats,
campaignBudgetFormatted,
advancedTargeInput,
estimatedImpressions
} = useCreateCampaignData()
+ const { isAdmin } = useAccount()
+
const loading = useMemo(() => !allowedBannerSizes.length, [allowedBannerSizes.length])
return (
-
-
-
+
+
{placement === 'site' && (
-
+
)}
-
-
-
-
+
+
+ {isAdmin && }
+
-
-
- void }) => {
noBorder
mb="xs"
/>
-
+
{step === 3 ? (
)
}
diff --git a/src/components/EditCampaign/EditCampaign.tsx b/src/components/EditCampaign/EditCampaign.tsx
index 99141bc3..f2dc50e2 100644
--- a/src/components/EditCampaign/EditCampaign.tsx
+++ b/src/components/EditCampaign/EditCampaign.tsx
@@ -20,7 +20,7 @@ import {
TargetingInputSingle
} from 'adex-common'
import MultiSelectAndRadioButtons from 'components/CreateCampaign/StepTwo/MultiSelectAndRadioButtons'
-import { CAT_GROUPS, CATEGORIES, COUNTRIES, REGION_GROUPS } from 'constants/createCampaign'
+import { CAT_GROUPS, CATEGORIES, COUNTRIES, REGION_GROUPS, SSPs } from 'constants/createCampaign'
import { parseBigNumTokenAmountToDecimal, parseToBigNumPrecision } from 'helpers'
import {
@@ -45,6 +45,7 @@ type TargetingInputEdit = {
location: TargetingInputSingle
categories: TargetingInputSingle
advanced: AdvancedInputSingle
+ ssp?: TargetingInputSingle
}
}
@@ -58,6 +59,7 @@ type FormProps = {
const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boolean }) => {
const {
+ isAdmin: isAdminEdit,
adexAccount: { balanceToken }
} = useAccount()
const { tabValue = 'budget' } = useParams()
@@ -134,6 +136,16 @@ const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boo
}
return null
},
+ ssp: (sspVal) => {
+ if (!sspVal) return 'Invalid ssp value'
+ if (sspVal.apply === 'in' && !sspVal.in.length) {
+ return 'SSP list cannot be empty'
+ }
+ if (sspVal.apply === 'nin' && !sspVal.nin.length) {
+ return 'SSP list cannot be empty'
+ }
+ return null
+ },
advanced: {
includeIncentivized: (value) => (typeof value !== 'boolean' ? 'Invalid value' : null),
disableFrequencyCapping: (value) =>
@@ -186,6 +198,14 @@ const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boo
[campaign]
)
+ const sspSelectedRadioAndValuesArray = useMemo(
+ () =>
+ campaign && campaign.targetingInput.inputs.ssp
+ ? findArrayWithLengthInObjectAsValue(campaign.targetingInput.inputs.ssp)
+ : [],
+ [campaign]
+ )
+
const handleCategories = useCallback(
(selectedRadio: TargetingInputApplyProp, categoriesValue: string[]) => {
form.setFieldValue('targetingInput.inputs.categories', {
@@ -208,6 +228,17 @@ const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boo
[form]
)
+ const handleSSps = useCallback(
+ (selectedRadio: TargetingInputApplyProp, sspValue: string[]) => {
+ form.setFieldValue('targetingInput.inputs.ssp', {
+ apply: selectedRadio,
+ in: selectedRadio === 'in' ? sspValue : [],
+ nin: selectedRadio === 'nin' ? sspValue : []
+ })
+ },
+ [form]
+ )
+
const handleEditCampaign = useCallback(
async (values: FormProps) => {
const impression = {
@@ -227,6 +258,7 @@ const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boo
const inputs: Partial = {
categories: values.targetingInput.inputs.categories,
location: values.targetingInput.inputs.location,
+ ssp: values.targetingInput.inputs.ssp,
advanced: values.targetingInput.inputs.advanced
}
@@ -422,6 +454,29 @@ const EditCampaign = ({ campaign, isAdmin }: { campaign: Campaign; isAdmin?: boo
/>
+ {isAdminEdit && (
+
+
+ SSPs
+
+
+
+ )}
+
diff --git a/src/components/common/CampainDetailsRow/index.ts b/src/components/common/CampainDetailsRow/index.ts
deleted file mode 100644
index 61ca631e..00000000
--- a/src/components/common/CampainDetailsRow/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import CampaignDetailsRow from './CampaignDetailsRow'
-
-export default CampaignDetailsRow
diff --git a/src/components/common/CampainDetailsRow/CampaignDetailsRow.tsx b/src/components/common/DetailsRow/DetailsRow.tsx
similarity index 86%
rename from src/components/common/CampainDetailsRow/CampaignDetailsRow.tsx
rename to src/components/common/DetailsRow/DetailsRow.tsx
index e341c396..812394f8 100644
--- a/src/components/common/CampainDetailsRow/CampaignDetailsRow.tsx
+++ b/src/components/common/DetailsRow/DetailsRow.tsx
@@ -1,6 +1,6 @@
import { Divider, Flex, Text, FlexProps, MantineFontSize } from '@mantine/core'
-export type CampaignDetailsRowProps = FlexProps & {
+export type DetailsRowProps = FlexProps & {
title: string
value: any | undefined
lighterColor?: boolean | undefined
@@ -9,7 +9,7 @@ export type CampaignDetailsRowProps = FlexProps & {
column?: boolean
}
-const CampaignDetailsRow = ({
+const DetailsRow = ({
title,
value,
lighterColor,
@@ -17,7 +17,7 @@ const CampaignDetailsRow = ({
noBorder = false,
column = false,
...flexProps
-}: CampaignDetailsRowProps) => {
+}: DetailsRowProps) => {
return (
<>
getAllAccounts: () => void
+ dspStats: DspStats
+ getDspStats: () => void
initialDataLoading: boolean
makeTransfer: (
values: AdminTransfer,
@@ -20,12 +23,33 @@ interface IAdminContext {
) => Promise
}
+const dspStatsDefault: DspStats = {
+ totalRequests: 0,
+ ortbRequests: 0,
+ throttledRequests: 0,
+ ortbRequestsPerSecond: 0,
+ throttledRequestsPerSecond: 0,
+ bidRequestsWithNoBids: 0,
+ bidRequestsBidsInTime: 0,
+ bidRequestsWithBidsLate: 0,
+ last24h: {
+ totalRequests: 0,
+ ortbRequests: 0,
+ throttledRequests: 0,
+ bidRequestsWithNoBids: 0,
+ bidRequestsBidsInTime: 0,
+ bidRequestsWithBidsLate: 0
+ },
+ ssp: []
+}
+
const AdminContext = createContext(null)
const AdminProvider: FC = ({ children }) => {
const { adexServicesRequest } = useAdExApi()
const [initialDataLoading, setLoading] = useState(true)
const [accounts, setAccounts] = useState