@stoker-platform/web-app 0.5.138 → 0.5.140
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/src/Collection.tsx +35 -15
- package/src/List.tsx +100 -126
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/src/Collection.tsx
CHANGED
|
@@ -1722,11 +1722,11 @@ function Collection({
|
|
|
1722
1722
|
{icon ? createElement(icon) : null}
|
|
1723
1723
|
<h1>{collectionTitle}</h1>
|
|
1724
1724
|
</Card>
|
|
1725
|
-
{(connectionStatus === "online" || isPreloadCacheEnabled) && (
|
|
1725
|
+
{isInitialized && (connectionStatus === "online" || isPreloadCacheEnabled) && (
|
|
1726
1726
|
<>
|
|
1727
1727
|
{tab !== "calendar" &&
|
|
1728
1728
|
!relationList?.loadAll &&
|
|
1729
|
-
(hasRangeFilter || currentField) && (
|
|
1729
|
+
(hasRangeFilter || currentField || willHaveRangeRow) && (
|
|
1730
1730
|
<div
|
|
1731
1731
|
className={cn(
|
|
1732
1732
|
"hidden",
|
|
@@ -1736,12 +1736,22 @@ function Collection({
|
|
|
1736
1736
|
"transform -translate-x-1/2",
|
|
1737
1737
|
)}
|
|
1738
1738
|
>
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1739
|
+
{hasRangeFilter || currentField ? (
|
|
1740
|
+
<DateRangeSelector
|
|
1741
|
+
collection={collection}
|
|
1742
|
+
rangeSelector={rangeSelector}
|
|
1743
|
+
setRangeSelector={setRangeSelector}
|
|
1744
|
+
relationList={!!relationList}
|
|
1745
|
+
/>
|
|
1746
|
+
) : (
|
|
1747
|
+
<div
|
|
1748
|
+
className={cn(
|
|
1749
|
+
"h-9 rounded-md border border-input bg-background shadow-sm",
|
|
1750
|
+
relationList ? "w-[220px]" : "w-[300px]",
|
|
1751
|
+
)}
|
|
1752
|
+
aria-hidden="true"
|
|
1753
|
+
/>
|
|
1754
|
+
)}
|
|
1745
1755
|
</div>
|
|
1746
1756
|
)}
|
|
1747
1757
|
<div className="relative ml-auto flex-1 md:grow-0 print:hidden flex items-center">
|
|
@@ -1883,7 +1893,7 @@ function Collection({
|
|
|
1883
1893
|
{!formList &&
|
|
1884
1894
|
!relationList?.loadAll &&
|
|
1885
1895
|
tab !== "calendar" &&
|
|
1886
|
-
(hasRangeFilter || currentField) && (
|
|
1896
|
+
(hasRangeFilter || currentField || willHaveRangeRow) && (
|
|
1887
1897
|
<div
|
|
1888
1898
|
className={cn(
|
|
1889
1899
|
relationList
|
|
@@ -1891,12 +1901,22 @@ function Collection({
|
|
|
1891
1901
|
: "lg:hidden 2xl:flex lg:absolute lg:left-1/2 lg:transform lg:-translate-x-1/2 lg:mt-0 mt-2",
|
|
1892
1902
|
)}
|
|
1893
1903
|
>
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1904
|
+
{hasRangeFilter || currentField ? (
|
|
1905
|
+
<DateRangeSelector
|
|
1906
|
+
collection={collection}
|
|
1907
|
+
rangeSelector={rangeSelector}
|
|
1908
|
+
setRangeSelector={setRangeSelector}
|
|
1909
|
+
relationList={!!relationList}
|
|
1910
|
+
/>
|
|
1911
|
+
) : (
|
|
1912
|
+
<div
|
|
1913
|
+
className={cn(
|
|
1914
|
+
"h-9 rounded-md border border-input bg-background shadow-sm",
|
|
1915
|
+
relationList ? "w-[220px]" : "w-[300px]",
|
|
1916
|
+
)}
|
|
1917
|
+
aria-hidden="true"
|
|
1918
|
+
/>
|
|
1919
|
+
)}
|
|
1900
1920
|
</div>
|
|
1901
1921
|
)}
|
|
1902
1922
|
<div
|
package/src/List.tsx
CHANGED
|
@@ -101,6 +101,96 @@ import { getSortingValue } from "./utils/getSortingValue"
|
|
|
101
101
|
|
|
102
102
|
export const description = "A list of records in a table. The content area has a search bar in the header."
|
|
103
103
|
|
|
104
|
+
type AreaChartData = { date: string; metric1: number; metric2?: number }
|
|
105
|
+
|
|
106
|
+
interface AreaMetricChartProps {
|
|
107
|
+
chartConfig: ChartConfig
|
|
108
|
+
chartData: AreaChartData[]
|
|
109
|
+
timeRange: string | undefined
|
|
110
|
+
timezone: string
|
|
111
|
+
showMetric2: boolean
|
|
112
|
+
showLegend: boolean
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const AreaMetricChart = ({
|
|
116
|
+
chartConfig,
|
|
117
|
+
chartData,
|
|
118
|
+
timeRange,
|
|
119
|
+
timezone,
|
|
120
|
+
showMetric2,
|
|
121
|
+
showLegend,
|
|
122
|
+
}: AreaMetricChartProps) => {
|
|
123
|
+
const filteredData = useMemo(() => {
|
|
124
|
+
return chartData?.filter((item) => {
|
|
125
|
+
const date = new Date(item.date)
|
|
126
|
+
let daysToSubtract = 90
|
|
127
|
+
if (timeRange === "30d") {
|
|
128
|
+
daysToSubtract = 30
|
|
129
|
+
} else if (timeRange === "7d") {
|
|
130
|
+
daysToSubtract = 7
|
|
131
|
+
}
|
|
132
|
+
const startDate = DateTime.now().setZone(timezone).toJSDate()
|
|
133
|
+
const endDate = DateTime.now().setZone(timezone).toJSDate()
|
|
134
|
+
startDate.setDate(startDate.getDate() - daysToSubtract)
|
|
135
|
+
return date >= startDate && date <= endDate
|
|
136
|
+
})
|
|
137
|
+
}, [chartData, timeRange, timezone])
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<ChartContainer config={chartConfig} className="aspect-auto h-[173px] w-full">
|
|
141
|
+
<AreaChart data={filteredData}>
|
|
142
|
+
<defs>
|
|
143
|
+
<linearGradient id="fill1" x1="0" y1="0" x2="0" y2="1">
|
|
144
|
+
<stop offset="5%" stopColor="var(--chart-dark)" stopOpacity={0.8} />
|
|
145
|
+
<stop offset="95%" stopColor="var(--chart-light)" stopOpacity={0.1} />
|
|
146
|
+
</linearGradient>
|
|
147
|
+
<linearGradient id="fill2" x1="0" y1="0" x2="0" y2="1">
|
|
148
|
+
<stop offset="5%" stopColor="var(--chart-dark)" stopOpacity={0.8} />
|
|
149
|
+
<stop offset="95%" stopColor="var(--chart-light)" stopOpacity={0.1} />
|
|
150
|
+
</linearGradient>
|
|
151
|
+
</defs>
|
|
152
|
+
<CartesianGrid vertical={false} className="last:opacity-0" />
|
|
153
|
+
<XAxis
|
|
154
|
+
dataKey="date"
|
|
155
|
+
tickLine={false}
|
|
156
|
+
axisLine={false}
|
|
157
|
+
tickMargin={8}
|
|
158
|
+
minTickGap={32}
|
|
159
|
+
tickFormatter={(value) => {
|
|
160
|
+
const date = new Date(value)
|
|
161
|
+
return date.toLocaleDateString("en-US", {
|
|
162
|
+
month: "short",
|
|
163
|
+
day: "numeric",
|
|
164
|
+
})
|
|
165
|
+
}}
|
|
166
|
+
/>
|
|
167
|
+
<YAxis hide padding={{ top: 16 }} />
|
|
168
|
+
<ChartTooltip
|
|
169
|
+
cursor={false}
|
|
170
|
+
content={
|
|
171
|
+
<ChartTooltipContent
|
|
172
|
+
labelFormatter={(value) => {
|
|
173
|
+
return new Date(value).toLocaleDateString("en-US", {
|
|
174
|
+
month: "short",
|
|
175
|
+
day: "numeric",
|
|
176
|
+
})
|
|
177
|
+
}}
|
|
178
|
+
indicator="dot"
|
|
179
|
+
/>
|
|
180
|
+
}
|
|
181
|
+
/>
|
|
182
|
+
<Area dataKey="metric1" type="natural" fill="url(#fill1)" stroke="var(--chart-dark)" stackId="a" />
|
|
183
|
+
{showMetric2 && (
|
|
184
|
+
<Area dataKey="metric2" type="natural" fill="url(#fill2)" stroke="var(--chart-light)" stackId="a" />
|
|
185
|
+
)}
|
|
186
|
+
{showLegend && <ChartLegend className="pb-3" content={<ChartLegendContent />} />}
|
|
187
|
+
</AreaChart>
|
|
188
|
+
</ChartContainer>
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const AreaMetricChartMemo = memo(AreaMetricChart)
|
|
193
|
+
|
|
104
194
|
interface ListProps {
|
|
105
195
|
collection: CollectionSchema
|
|
106
196
|
list: StokerRecord[] | undefined
|
|
@@ -1427,11 +1517,7 @@ export function List({
|
|
|
1427
1517
|
|
|
1428
1518
|
const chartData =
|
|
1429
1519
|
// eslint-disable-next-line security/detect-object-injection
|
|
1430
|
-
(metricsValues[index] as
|
|
1431
|
-
date: string
|
|
1432
|
-
metric1: number
|
|
1433
|
-
metric2?: number
|
|
1434
|
-
}[]) || []
|
|
1520
|
+
(metricsValues[index] as AreaChartData[]) || []
|
|
1435
1521
|
|
|
1436
1522
|
const chartConfig = {
|
|
1437
1523
|
visitors: {
|
|
@@ -1447,22 +1533,6 @@ export function List({
|
|
|
1447
1533
|
},
|
|
1448
1534
|
} satisfies ChartConfig
|
|
1449
1535
|
|
|
1450
|
-
const filteredData = chartData?.filter((item) => {
|
|
1451
|
-
const date = new Date(item.date)
|
|
1452
|
-
let daysToSubtract = 90
|
|
1453
|
-
// eslint-disable-next-line security/detect-object-injection
|
|
1454
|
-
if (timeRange[metricTitle] === "30d") {
|
|
1455
|
-
daysToSubtract = 30
|
|
1456
|
-
// eslint-disable-next-line security/detect-object-injection
|
|
1457
|
-
} else if (timeRange[metricTitle] === "7d") {
|
|
1458
|
-
daysToSubtract = 7
|
|
1459
|
-
}
|
|
1460
|
-
const startDate = DateTime.now().setZone(timezone).toJSDate()
|
|
1461
|
-
const endDate = DateTime.now().setZone(timezone).toJSDate()
|
|
1462
|
-
startDate.setDate(startDate.getDate() - daysToSubtract)
|
|
1463
|
-
return date >= startDate && date <= endDate
|
|
1464
|
-
})
|
|
1465
|
-
|
|
1466
1536
|
return (
|
|
1467
1537
|
<div key={`metric-${index}`} className="grid gap-3 flex-1 min-w-0">
|
|
1468
1538
|
<Card className="pt-0 w-full" key={`metric-${index}`}>
|
|
@@ -1504,111 +1574,15 @@ export function List({
|
|
|
1504
1574
|
</Select>
|
|
1505
1575
|
</CardHeader>
|
|
1506
1576
|
<CardContent className="flex-1 px-2 sm:px-6 pb-0">
|
|
1507
|
-
<
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
y1="0"
|
|
1517
|
-
x2="0"
|
|
1518
|
-
y2="1"
|
|
1519
|
-
>
|
|
1520
|
-
<stop
|
|
1521
|
-
offset="5%"
|
|
1522
|
-
stopColor="var(--chart-dark)"
|
|
1523
|
-
stopOpacity={0.8}
|
|
1524
|
-
/>
|
|
1525
|
-
<stop
|
|
1526
|
-
offset="95%"
|
|
1527
|
-
stopColor="var(--chart-light)"
|
|
1528
|
-
stopOpacity={0.1}
|
|
1529
|
-
/>
|
|
1530
|
-
</linearGradient>
|
|
1531
|
-
<linearGradient
|
|
1532
|
-
id="fill2"
|
|
1533
|
-
x1="0"
|
|
1534
|
-
y1="0"
|
|
1535
|
-
x2="0"
|
|
1536
|
-
y2="1"
|
|
1537
|
-
>
|
|
1538
|
-
<stop
|
|
1539
|
-
offset="5%"
|
|
1540
|
-
stopColor="var(--chart-dark)"
|
|
1541
|
-
stopOpacity={0.8}
|
|
1542
|
-
/>
|
|
1543
|
-
<stop
|
|
1544
|
-
offset="95%"
|
|
1545
|
-
stopColor="var(--chart-light)"
|
|
1546
|
-
stopOpacity={0.1}
|
|
1547
|
-
/>
|
|
1548
|
-
</linearGradient>
|
|
1549
|
-
</defs>
|
|
1550
|
-
<CartesianGrid
|
|
1551
|
-
vertical={false}
|
|
1552
|
-
className="last:opacity-0"
|
|
1553
|
-
/>
|
|
1554
|
-
<XAxis
|
|
1555
|
-
dataKey="date"
|
|
1556
|
-
tickLine={false}
|
|
1557
|
-
axisLine={false}
|
|
1558
|
-
tickMargin={8}
|
|
1559
|
-
minTickGap={32}
|
|
1560
|
-
tickFormatter={(value) => {
|
|
1561
|
-
const date = new Date(value)
|
|
1562
|
-
return date.toLocaleDateString(
|
|
1563
|
-
"en-US",
|
|
1564
|
-
{
|
|
1565
|
-
month: "short",
|
|
1566
|
-
day: "numeric",
|
|
1567
|
-
},
|
|
1568
|
-
)
|
|
1569
|
-
}}
|
|
1570
|
-
/>
|
|
1571
|
-
<YAxis hide padding={{ top: 16 }} />
|
|
1572
|
-
<ChartTooltip
|
|
1573
|
-
cursor={false}
|
|
1574
|
-
content={
|
|
1575
|
-
<ChartTooltipContent
|
|
1576
|
-
labelFormatter={(value) => {
|
|
1577
|
-
return new Date(
|
|
1578
|
-
value,
|
|
1579
|
-
).toLocaleDateString("en-US", {
|
|
1580
|
-
month: "short",
|
|
1581
|
-
day: "numeric",
|
|
1582
|
-
})
|
|
1583
|
-
}}
|
|
1584
|
-
indicator="dot"
|
|
1585
|
-
/>
|
|
1586
|
-
}
|
|
1587
|
-
/>
|
|
1588
|
-
<Area
|
|
1589
|
-
dataKey="metric1"
|
|
1590
|
-
type="natural"
|
|
1591
|
-
fill="url(#fill1)"
|
|
1592
|
-
stroke="var(--chart-dark)"
|
|
1593
|
-
stackId="a"
|
|
1594
|
-
/>
|
|
1595
|
-
{metricField2 && (
|
|
1596
|
-
<Area
|
|
1597
|
-
dataKey="metric2"
|
|
1598
|
-
type="natural"
|
|
1599
|
-
fill="url(#fill2)"
|
|
1600
|
-
stroke="var(--chart-light)"
|
|
1601
|
-
stackId="a"
|
|
1602
|
-
/>
|
|
1603
|
-
)}
|
|
1604
|
-
{metricField1 && metricField2 && (
|
|
1605
|
-
<ChartLegend
|
|
1606
|
-
className="pb-3"
|
|
1607
|
-
content={<ChartLegendContent />}
|
|
1608
|
-
/>
|
|
1609
|
-
)}
|
|
1610
|
-
</AreaChart>
|
|
1611
|
-
</ChartContainer>
|
|
1577
|
+
<AreaMetricChartMemo
|
|
1578
|
+
chartConfig={chartConfig}
|
|
1579
|
+
chartData={chartData}
|
|
1580
|
+
// eslint-disable-next-line security/detect-object-injection
|
|
1581
|
+
timeRange={timeRange[metricTitle]}
|
|
1582
|
+
timezone={timezone}
|
|
1583
|
+
showMetric2={!!metricField2}
|
|
1584
|
+
showLegend={!!(metricField1 && metricField2)}
|
|
1585
|
+
/>
|
|
1612
1586
|
</CardContent>
|
|
1613
1587
|
</div>
|
|
1614
1588
|
</Card>
|