Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
e9e9fc06
Commit
e9e9fc06
authored
Dec 11, 2022
by
Yuri Mikhin
Committed by
Yuri Mikhin
Dec 12, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve stats charts.
parent
441f62af
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
51 additions
and
44 deletions
+51
-44
repeat_arrow.svg
icons/repeat_arrow.svg
+3
-0
vertical_dots.svg
icons/vertical_dots.svg
+0
-0
charts.ts
pages/api/stats/charts.ts
+2
-2
counters.ts
pages/api/stats/counters.ts
+0
-0
stats.ts
types/client/stats.ts
+0
-6
ChartWidget.tsx
ui/stats/ChartWidget.tsx
+24
-20
ChartWidgetGraph.tsx
ui/stats/ChartWidgetGraph.tsx
+8
-6
ChartWidgetSkeleton.tsx
ui/stats/ChartWidgetSkeleton.tsx
+1
-1
ChartsWidgetsList.tsx
ui/stats/ChartsWidgetsList.tsx
+1
-2
FullscreenChartModal.tsx
ui/stats/FullscreenChartModal.tsx
+1
-1
NumberWidgetsList.tsx
ui/stats/NumberWidgetsList.tsx
+1
-1
StatsDropdownMenu.tsx
ui/stats/StatsDropdownMenu.tsx
+9
-3
StatsFilters.tsx
ui/stats/StatsFilters.tsx
+1
-1
charts-scheme.ts
ui/stats/constants/charts-scheme.ts
+0
-1
No files found.
icons/repeat_arrow.svg
0 → 100644
View file @
e9e9fc06
<svg
viewBox=
"0 0 20 20"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<path
d=
"M6.485 7.012h1.446a.918.918 0 1 1 0 1.84H4.253a.919.919 0 0 1-.92-.92V4.254a.919.919 0 1 1 1.84 0v1.47l.505-.505a6.436 6.436 0 0 1 9.103 0 6.436 6.436 0 0 1 0 9.103 6.436 6.436 0 0 1-9.103 0 .92.92 0 0 1 1.302-1.301 4.597 4.597 0 1 0 0-6.503l-.495.494Z"
fill=
"currentColor"
/>
</svg>
icons/vertical
-
dots.svg
→
icons/vertical
_
dots.svg
View file @
e9e9fc06
File moved
pages/api/stats/charts
/blocks/new
.ts
→
pages/api/stats/charts.ts
View file @
e9e9fc06
...
@@ -4,8 +4,8 @@ import appConfig from 'configs/app/config';
...
@@ -4,8 +4,8 @@ import appConfig from 'configs/app/config';
import
handler
from
'
lib/api/handler
'
;
import
handler
from
'
lib/api/handler
'
;
const
getUrl
=
(
req
:
NextApiRequest
)
=>
{
const
getUrl
=
(
req
:
NextApiRequest
)
=>
{
const
{
from
,
to
}
=
req
.
query
;
const
{
name
,
from
,
to
}
=
req
.
query
;
return
`/v1/
blocks/new?
${
from
?
`&from=
${
from
}
&to=
${
to
}
`
:
''
}
`
;
return
`/v1/
charts/line?name=
${
name
}
${
from
?
`&from=
${
from
}
&to=
${
to
}
`
:
''
}
`
;
};
};
const
requestHandler
=
handler
(
getUrl
,
[
'
GET
'
],
appConfig
.
statsApi
.
endpoint
);
const
requestHandler
=
handler
(
getUrl
,
[
'
GET
'
],
appConfig
.
statsApi
.
endpoint
);
...
...
pages/api/stats/
index
.ts
→
pages/api/stats/
counters
.ts
View file @
e9e9fc06
File moved
types/client/stats.ts
View file @
e9e9fc06
...
@@ -23,10 +23,4 @@ export type StatsChart = {
...
@@ -23,10 +23,4 @@ export type StatsChart = {
id
:
string
;
id
:
string
;
title
:
string
;
title
:
string
;
description
:
string
;
description
:
string
;
apiMethodURL
:
string
;
}
export
interface
ModalChart
{
id
:
string
;
title
:
string
;
}
}
ui/stats/ChartWidget.tsx
View file @
e9e9fc06
import
{
Box
,
Button
,
Grid
,
Heading
,
Icon
,
IconButton
,
Menu
,
MenuButton
,
MenuItem
,
MenuList
,
Text
,
useColorModeValue
,
VisuallyHidden
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Grid
,
Heading
,
Icon
,
IconButton
,
Menu
,
MenuButton
,
MenuItem
,
MenuList
,
Text
,
useColorModeValue
,
VisuallyHidden
}
from
'
@chakra-ui/react
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
import
React
,
{
useCallback
,
useState
}
from
'
react
'
;
...
@@ -6,7 +6,8 @@ import type { Charts } from 'types/api/stats';
...
@@ -6,7 +6,8 @@ import type { Charts } from 'types/api/stats';
import
{
QueryKeys
}
from
'
types/client/queries
'
;
import
{
QueryKeys
}
from
'
types/client/queries
'
;
import
type
{
StatsIntervalIds
}
from
'
types/client/stats
'
;
import
type
{
StatsIntervalIds
}
from
'
types/client/stats
'
;
import
dotsIcon
from
'
icons/vertical-dots.svg
'
;
import
repeatArrow
from
'
icons/repeat_arrow.svg
'
;
import
dotsIcon
from
'
icons/vertical_dots.svg
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
ChartWidgetGraph
from
'
./ChartWidgetGraph
'
;
import
ChartWidgetGraph
from
'
./ChartWidgetGraph
'
;
...
@@ -16,7 +17,6 @@ import FullscreenChartModal from './FullscreenChartModal';
...
@@ -16,7 +17,6 @@ import FullscreenChartModal from './FullscreenChartModal';
type
Props
=
{
type
Props
=
{
id
:
string
;
id
:
string
;
apiMethodURL
:
string
;
title
:
string
;
title
:
string
;
description
:
string
;
description
:
string
;
interval
:
StatsIntervalIds
;
interval
:
StatsIntervalIds
;
...
@@ -26,7 +26,7 @@ function formatDate(date: Date) {
...
@@ -26,7 +26,7 @@ function formatDate(date: Date) {
return
date
.
toISOString
().
substring
(
0
,
10
);
return
date
.
toISOString
().
substring
(
0
,
10
);
}
}
const
ChartWidget
=
({
id
,
title
,
description
,
apiMethodURL
,
interval
}:
Props
)
=>
{
const
ChartWidget
=
({
id
,
title
,
description
,
interval
}:
Props
)
=>
{
const
fetch
=
useFetch
();
const
fetch
=
useFetch
();
const
selectedInterval
=
STATS_INTERVALS
[
interval
];
const
selectedInterval
=
STATS_INTERVALS
[
interval
];
...
@@ -40,7 +40,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
...
@@ -40,7 +40,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
const
menuButtonColor
=
useColorModeValue
(
'
black
'
,
'
white
'
);
const
menuButtonColor
=
useColorModeValue
(
'
black
'
,
'
white
'
);
const
borderColor
=
useColorModeValue
(
'
gray.200
'
,
'
gray.600
'
);
const
borderColor
=
useColorModeValue
(
'
gray.200
'
,
'
gray.600
'
);
const
url
=
`
${
apiMethodURL
}${
startDate
?
`?
from=
${
startDate
}
&to=
${
endDate
}
`
:
''
}
`
;
const
url
=
`
/node-api/stats/charts?name=
${
id
}${
startDate
?
`&
from=
${
startDate
}
&to=
${
endDate
}
`
:
''
}
`
;
const
{
data
,
isLoading
}
=
useQuery
<
unknown
,
unknown
,
Charts
>
(
const
{
data
,
isLoading
}
=
useQuery
<
unknown
,
unknown
,
Charts
>
(
[
QueryKeys
.
charts
,
id
,
startDate
],
[
QueryKeys
.
charts
,
id
,
startDate
],
...
@@ -58,7 +58,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
...
@@ -58,7 +58,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
const
showChartFullscreen
=
useCallback
(()
=>
{
const
showChartFullscreen
=
useCallback
(()
=>
{
setIsFullscreen
(
true
);
setIsFullscreen
(
true
);
if
(
!
document
.
fullscreenElement
)
{
if
(
!
document
.
fullscreenElement
&&
document
.
documentElement
.
requestFullscreen
)
{
document
.
documentElement
.
requestFullscreen
();
document
.
documentElement
.
requestFullscreen
();
}
}
},
[]);
},
[]);
...
@@ -91,7 +91,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
...
@@ -91,7 +91,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
>
>
<
Grid
<
Grid
gridTemplateColumns=
"auto auto 36px"
gridTemplateColumns=
"auto auto 36px"
gridColumnGap=
{
4
}
gridColumnGap=
{
2
}
>
>
<
Heading
<
Heading
mb=
{
1
}
mb=
{
1
}
...
@@ -110,19 +110,22 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
...
@@ -110,19 +110,22 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
{
description
}
{
description
}
</
Text
>
</
Text
>
{
!
isZoomResetInitial
&&
(
<
IconButton
<
Button
hidden=
{
isZoomResetInitial
}
gridColumn=
{
2
}
aria
-
label=
"Reset zoom"
justifySelf=
"end"
title=
"Reset zoom"
alignSelf=
"top"
colorScheme=
"blue"
gridRow=
"1/3"
w=
{
9
}
size=
"sm"
h=
{
8
}
variant=
"outline"
gridColumn=
{
2
}
onClick=
{
handleZoomResetClick
}
justifySelf=
"end"
>
alignSelf=
"top"
Reset zoom
gridRow=
"1/3"
</
Button
>
size=
"sm"
)
}
variant=
"ghost"
onClick=
{
handleZoomResetClick
}
icon=
{
<
Icon
as=
{
repeatArrow
}
w=
{
4
}
h=
{
4
}
color=
"blue.700"
/>
}
/>
<
Menu
>
<
Menu
>
<
MenuButton
<
MenuButton
...
@@ -152,6 +155,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
...
@@ -152,6 +155,7 @@ const ChartWidget = ({ id, title, description, apiMethodURL, interval }: Props)
title=
{
title
}
title=
{
title
}
/>
/>
</
Box
>
</
Box
>
<
FullscreenChartModal
<
FullscreenChartModal
isOpen=
{
isFullscreen
}
isOpen=
{
isFullscreen
}
items=
{
items
}
items=
{
items
}
...
...
ui/stats/ChartWidgetGraph.tsx
View file @
e9e9fc06
...
@@ -3,6 +3,7 @@ import React, { useEffect, useMemo } from 'react';
...
@@ -3,6 +3,7 @@ import React, { useEffect, useMemo } from 'react';
import
type
{
TimeChartItem
}
from
'
ui/shared/chart/types
'
;
import
type
{
TimeChartItem
}
from
'
ui/shared/chart/types
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
ChartArea
from
'
ui/shared/chart/ChartArea
'
;
import
ChartArea
from
'
ui/shared/chart/ChartArea
'
;
import
ChartAxis
from
'
ui/shared/chart/ChartAxis
'
;
import
ChartAxis
from
'
ui/shared/chart/ChartAxis
'
;
import
ChartGridLine
from
'
ui/shared/chart/ChartGridLine
'
;
import
ChartGridLine
from
'
ui/shared/chart/ChartGridLine
'
;
...
@@ -23,12 +24,13 @@ interface Props {
...
@@ -23,12 +24,13 @@ interface Props {
const
CHART_MARGIN
=
{
bottom
:
20
,
left
:
52
,
right
:
30
,
top
:
10
};
const
CHART_MARGIN
=
{
bottom
:
20
,
left
:
52
,
right
:
30
,
top
:
10
};
const
ChartWidgetGraph
=
({
items
,
onZoom
,
isZoomResetInitial
,
title
}:
Props
)
=>
{
const
ChartWidgetGraph
=
({
items
,
onZoom
,
isZoomResetInitial
,
title
}:
Props
)
=>
{
const
isMobile
=
useIsMobile
();
const
ref
=
React
.
useRef
<
SVGSVGElement
>
(
null
);
const
ref
=
React
.
useRef
<
SVGSVGElement
>
(
null
);
const
[
range
,
setRange
]
=
React
.
useState
<
[
number
,
number
]
>
([
0
,
Infinity
]);
const
{
width
,
height
,
innerWidth
,
innerHeight
}
=
useChartSize
(
ref
.
current
,
CHART_MARGIN
);
const
overlayRef
=
React
.
useRef
<
SVGRectElement
>
(
null
);
const
color
=
useToken
(
'
colors
'
,
'
blue.200
'
);
const
color
=
useToken
(
'
colors
'
,
'
blue.200
'
);
const
overlayRef
=
React
.
useRef
<
SVGRectElement
>
(
null
);
const
chartId
=
useMemo
(()
=>
`chart-
${
crypto
.
randomUUID
()
}
`
,
[]);
const
chartId
=
useMemo
(()
=>
`chart-
${
crypto
.
randomUUID
()
}
`
,
[]);
const
[
range
,
setRange
]
=
React
.
useState
<
[
number
,
number
]
>
([
0
,
Infinity
]);
const
{
innerWidth
,
innerHeight
}
=
useChartSize
(
ref
.
current
,
CHART_MARGIN
);
const
displayedData
=
useMemo
(()
=>
items
.
slice
(
range
[
0
],
range
[
1
]).
map
((
d
)
=>
const
displayedData
=
useMemo
(()
=>
items
.
slice
(
range
[
0
],
range
[
1
]).
map
((
d
)
=>
({
...
d
,
date
:
new
Date
(
d
.
date
)
})),
[
items
,
range
]);
({
...
d
,
date
:
new
Date
(
d
.
date
)
})),
[
items
,
range
]);
...
@@ -52,9 +54,9 @@ const ChartWidgetGraph = ({ items, onZoom, isZoomResetInitial, title }: Props) =
...
@@ -52,9 +54,9 @@ const ChartWidgetGraph = ({ items, onZoom, isZoomResetInitial, title }: Props) =
},
[
isZoomResetInitial
]);
},
[
isZoomResetInitial
]);
return
(
return
(
<
svg
width=
{
width
||
'
100%
'
}
height=
{
height
||
'
100%
'
}
ref=
{
ref
}
cursor=
"pointer"
id=
{
chartId
}
>
<
svg
width=
"100%"
height=
"100%"
ref=
{
ref
}
cursor=
"pointer"
id=
{
chartId
}
>
<
g
transform=
{
`translate(${ CHART_MARGIN?.left || 0 },${ CHART_MARGIN?.top || 0 })`
}
opacity=
{
width
?
1
:
0
}
>
<
g
transform=
{
`translate(${ CHART_MARGIN?.left || 0 },${ CHART_MARGIN?.top || 0 })`
}
opacity=
{
1
}
>
<
ChartGridLine
<
ChartGridLine
type=
"horizontal"
type=
"horizontal"
scale=
{
yScale
}
scale=
{
yScale
}
...
@@ -93,7 +95,7 @@ const ChartWidgetGraph = ({ items, onZoom, isZoomResetInitial, title }: Props) =
...
@@ -93,7 +95,7 @@ const ChartWidgetGraph = ({ items, onZoom, isZoomResetInitial, title }: Props) =
type=
"bottom"
type=
"bottom"
scale=
{
xScale
}
scale=
{
xScale
}
transform=
{
`translate(0, ${ innerHeight })`
}
transform=
{
`translate(0, ${ innerHeight })`
}
ticks=
{
5
}
ticks=
{
isMobile
?
1
:
3
}
anchorEl=
{
overlayRef
.
current
}
anchorEl=
{
overlayRef
.
current
}
disableAnimation
disableAnimation
/>
/>
...
...
ui/stats/ChartWidgetSkeleton.tsx
View file @
e9e9fc06
...
@@ -5,7 +5,7 @@ const ChartWidgetSkeleton = () => {
...
@@ -5,7 +5,7 @@ const ChartWidgetSkeleton = () => {
return
(
return
(
<
Box
<
Box
height=
"235px"
height=
"235px"
padding=
{
{
base
:
3
,
md
:
4
}
}
padding
Y
=
{
{
base
:
3
,
md
:
4
}
}
>
>
<
Skeleton
w=
"75%"
h=
"24px"
mb=
{
1
}
/>
<
Skeleton
w=
"75%"
h=
"24px"
mb=
{
1
}
/>
<
Skeleton
w=
"50%"
h=
"18px"
mb=
{
5
}
/>
<
Skeleton
w=
"50%"
h=
"18px"
mb=
{
5
}
/>
...
...
ui/stats/ChartsWidgetsList.tsx
View file @
e9e9fc06
...
@@ -39,7 +39,7 @@ const ChartsWidgetsList = ({ charts, interval }: Props) => {
...
@@ -39,7 +39,7 @@ const ChartsWidgetsList = ({ charts, interval }: Props) => {
<
Grid
<
Grid
templateColumns=
{
{
templateColumns=
{
{
sm
:
'
repeat(2, 1fr)
'
,
lg
:
'
repeat(2, 1fr)
'
,
}
}
}
}
gap=
{
4
}
gap=
{
4
}
>
>
...
@@ -50,7 +50,6 @@ const ChartsWidgetsList = ({ charts, interval }: Props) => {
...
@@ -50,7 +50,6 @@ const ChartsWidgetsList = ({ charts, interval }: Props) => {
>
>
<
ChartWidget
<
ChartWidget
id=
{
chart
.
id
}
id=
{
chart
.
id
}
apiMethodURL=
{
chart
.
apiMethodURL
}
title=
{
chart
.
title
}
title=
{
chart
.
title
}
description=
{
chart
.
description
}
description=
{
chart
.
description
}
interval=
{
interval
}
interval=
{
interval
}
...
...
ui/stats/FullscreenChartModal.tsx
View file @
e9e9fc06
...
@@ -74,7 +74,7 @@ const FullscreenChartModal = ({
...
@@ -74,7 +74,7 @@ const FullscreenChartModal = ({
<
ModalCloseButton
/>
<
ModalCloseButton
/>
<
ModalBody
<
ModalBody
h=
"
100
%"
h=
"
75
%"
>
>
<
ChartWidgetGraph
<
ChartWidgetGraph
items=
{
items
}
items=
{
items
}
...
...
ui/stats/NumberWidgetsList.tsx
View file @
e9e9fc06
...
@@ -17,7 +17,7 @@ const NumberWidgetsList = () => {
...
@@ -17,7 +17,7 @@ const NumberWidgetsList = () => {
const
{
data
,
isLoading
}
=
useQuery
<
unknown
,
unknown
,
Stats
>
(
const
{
data
,
isLoading
}
=
useQuery
<
unknown
,
unknown
,
Stats
>
(
[
QueryKeys
.
stats
],
[
QueryKeys
.
stats
],
async
()
=>
await
fetch
(
`/node-api/stats`
),
async
()
=>
await
fetch
(
`/node-api/stats
/counters
`
),
);
);
return
(
return
(
...
...
ui/stats/StatsDropdownMenu.tsx
View file @
e9e9fc06
import
{
Box
,
Button
,
Icon
,
Menu
,
MenuButton
,
MenuItemOption
,
MenuList
,
MenuOptionGroup
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Button
,
Icon
,
Menu
,
MenuButton
,
MenuItemOption
,
MenuList
,
MenuOptionGroup
,
Text
}
from
'
@chakra-ui/react
'
;
import
React
,
{
useCallback
}
from
'
react
'
;
import
React
,
{
useCallback
}
from
'
react
'
;
import
eastMiniArrowIcon
from
'
icons/arrows/east-mini.svg
'
;
import
eastMiniArrowIcon
from
'
icons/arrows/east-mini.svg
'
;
...
@@ -32,8 +32,14 @@ export function StatsDropdownMenu<T extends string>({ items, selectedId, onSelec
...
@@ -32,8 +32,14 @@ export function StatsDropdownMenu<T extends string>({ items, selectedId, onSelec
display=
"flex"
display=
"flex"
alignItems=
"center"
alignItems=
"center"
>
>
{
selectedCategory
?.
title
}
<
Text
<
Icon
transform=
"rotate(-90deg)"
ml=
{
{
base
:
'
auto
'
,
sm
:
1
}
}
as=
{
eastMiniArrowIcon
}
w=
{
5
}
h=
{
5
}
/>
whiteSpace=
"nowrap"
overflow=
"hidden"
textOverflow=
"ellipsis"
>
{
selectedCategory
?.
title
}
</
Text
>
<
Icon
transform=
"rotate(-90deg)"
ml=
"auto"
as=
{
eastMiniArrowIcon
}
w=
{
5
}
h=
{
5
}
/>
</
Box
>
</
Box
>
</
MenuButton
>
</
MenuButton
>
...
...
ui/stats/StatsFilters.tsx
View file @
e9e9fc06
...
@@ -48,7 +48,7 @@ const StatsFilters = ({
...
@@ -48,7 +48,7 @@ const StatsFilters = ({
"section interval"`
,
"section interval"`
,
lg
:
`"input section interval"`
,
lg
:
`"input section interval"`
,
}
}
}
}
gridTemplateColumns=
{
{
lg
:
'
1fr auto auto
'
}
}
gridTemplateColumns=
{
{
base
:
'
repeat(2, minmax(0, 1fr))
'
,
lg
:
'
1fr auto auto
'
}
}
>
>
<
GridItem
<
GridItem
w=
"100%"
w=
"100%"
...
...
ui/stats/constants/charts-scheme.ts
View file @
e9e9fc06
...
@@ -9,7 +9,6 @@ export const statsChartsScheme: Array<StatsSection> = [
...
@@ -9,7 +9,6 @@ export const statsChartsScheme: Array<StatsSection> = [
id
:
'
new-blocks
'
,
id
:
'
new-blocks
'
,
title
:
'
New blocks
'
,
title
:
'
New blocks
'
,
description
:
'
New blocks number per day
'
,
description
:
'
New blocks number per day
'
,
apiMethodURL
:
'
/node-api/stats/charts/blocks/new
'
,
visible
:
true
,
visible
:
true
,
},
},
],
],
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment