diff --git a/assets/icons/headphones.svg b/assets/icons/headphones.svg new file mode 100644 index 00000000..98b393ef --- /dev/null +++ b/assets/icons/headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/monitor.svg b/assets/icons/monitor.svg new file mode 100644 index 00000000..8d8c7af9 --- /dev/null +++ b/assets/icons/monitor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/shopping-cart.svg b/assets/icons/shopping-cart.svg new file mode 100644 index 00000000..fedbbae0 --- /dev/null +++ b/assets/icons/shopping-cart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/smartphone.svg b/assets/icons/smartphone.svg new file mode 100644 index 00000000..bb785ab5 --- /dev/null +++ b/assets/icons/smartphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/star-solid.svg b/assets/icons/star-solid.svg new file mode 100644 index 00000000..02f6e1ba --- /dev/null +++ b/assets/icons/star-solid.svg @@ -0,0 +1,4 @@ + + + Star Solid + \ No newline at end of file diff --git a/assets/icons/trending-up.svg b/assets/icons/trending-up.svg new file mode 100644 index 00000000..b44aef1e --- /dev/null +++ b/assets/icons/trending-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/wallet.svg b/assets/icons/wallet.svg new file mode 100644 index 00000000..9d39e59a --- /dev/null +++ b/assets/icons/wallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/samples/mediaco/CustomListView/ActivityListView.scss b/src/samples/mediaco/CustomListView/ActivityListView.scss new file mode 100644 index 00000000..c1ff3d00 --- /dev/null +++ b/src/samples/mediaco/CustomListView/ActivityListView.scss @@ -0,0 +1,395 @@ +.alv-root { + color: #111827; + max-width: 100%; +} + +.header-container { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + margin-bottom: 10px; +} + +.alv-title { + margin: 0; + line-height: 1.1; + font-size: 2rem; + font-weight: 400; + color: #222; + position: relative; + display: inline-block; + padding-bottom: 8px; + + &::after { + content: ''; + position: absolute; + left: 0; + bottom: 0; + width: 100%; + height: 4px; + background: linear-gradient(to right, #a41a61, #ff4fc3); + border-radius: 2px; + } +} + +.alv-headerBtn { + cursor: pointer; + text-align: right; + margin-top: 10px; + color: #6750a4; + + &:hover { + text-decoration: underline; + } +} + +.alv-card { + background: #ffffff; + border: 1px solid rgba(17, 24, 39, 0.08); + border-radius: 18px; + box-shadow: 0 10px 22px rgba(17, 24, 39, 0.1); + overflow: hidden; +} + +.alv-row { + position: relative; + display: grid; + grid-template-columns: 52px 1fr auto; + align-items: center; + column-gap: 14px; + padding: 16px 18px; + + &:not(:last-child)::after { + content: ''; + position: absolute; + bottom: 0; + left: 20px; + right: 16px; + height: 1px; + background-color: #e5e7eb; + } + + &:hover .alv-iconCircle { + transform: scale(1.1); + } +} + +.alv-rowClickable { + cursor: pointer; + + &:hover { + background: rgba(17, 24, 39, 0.02); + } +} + +/* Icon circle */ +.alv-iconCircle { + width: 44px; + height: 44px; + border-radius: 15px; + display: grid; + place-items: center; + flex: none; +} + +/* icon */ +.alv-iconImg { + width: 20px; + height: 20px; + object-fit: contain; + display: block; +} + +/* Background colors for each icon */ +.bg-0 { + background-color: #ede9fe; +} /* Light purple */ +.bg-1 { + background-color: #fce7f3; +} /* Light pink */ +.bg-2 { + background-color: #e0f2fe; +} /* Light blue */ +.bg-3 { + background-color: #ffedd5; +} /* Light orange */ +.bg-4 { + background-color: #f3e8ff; +} /* Lavender */ +.bg-5 { + background-color: #d1fae5; +} /* Light green */ + +.color-0 { + filter: brightness(0) saturate(100%) invert(20%) sepia(80%) hue-rotate(250deg) saturate(500%); +} /* Dark purple */ +.color-1 { + filter: brightness(0) saturate(100%) invert(20%) sepia(80%) hue-rotate(320deg) saturate(500%); +} /* Dark pink */ +.color-2 { + filter: brightness(0) saturate(100%) invert(20%) sepia(80%) hue-rotate(190deg) saturate(500%); +} /* Dark blue */ +.color-3 { + filter: brightness(0) saturate(100%) invert(20%) sepia(80%) hue-rotate(25deg) saturate(500%); +} /* Dark orange */ +.color-4 { + filter: brightness(0) saturate(100%) invert(35%) sepia(55%) hue-rotate(255deg) saturate(420%); +} /* Dark Lavender */ +.color-5 { + filter: brightness(0) saturate(100%) invert(20%) sepia(80%) hue-rotate(90deg) saturate(500%); +} /* Dark green */ + +.alv-content { + min-width: 0; +} + +.extra-content { + height: 48px; + display: flex; + align-items: center; +} + +.star { + filter: brightness(0) saturate(100%) invert(60%) sepia(92%) saturate(748%) hue-rotate(1deg) brightness(101%); + height: 16px; +} + +.alv-topLine { + display: flex; + align-items: baseline; + gap: 8px; + flex-wrap: wrap; +} + +.alv-itemTitle { + font-size: 16px; + font-weight: 500; +} + +.alv-dot { + color: rgba(17, 24, 39, 0.35); + font-weight: 700; +} + +.alv-time { + font-size: 12px; + font-weight: 450; + color: rgba(17, 24, 39, 0.45); +} + +.alv-desc { + margin: 0; + font-size: 14px; + line-height: 1.35; + color: rgba(17, 24, 39, 0.7); +} + +.alv-divider { + position: absolute; + left: 84px; + right: 18px; + bottom: 0; + height: 1px; + background: rgba(17, 24, 39, 0.1); +} + +.alv-modalOverlay { + position: fixed; + inset: 0; + z-index: 9999; + display: grid; + place-items: center; +} + +.alv-modalBackdrop { + position: absolute; + inset: 0; + background: rgba(17, 24, 39, 0.5); +} + +.alv-modalPanel { + position: relative; + width: min(920px, calc(100vw - 48px)); + height: min(560px, calc(100vh - 72px)); + background: #ffffff; + border-radius: 14px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25); + overflow: hidden; + border: 1px solid rgba(17, 24, 39, 0.12); +} + +.alv-modalShell { + height: 100%; + display: flex; + flex-direction: column; +} + +.alv-modalHeader { + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 18px 18px 14px 18px; +} + +.alv-modalTitle { + margin: 0; + font-size: 28px; + font-weight: 500; + color: #111827; + line-height: 1.1; +} + +.alv-modalSubtitle { + margin-top: 6px; + font-size: 12px; + font-weight: 400; + color: rgba(17, 24, 39, 0.55); +} + +.alv-modalCloseBtn { + border: none; + background: rgba(17, 24, 39, 0.06); + color: #111827; + width: 34px; + height: 34px; + border-radius: 999px; + display: grid; + place-items: center; + cursor: pointer; + + &:hover { + background: rgba(17, 24, 39, 0.1); + } +} + +.alv-modalDivider { + height: 1px; + background: rgba(17, 24, 39, 0.12); +} + +.alv-modalBody { + padding: 18px; + overflow: auto; +} + +/* Tiles grid */ +.alv-tilesGrid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 18px; + + /* Responsive: 1 column on narrow screens */ + @media (max-width: 640px) { + grid-template-columns: 1fr; + } +} + +/* Tile card */ +.alv-tile { + text-align: left; + width: 100%; + border: 1px solid rgba(17, 24, 39, 0.14); + background: rgba(255, 255, 255, 0.35); + border-radius: 14px; + padding: 16px; + display: grid; + grid-template-columns: 52px 1fr; + column-gap: 14px; + align-items: center; + box-shadow: 0 6px 14px rgba(17, 24, 39, 0.12); + cursor: pointer; + + &:hover { + background: rgba(255, 255, 255, 0.55); + transform: scale(1.01); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); + } + + &:focus { + outline: 2px solid rgba(214, 26, 138, 0.35); + outline-offset: 2px; + } +} + +.alv-tileIconCircle { + width: 44px; + height: 44px; + border-radius: 12px; + display: grid; + place-items: center; +} + +.alv-tileText { + min-width: 0; +} + +.alv-tileTitle { + font-size: 16px; + font-weight: 500; + color: #111827; + margin-bottom: 4px; +} + +.alv-tileDesc { + font-size: 12px; + line-height: 1.35; + color: rgba(17, 24, 39, 0.65); + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 1; + overflow: hidden; +} + +/* --- Gallery Grid Modal Styles --- */ +.gallery-grid-container { + flex: 1; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); + gap: 20px; + padding: 24px; + overflow-y: auto; +} + +.gallery-grid-item { + position: relative; + display: flex; + flex-direction: column; + border: 1px solid #e0e0e0; + border-radius: 1.5rem; + transition: + transform 0.2s, + box-shadow 0.2s; + aspect-ratio: 4 / 3; + overflow: hidden; + background-color: #000; + cursor: pointer; + + &:hover { + transform: translateY(-4px); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15); + } + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + } + + p { + position: absolute; + bottom: 0; + left: 0; + margin: 0; + padding: 16px; + width: 100%; + box-sizing: border-box; + font-weight: 500; + color: #fff; + letter-spacing: 0.15px; + font-size: 16px; + line-height: 24px; + background: linear-gradient(transparent, rgba(0, 0, 0, 0.8)); + } +} diff --git a/src/samples/mediaco/CustomListView/ActivityListView.tsx b/src/samples/mediaco/CustomListView/ActivityListView.tsx new file mode 100644 index 00000000..e3151af4 --- /dev/null +++ b/src/samples/mediaco/CustomListView/ActivityListView.tsx @@ -0,0 +1,87 @@ +import './ActivityListView.scss'; +import { getImageSrc, getSDKStaticConentUrl } from './utils'; + +interface ActivityItem { + rating?: number; + id?: string | number; + title: string; + description: string; + time: string; + iconSrc: string; + iconAlt?: string; + views?: string; + accent?: { + bg?: string; + fg?: string; + }; +} + +interface ActivityListViewProps { + title?: string; + items?: ActivityItem[]; + referenceDataPage?: string; + showAllItems: () => void; + onItemClick?: (item: ActivityItem) => void; +} + +export default function ActivityListView({ title, items = [], referenceDataPage, showAllItems }: ActivityListViewProps) { + return ( +
+
+

{title}

+
+ +
+ {items.slice(0, 5).map((item, idx) => ( +
+ + +
+
+ {item.title} + {item.time && ( + + )} + {item.time} +
+
+ {item.description} + {item.views && ( + + )} + {item.views} +
+
+ {item.rating && ( +
+ star +  {item.rating} +
+ )} +
+ ))} +
+ {referenceDataPage === 'D_AccountHistoryList' && ( +
+ Show all +
+ )} +
+ ); +} diff --git a/src/samples/mediaco/CustomListView/CarouselListView.scss b/src/samples/mediaco/CustomListView/CarouselListView.scss new file mode 100644 index 00000000..f1dabc6a --- /dev/null +++ b/src/samples/mediaco/CustomListView/CarouselListView.scss @@ -0,0 +1,118 @@ +.carousel-host-container { + width: 100%; + position: relative; + overflow: hidden; + display: flex; + flex-direction: column; +} + +.header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; + padding: 0 16px; + + h2 { + margin: 0; + font-size: 20px; + font-weight: 500; + } +} + +.carousel-scroll-area { + display: flex; + align-items: center; + width: 100%; + max-width: 100%; + padding: 0; + overflow-x: auto; + overflow-y: hidden; + scroll-behavior: auto; + box-sizing: border-box; + border-radius: 12px; + + &::-webkit-scrollbar { + display: none; + } + scrollbar-width: none; +} + +.card-wrapper { + flex: 0 0 200px; + height: 350px; + margin: 0 10px; + transition: + flex-basis 0.1s linear, + min-width 0.1s linear; + will-change: flex-basis, min-width; + min-width: 0; +} + +.inner-material-card { + width: 100%; + height: 100%; + padding: 0 !important; + overflow: hidden; + position: relative; + background: #000; + border-radius: 8px; + + img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + } + + .card-overlay { + position: absolute; + bottom: 0; + left: 0; + width: 100%; + padding: 16px; + background: linear-gradient(transparent, rgba(0, 0, 0, 0.9)); + color: white; + + h3 { + margin: 0; + font-size: 16px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } +} + +.skeleton-shimmer { + width: 100%; + height: 100%; + background: #e0e0e0; + position: relative; + overflow: hidden; + + &::after { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + transform: translateX(-100%); + background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.1) 50%, transparent 100%); + animation: shimmer 1.5s infinite; + } +} + +.skeleton-text { + height: 16px; + width: 80%; + background: rgba(255, 255, 255, 0.3); + border-radius: 4px; +} + +@keyframes shimmer { + 100% { + transform: translateX(100%); + } +} diff --git a/src/samples/mediaco/CustomListView/CarouselListView.tsx b/src/samples/mediaco/CustomListView/CarouselListView.tsx new file mode 100644 index 00000000..d4f337d3 --- /dev/null +++ b/src/samples/mediaco/CustomListView/CarouselListView.tsx @@ -0,0 +1,201 @@ +import React, { useEffect, useRef, useState, useCallback } from 'react'; +import Card from '@mui/material/Card'; +import './CarouselListView.scss'; + +interface CarouselProps { + data: any[]; + getPConnect?: any; + title?: string; + showAllItems?: () => void; + referenceDataPage?: string; +} + +export const Carousel: React.FC = ({ data, title, showAllItems }) => { + const [isLoading, setIsLoading] = useState(true); + const [displayItems, setDisplayItems] = useState([]); + + const scrollContainerRef = useRef(null); + const cardRefs = useRef<(HTMLDivElement | null)[]>([]); + + const skeletonItems = new Array(6).fill(0); + + // 1. Build Data and Preload Images + useEffect(() => { + if (!data || data.length === 0) { + setIsLoading(true); + return; + } + + const mappedData = data.map(item => ({ + title: item.Carouselheading || item.Description || 'Untitled', + img: item.ImageURL, + ...item + })); + + let loopList = [...mappedData]; + const MIN_ITEMS = 12; + + if (loopList.length > 0) { + while (loopList.length < MIN_ITEMS) { + loopList = [...loopList, ...loopList]; + } + } + + const finalDisplayItems = [...loopList, ...loopList, ...loopList]; + setDisplayItems(finalDisplayItems); + + // Preload Logic + const uniqueUrls = [...new Set(finalDisplayItems.map(item => item.img))].filter(Boolean); + let loadedCount = 0; + const total = uniqueUrls.length; + + if (total === 0) { + setIsLoading(false); + return; + } + + uniqueUrls.forEach(url => { + const img = new Image(); + img.src = url; + + const onImageComplete = () => { + loadedCount++; + if (loadedCount === total) { + setIsLoading(false); + } + }; + + img.onload = onImageComplete; + img.onerror = onImageComplete; + }); + }, [data]); + + // The Scroll Math Logic + const handleScroll = useCallback( + (event: Event) => { + if (isLoading) return; + + const container = event.target as HTMLElement; + if (!container) return; + + requestAnimationFrame(() => { + const totalWidth = container.scrollWidth; + const singleSetWidth = totalWidth / 3; + const currentScroll = container.scrollLeft; + + // Infinite scroll snapping + if (currentScroll < 100) { + container.scrollLeft = currentScroll + singleSetWidth; + } else if (currentScroll >= singleSetWidth * 2 - 100) { + container.scrollLeft = currentScroll - singleSetWidth; + } + + const containerRect = container.getBoundingClientRect(); + if (containerRect.width === 0) return; + + // Dynamic width and opacity calculation + cardRefs.current.forEach(el => { + if (!el) return; + const rect = el.getBoundingClientRect(); + const cardCenter = rect.left - containerRect.left + rect.width / 2; + const containerCenter = containerRect.width / 2; + const distance = Math.abs(containerCenter - cardCenter); + + const activeZone = 400; + const minWidth = 200; + const maxWidth = 500; + let currentWidth = minWidth; + let opacity = 0.7; + + if (distance < activeZone) { + const factor = 1 - distance / activeZone; + currentWidth = minWidth + (maxWidth - minWidth) * factor; + opacity = 0.7 + 0.3 * factor; + } + + el.style.flexBasis = `${currentWidth}px`; + el.style.minWidth = `${currentWidth}px`; + el.style.opacity = `${opacity}`; + }); + }); + }, + [isLoading] + ); + + // Attach Scroll Listener + useEffect(() => { + const container = scrollContainerRef.current; + if (container) { + container.addEventListener('scroll', handleScroll); + return () => container.removeEventListener('scroll', handleScroll); + } + }, [handleScroll]); + + // Initialize Scroll Position once loading finishes + useEffect(() => { + if (!isLoading && scrollContainerRef.current) { + const container = scrollContainerRef.current; + + // setTimeout allows the browser to paint the flex items before measuring + setTimeout(() => { + if (container.scrollWidth > 0) { + const singleSetWidth = container.scrollWidth / 3; + container.scrollLeft = singleSetWidth; + + // Trigger the calculation to set initial card sizes + handleScroll({ target: container } as any); + } + }, 0); + } + }, [isLoading, handleScroll]); + + return ( +
+ {title && ( +
+

{title}

+
+ )} + +
+
+ {isLoading + ? // Skeleton State + skeletonItems.map((_, index) => ( +
+ +
+
+
+
+
+
+ )) + : // Loaded State + displayItems.map((item, index) => ( +
{ + cardRefs.current[index] = el; + }} + > + + Card Image +
+

{item.title}

+
+
+
+ ))} +
+
+ + {showAllItems && ( +
+ Show all +
+ )} +
+ ); +}; diff --git a/src/samples/mediaco/CustomListView/ListViewWrapper.tsx b/src/samples/mediaco/CustomListView/ListViewWrapper.tsx new file mode 100644 index 00000000..10212d79 --- /dev/null +++ b/src/samples/mediaco/CustomListView/ListViewWrapper.tsx @@ -0,0 +1,158 @@ +import { useEffect, useMemo, useRef, useState } from 'react'; +import ActivityListView from './ActivityListView'; +import './ActivityListView.scss'; +import { Carousel } from './CarouselListView'; + +import { modifyListData } from './utils'; +import type { PConnProps } from '@pega/react-sdk-components/lib/types/PConnProps'; + +interface ListViewProps extends PConnProps { + bInForm?: boolean; + globalSearch?: boolean; + referenceList?: any[]; + selectionMode?: string; + referenceType?: string; + payload?: any; + parameters?: any; + compositeKeys?: any; + showDynamicFields?: boolean; + readonlyContextList?: any; + value: any; + viewName?: string; + showRecords?: boolean; + displayAs?: string; +} + +export default function ListViewWrapper(props: ListViewProps) { + const [items, setItems] = useState([]); + const [open, setOpen] = useState(false); + const closeBtnRef = useRef(null); + const closeModal = () => setOpen(false); + const { getPConnect } = props; + const thePConn = getPConnect(); + const configProps: any = thePConn.getConfigProps() as ListViewProps; + const referenceDataPage = configProps.referenceList; + const template = configProps.presets[0]?.template; + const itemCountLabel = useMemo(() => { + const n = items?.length ?? 0; + return `${n} item${n === 1 ? '' : 's'} available`; + }, [items]); + + useEffect(() => { + PCore.getDataPageUtils() + .getDataAsync(referenceDataPage, thePConn.getContextName()) + .then(({ data }) => { + const modifiedData = data ? modifyListData(data, referenceDataPage) : []; + setItems(modifiedData); + }); + }, []); + + // ESC close + scroll lock + focus close button + useEffect(() => { + if (!open) return; + + const onKeyDown = e => { + if (e.key === 'Escape') closeModal(); + }; + + document.addEventListener('keydown', onKeyDown); + const prevOverflow = document.body.style.overflow; + document.body.style.overflow = 'hidden'; + return () => { + document.removeEventListener('keydown', onKeyDown); + document.body.style.overflow = prevOverflow; + }; + }, [open]); + + function showAllItems() { + setOpen(true); + } + + const title = + referenceDataPage === 'D_AccountHistoryList' + ? 'Activity' + : referenceDataPage === 'D_TrendingItemsList' + ? 'Trending Now' + : referenceDataPage === 'D_CarouselitemList' + ? 'Featured Content' + : ''; + + return ( +
+ {template === 'Table' && } + {template === 'Gallery' && } + {open && ( + +
+
+
+

{title === 'Activity' ? 'All Activities' : title}

+
{itemCountLabel}
+
+ + +
+ +
+ +
+ {template === 'Table' ? ( + // Existing List View Render +
+ {items.map((item, idx) => ( +
+ +
+
{item.title}
+
{item.description}
+
+
+ ))} +
+ ) : template === 'Gallery' ? ( +
+ {items.map((item, idx) => ( +
+ {item.Carouselheading +

{item.Carouselheading}

+
+ ))} +
+ ) : null} +
+
+ + )} +
+ ); +} + +function XIcon() { + return ( + + ); +} + +function Modal({ children, onClose }) { + return ( +
+ {/* Backdrop */} +
+ {/* Panel */} +
{children}
+
+ ); +} diff --git a/src/samples/mediaco/CustomListView/utils.ts b/src/samples/mediaco/CustomListView/utils.ts new file mode 100644 index 00000000..800f0726 --- /dev/null +++ b/src/samples/mediaco/CustomListView/utils.ts @@ -0,0 +1,114 @@ +import { SdkConfigAccess } from '@pega/auth/lib/sdk-auth-manager'; + +export function getImageSrc(name, serverUrl) { + let iconName = name.replace('pi-', '').replace('pi ', '').trim(); + if (iconName === 'line-chart') { + iconName = 'chart-line'; + } + + return getIconPath(serverUrl).concat(iconName).concat('.svg'); +} + +export function getIconPath(serverUrl) { + return serverUrl.concat('icons/'); +} + +export function getSDKStaticConentUrl() { + const sdkConfigServer = SdkConfigAccess.getSdkConfigServer(); + + if (!sdkConfigServer.sdkContentServerUrl.endsWith('/')) { + sdkConfigServer.sdkContentServerUrl = `${sdkConfigServer.sdkContentServerUrl}/`; + } + + return `${sdkConfigServer.sdkContentServerUrl}constellation/`; +} + +export function getIcon(activityType) { + switch (activityType) { + case 'Upgrade plan': + return 'trending-up'; + case 'Make payment': + return 'wallet'; + case 'Add Streaming': + return 'monitor'; + case 'New Service': + return 'shopping-cart'; + case 'Get Help': + return 'headphones'; + case 'Purchase Phone': + return 'smartphone'; + default: + return ''; + } +} + +export function timeSince(date: Date): string { + const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000); + let interval = seconds / 31536000; + if (interval > 1) { + return Math.floor(interval) + 'y ago'; + } + interval = seconds / 2592000; + if (interval > 1) { + return Math.floor(interval) + ' months ago'; + } + interval = seconds / 86400; + if (interval > 1) { + return Math.floor(interval) + 'd ago'; + } + interval = seconds / 3600; + if (interval > 1) { + return Math.floor(interval) + 'h ago'; + } + interval = seconds / 60; + if (interval > 1) { + return Math.floor(interval) + 'm ago'; + } + return Math.floor(seconds) + 's ago'; +} + +export function modifyListData(data: any[], referenceDataPage: string) { + if (referenceDataPage === 'D_AccountHistoryList') { + const caseTypeToActivityMap = { + 'Plan Upgrade': 'Upgrade plan', + Payment: 'Make payment', + AddOnPurchase: 'New Service', + 'New Statement': 'New Service', + ProfileUpdated: 'Get Help', + 'Product Demo': 'Purchase Phone', + 'Client Onboarding': 'Add Streaming', + 'Quarterly Review': 'New Service', + 'Sales Meeting': 'New Service' + }; + return data.map(item => { + const caseType = caseTypeToActivityMap[item.ActivityType]; + return { + id: item.pyGUID, + iconSrc: getImageSrc(getIcon(caseType), getSDKStaticConentUrl()), + title: item.ActivityType, + time: timeSince(new Date(item.pxUpdateDateTime || item.pxCreateDateTime)), + description: item.Description + }; + }); + } else if (referenceDataPage === 'D_TrendingItemsList') { + return data.map(item => { + return { + id: item.ID, + title: item.Name, + time: null, + description: item.Genere, + views: `${item.Views} views`, + rating: item.Rating + }; + }); + } else if (referenceDataPage === 'D_CarouselitemList') { + return data.map((item, index) => { + return { + id: item.pyGUID || `carousel-item-${index}`, + Carouselheading: item.Carouselheading, + ImageURL: item.ImageURL + }; + }); + } + return []; +} diff --git a/src/samples/mediaco/sdk-mediaco-component-map.ts b/src/samples/mediaco/sdk-mediaco-component-map.ts index 35bd3a88..906c8587 100644 --- a/src/samples/mediaco/sdk-mediaco-component-map.ts +++ b/src/samples/mediaco/sdk-mediaco-component-map.ts @@ -1,11 +1,14 @@ // Statically load all "MediaCo" components. +import ListViewWrapper from './CustomListView/ListViewWrapper'; + /* import end - DO NOT REMOVE */ // sdkMediaCoComponentMap is the JSON object where we'll store the components that are // specific to MediaCo application. const sdkMediaCoComponentMap = { + ListView: ListViewWrapper /* map end - DO NOT REMOVE */ };