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
a1f00dc6
Commit
a1f00dc6
authored
Dec 20, 2022
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
stats api
parent
64300957
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
64 additions
and
61 deletions
+64
-61
config.ts
configs/app/config.ts
+1
-0
buildUrl.ts
lib/api/buildUrl.ts
+9
-8
resources.ts
lib/api/resources.ts
+20
-0
useApiFetch.tsx
lib/api/useApiFetch.tsx
+13
-4
useApiQuery.tsx
lib/api/useApiQuery.tsx
+9
-4
useFetch.tsx
lib/hooks/useFetch.tsx
+1
-0
proxy.ts
pages/api/proxy.ts
+1
-1
charts.ts
pages/api/stats/charts.ts
+0
-13
counters.ts
pages/api/stats/counters.ts
+0
-8
ChartWidgetContainer.tsx
ui/stats/ChartWidgetContainer.tsx
+8
-12
NumberWidgetsList.tsx
ui/stats/NumberWidgetsList.tsx
+2
-11
No files found.
configs/app/config.ts
View file @
a1f00dc6
...
@@ -96,6 +96,7 @@ const config = Object.freeze({
...
@@ -96,6 +96,7 @@ const config = Object.freeze({
},
},
statsApi
:
{
statsApi
:
{
endpoint
:
getEnvValue
(
process
.
env
.
NEXT_PUBLIC_STATS_API_HOST
),
endpoint
:
getEnvValue
(
process
.
env
.
NEXT_PUBLIC_STATS_API_HOST
),
basePath
:
''
,
},
},
homepage
:
{
homepage
:
{
charts
:
parseEnvJson
<
Array
<
ChainIndicatorId
>>
(
getEnvValue
(
process
.
env
.
NEXT_PUBLIC_HOMEPAGE_CHARTS
))
||
[],
charts
:
parseEnvJson
<
Array
<
ChainIndicatorId
>>
(
getEnvValue
(
process
.
env
.
NEXT_PUBLIC_HOMEPAGE_CHARTS
))
||
[],
...
...
lib/api/buildUrl.ts
View file @
a1f00dc6
...
@@ -2,23 +2,24 @@ import { compile } from 'path-to-regexp';
...
@@ -2,23 +2,24 @@ import { compile } from 'path-to-regexp';
import
appConfig
from
'
configs/app/config
'
;
import
appConfig
from
'
configs/app/config
'
;
import
{
RESOURCES
}
from
'
./resources
'
;
import
type
{
ApiResource
}
from
'
./resources
'
;
export
default
function
buildUrl
(
export
default
function
buildUrl
(
resource
:
keyof
typeof
RESOURCES
,
resource
:
ApiResource
,
pathParams
?:
Record
<
string
,
string
>
,
pathParams
?:
Record
<
string
,
string
>
,
queryParams
?:
Record
<
string
,
string
>
,
queryParams
?:
Record
<
string
,
string
|
undefined
>
,
)
{
)
{
// FIXME was not able to figure out how to send CORS with credentials from localhost
// FIXME was not able to figure out how to send CORS with credentials from localhost
// so for local development we use nextjs api as proxy server (only!)
// so for local development we use nextjs api as proxy server (only!)
const
base
=
appConfig
.
host
===
'
localhost
'
?
appConfig
.
baseUrl
:
appConfig
.
api
.
endpoint
;
const
baseUrl
=
appConfig
.
host
===
'
localhost
'
?
appConfig
.
baseUrl
:
(
resource
.
endpoint
||
appConfig
.
api
.
endpoint
);
const
basePath
=
resource
.
basePath
!==
undefined
?
resource
.
basePath
:
appConfig
.
api
.
basePath
;
const
path
=
appConfig
.
host
===
'
localhost
'
?
const
path
=
appConfig
.
host
===
'
localhost
'
?
'
/proxy
'
+
appConfig
.
api
.
basePath
+
RESOURCES
[
resource
]
.
path
:
'
/proxy
'
+
basePath
+
resource
.
path
:
appConfig
.
api
.
basePath
+
RESOURCES
[
resource
]
.
path
;
basePath
+
resource
.
path
;
const
url
=
new
URL
(
compile
(
path
)(
pathParams
),
base
);
const
url
=
new
URL
(
compile
(
path
)(
pathParams
),
base
Url
);
queryParams
&&
Object
.
entries
(
queryParams
).
forEach
(([
key
,
value
])
=>
{
queryParams
&&
Object
.
entries
(
queryParams
).
forEach
(([
key
,
value
])
=>
{
url
.
searchParams
.
append
(
key
,
value
);
value
&&
url
.
searchParams
.
append
(
key
,
value
);
});
});
return
url
.
toString
();
return
url
.
toString
();
...
...
lib/api/resources.ts
View file @
a1f00dc6
import
appConfig
from
'
configs/app/config
'
;
export
interface
ApiResource
{
path
:
string
;
endpoint
?:
string
;
basePath
?:
string
;
}
export
const
RESOURCES
=
{
export
const
RESOURCES
=
{
// account
// account
user_info
:
{
user_info
:
{
...
@@ -25,6 +33,18 @@ export const RESOURCES = {
...
@@ -25,6 +33,18 @@ export const RESOURCES = {
path
:
'
/api/account/v1/user/api_keys/:id?
'
,
path
:
'
/api/account/v1/user/api_keys/:id?
'
,
},
},
// STATS
stats_counters
:
{
path
:
'
/api/v1/counters
'
,
endpoint
:
appConfig
.
statsApi
.
endpoint
,
basePath
:
appConfig
.
statsApi
.
basePath
,
},
stats_charts
:
{
path
:
'
/api/v1/charts/line
'
,
endpoint
:
appConfig
.
statsApi
.
endpoint
,
basePath
:
appConfig
.
statsApi
.
basePath
,
},
// DEPRECATED
// DEPRECATED
old_api
:
{
old_api
:
{
path
:
'
/api
'
,
path
:
'
/api
'
,
...
...
lib/api/useApiFetch.tsx
View file @
a1f00dc6
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
appConfig
from
'
configs/app/config
'
;
import
type
{
Params
as
FetchParams
}
from
'
lib/hooks/useFetch
'
;
import
type
{
Params
as
FetchParams
}
from
'
lib/hooks/useFetch
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
buildUrl
from
'
./buildUrl
'
;
import
buildUrl
from
'
./buildUrl
'
;
import
type
{
RESOURCES
,
ResourceError
}
from
'
./resources
'
;
import
{
RESOURCES
}
from
'
./resources
'
;
import
type
{
ResourceError
,
ApiResource
}
from
'
./resources
'
;
export
interface
Params
{
export
interface
Params
{
pathParams
?:
Record
<
string
,
string
>
;
pathParams
?:
Record
<
string
,
string
>
;
queryParams
?:
Record
<
string
,
string
>
;
queryParams
?:
Record
<
string
,
string
|
undefined
>
;
fetchParams
?:
Pick
<
FetchParams
,
'
body
'
|
'
method
'
>
;
fetchParams
?:
Pick
<
FetchParams
,
'
body
'
|
'
method
'
>
;
}
}
...
@@ -16,10 +18,17 @@ export default function useApiFetch() {
...
@@ -16,10 +18,17 @@ export default function useApiFetch() {
const
fetch
=
useFetch
();
const
fetch
=
useFetch
();
return
React
.
useCallback
(<
R
extends
keyof
typeof
RESOURCES
,
SuccessType
=
unknown
,
ErrorType
=
ResourceError
>
(
return
React
.
useCallback
(<
R
extends
keyof
typeof
RESOURCES
,
SuccessType
=
unknown
,
ErrorType
=
ResourceError
>
(
resource: R,
resource
Name
: R,
{
pathParams
,
queryParams
,
fetchParams
}
: Params =
{}
,
{
pathParams
,
queryParams
,
fetchParams
}
: Params =
{}
,
) =
>
{
) =
>
{
const
resource
:
ApiResource
=
RESOURCES
[
resourceName
];
const
url
=
buildUrl
(
resource
,
pathParams
,
queryParams
);
const
url
=
buildUrl
(
resource
,
pathParams
,
queryParams
);
return
fetch
<
SuccessType
,
ErrorType
>
(
url
,
{
credentials
:
'
include
'
,
...
fetchParams
});
return
fetch
<
SuccessType
,
ErrorType
>
(
url
,
{
credentials
:
'
include
'
,
...(
resource
.
endpoint
&&
appConfig
.
host
===
'
localhost
'
?
{
headers
:
{
'
x-endpoint
'
:
resource
.
endpoint
,
}
}
:
{}),
...
fetchParams
,
});
}
, [ fetch ]);
}
, [ fetch ]);
}
}
lib/api/useApiQuery.tsx
View file @
a1f00dc6
...
@@ -2,6 +2,7 @@ import type { UseQueryOptions } from '@tanstack/react-query';
...
@@ -2,6 +2,7 @@ import type { UseQueryOptions } from '@tanstack/react-query';
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
type
{
UserInfo
,
CustomAbis
,
PublicTags
,
AddressTags
,
TransactionTags
,
ApiKeys
,
WatchlistAddress
}
from
'
types/api/account
'
;
import
type
{
UserInfo
,
CustomAbis
,
PublicTags
,
AddressTags
,
TransactionTags
,
ApiKeys
,
WatchlistAddress
}
from
'
types/api/account
'
;
import
type
{
Stats
,
Charts
}
from
'
types/api/stats
'
;
import
type
{
CsrfData
}
from
'
types/client/account
'
;
import
type
{
CsrfData
}
from
'
types/client/account
'
;
import
type
{
RESOURCES
,
ResourceError
}
from
'
./resources
'
;
import
type
{
RESOURCES
,
ResourceError
}
from
'
./resources
'
;
...
@@ -18,9 +19,11 @@ export default function useApiQuery<R extends keyof typeof RESOURCES>(
...
@@ -18,9 +19,11 @@ export default function useApiQuery<R extends keyof typeof RESOURCES>(
)
{
)
{
const
apiFetch
=
useApiFetch
();
const
apiFetch
=
useApiFetch
();
return
useQuery
<
unknown
,
ResourceError
,
ResourcePayload
<
R
>>
([
resource
],
async
()
=>
{
return
useQuery
<
unknown
,
ResourceError
,
ResourcePayload
<
R
>>
(
return
apiFetch
<
R
,
ResourcePayload
<
R
>
,
ResourceError
>
(
resource
,
{
pathParams
,
queryParams
,
fetchParams
});
pathParams
||
queryParams
?
[
resource
,
{
...
pathParams
,
...
queryParams
}
]
:
[
resource
],
},
queryOptions
);
async
()
=>
{
return
apiFetch
<
R
,
ResourcePayload
<
R
>
,
ResourceError
>
(
resource
,
{
pathParams
,
queryParams
,
fetchParams
});
},
queryOptions
);
}
}
export
type
ResourcePayload
<
Q
extends
keyof
typeof
RESOURCES
>
=
export
type
ResourcePayload
<
Q
extends
keyof
typeof
RESOURCES
>
=
...
@@ -32,4 +35,6 @@ export type ResourcePayload<Q extends keyof typeof RESOURCES> =
...
@@ -32,4 +35,6 @@ export type ResourcePayload<Q extends keyof typeof RESOURCES> =
Q
extends
'
private_tags_tx
'
?
TransactionTags
:
Q
extends
'
private_tags_tx
'
?
TransactionTags
:
Q
extends
'
api_keys
'
?
ApiKeys
:
Q
extends
'
api_keys
'
?
ApiKeys
:
Q
extends
'
watchlist
'
?
Array
<
WatchlistAddress
>
:
Q
extends
'
watchlist
'
?
Array
<
WatchlistAddress
>
:
never
;
Q
extends
'
stats_counters
'
?
Stats
:
Q
extends
'
stats_charts
'
?
Charts
:
never
;
lib/hooks/useFetch.tsx
View file @
a1f00dc6
...
@@ -9,6 +9,7 @@ import { resourceKey, RESOURCES } from 'lib/api/resources';
...
@@ -9,6 +9,7 @@ import { resourceKey, RESOURCES } from 'lib/api/resources';
export
interface
Params
{
export
interface
Params
{
method
?:
RequestInit
[
'
method
'
];
method
?:
RequestInit
[
'
method
'
];
headers
?:
RequestInit
[
'
headers
'
];
body
?:
Record
<
string
,
unknown
>
;
body
?:
Record
<
string
,
unknown
>
;
credentials
?:
RequestCredentials
;
credentials
?:
RequestCredentials
;
}
}
...
...
pages/api/proxy.ts
View file @
a1f00dc6
...
@@ -10,7 +10,7 @@ const handler = async(_req: NextApiRequest, res: NextApiResponse) => {
...
@@ -10,7 +10,7 @@ const handler = async(_req: NextApiRequest, res: NextApiResponse) => {
return
;
return
;
}
}
const
response
=
await
fetchFactory
(
_req
)(
const
response
=
await
fetchFactory
(
_req
,
_req
.
headers
[
'
x-endpoint
'
]?.
toString
()
)(
_req
.
url
.
replace
(
/^
\/
proxy/
,
''
),
_req
.
url
.
replace
(
/^
\/
proxy/
,
''
),
_pickBy
(
_pick
(
_req
,
[
'
body
'
,
'
method
'
]),
Boolean
),
_pickBy
(
_pick
(
_req
,
[
'
body
'
,
'
method
'
]),
Boolean
),
);
);
...
...
pages/api/stats/charts.ts
deleted
100644 → 0
View file @
64300957
import
type
{
NextApiRequest
}
from
'
next
'
;
import
appConfig
from
'
configs/app/config
'
;
import
handler
from
'
lib/api/handler
'
;
const
getUrl
=
(
req
:
NextApiRequest
)
=>
{
const
{
name
,
from
,
to
}
=
req
.
query
;
return
`/v1/charts/line?name=
${
name
}${
from
?
`&from=
${
from
}
&to=
${
to
}
`
:
''
}
`
;
};
const
requestHandler
=
handler
(
getUrl
,
[
'
GET
'
],
appConfig
.
statsApi
.
endpoint
);
export
default
requestHandler
;
pages/api/stats/counters.ts
deleted
100644 → 0
View file @
64300957
import
appConfig
from
'
configs/app/config
'
;
import
handler
from
'
lib/api/handler
'
;
const
getUrl
=
()
=>
'
/v1/counters
'
;
const
requestHandler
=
handler
(
getUrl
,
[
'
GET
'
],
appConfig
.
statsApi
.
endpoint
);
export
default
requestHandler
;
ui/stats/ChartWidgetContainer.tsx
View file @
a1f00dc6
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
Charts
}
from
'
types/api/stats
'
;
import
{
QueryKeys
}
from
'
types/client/queries
'
;
import
type
{
StatsIntervalIds
}
from
'
types/client/stats
'
;
import
type
{
StatsIntervalIds
}
from
'
types/client/stats
'
;
import
use
Fetch
from
'
lib/hooks/useFetch
'
;
import
use
ApiQuery
from
'
lib/api/useApiQuery
'
;
import
ChartWidget
from
'
../shared/chart/ChartWidget
'
;
import
ChartWidget
from
'
../shared/chart/ChartWidget
'
;
import
{
STATS_INTERVALS
}
from
'
./constants
'
;
import
{
STATS_INTERVALS
}
from
'
./constants
'
;
...
@@ -22,19 +19,18 @@ function formatDate(date: Date) {
...
@@ -22,19 +19,18 @@ function formatDate(date: Date) {
}
}
const
ChartWidgetContainer
=
({
id
,
title
,
description
,
interval
}:
Props
)
=>
{
const
ChartWidgetContainer
=
({
id
,
title
,
description
,
interval
}:
Props
)
=>
{
const
fetch
=
useFetch
();
const
selectedInterval
=
STATS_INTERVALS
[
interval
];
const
selectedInterval
=
STATS_INTERVALS
[
interval
];
const
endDate
=
selectedInterval
.
start
?
formatDate
(
new
Date
())
:
undefined
;
const
endDate
=
selectedInterval
.
start
?
formatDate
(
new
Date
())
:
undefined
;
const
startDate
=
selectedInterval
.
start
?
formatDate
(
selectedInterval
.
start
)
:
undefined
;
const
startDate
=
selectedInterval
.
start
?
formatDate
(
selectedInterval
.
start
)
:
undefined
;
const
url
=
`/node-api/stats/charts?name=
${
id
}${
startDate
?
`&from=
${
startDate
}
&to=
${
endDate
}
`
:
''
}
`
;
const
{
data
,
isLoading
}
=
useApiQuery
(
'
stats_charts
'
,
{
queryParams
:
{
const
{
data
,
isLoading
}
=
useQuery
<
unknown
,
unknown
,
Charts
>
(
name
:
id
,
[
QueryKeys
.
charts
,
id
,
startDate
],
from
:
startDate
,
async
()
=>
await
fetch
(
url
),
to
:
endDate
,
);
},
});
const
items
=
data
?.
chart
const
items
=
data
?.
chart
.
map
((
item
)
=>
{
.
map
((
item
)
=>
{
...
...
ui/stats/NumberWidgetsList.tsx
View file @
a1f00dc6
import
{
Grid
}
from
'
@chakra-ui/react
'
;
import
{
Grid
}
from
'
@chakra-ui/react
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
type
{
Stats
}
from
'
types/api/stats
'
;
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
QueryKeys
}
from
'
types/client/queries
'
;
import
useFetch
from
'
lib/hooks/useFetch
'
;
import
NumberWidget
from
'
./NumberWidget
'
;
import
NumberWidget
from
'
./NumberWidget
'
;
import
NumberWidgetSkeleton
from
'
./NumberWidgetSkeleton
'
;
import
NumberWidgetSkeleton
from
'
./NumberWidgetSkeleton
'
;
...
@@ -13,12 +9,7 @@ import NumberWidgetSkeleton from './NumberWidgetSkeleton';
...
@@ -13,12 +9,7 @@ import NumberWidgetSkeleton from './NumberWidgetSkeleton';
const
skeletonsCount
=
8
;
const
skeletonsCount
=
8
;
const
NumberWidgetsList
=
()
=>
{
const
NumberWidgetsList
=
()
=>
{
const
fetch
=
useFetch
();
const
{
data
,
isLoading
}
=
useApiQuery
(
'
stats_counters
'
);
const
{
data
,
isLoading
}
=
useQuery
<
unknown
,
unknown
,
Stats
>
(
[
QueryKeys
.
stats
],
async
()
=>
await
fetch
(
`/node-api/stats/counters`
),
);
return
(
return
(
<
Grid
<
Grid
...
...
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