2024-07-06 20:57:32 -07:00
import dayjs from "dayjs" ;
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
import { ref , watch , computed } from "vue" ;
2024-07-03 13:05:14 -07:00
2023-12-26 14:46:32 -05:00
// note: build step can miss unix import for some reason, so
// we have to import it like this
2024-03-29 22:09:45 -07:00
2024-07-09 15:17:38 -07:00
const { unix } = dayjs ; // eslint-disable-line import/no-named-as-default-member
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
export function useCountryNames ( style = "long" ) {
const formattingOptions = { type : "region" , style } ;
const { formats } = useVIntl ( ) ;
2023-12-26 14:46:32 -05:00
return function formatCountryName ( code ) {
2024-07-06 20:57:32 -07:00
return formats . displayName ( code , formattingOptions ) ;
} ;
2023-12-26 14:46:32 -05:00
}
export const countryCodeToName = ( code ) => {
2024-07-06 20:57:32 -07:00
const formatCountryName = useCountryNames ( ) ;
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
return formatCountryName ( code ) ;
} ;
2023-12-26 14:46:32 -05:00
export const countryCodeToFlag = ( code ) => {
2024-07-06 20:57:32 -07:00
if ( code === "XX" ) {
return undefined ;
2023-12-26 14:46:32 -05:00
}
2024-07-06 20:57:32 -07:00
return ` https://flagcdn.com/h240/ ${ code . toLowerCase ( ) } .png ` ;
} ;
2023-12-26 14:46:32 -05:00
export const formatTimestamp = ( timestamp ) => {
2024-07-06 20:57:32 -07:00
return unix ( timestamp ) . format ( ) ;
} ;
2023-12-26 14:46:32 -05:00
export const formatPercent = ( value , sum ) => {
2024-07-06 20:57:32 -07:00
return ` ${ ( ( value / sum ) * 100 ) . toFixed ( 2 ) } % ` ;
} ;
2023-12-26 14:46:32 -05:00
2024-01-10 12:50:21 -08:00
const hashProjectId = ( projectId ) => {
2024-07-06 20:57:32 -07:00
return projectId . split ( "" ) . reduce ( ( acc , char ) => acc + char . charCodeAt ( 0 ) , 0 ) % 30 ;
} ;
2024-01-10 12:50:21 -08:00
2024-01-12 14:51:03 -08:00
export const defaultColors = [
2024-07-06 20:57:32 -07:00
"#ff496e" , // Original: Bright pink
"#ffa347" , // Original: Bright orange
"#1bd96a" , // Original: Bright green
"#4f9cff" , // Original: Bright blue
"#c78aff" , // Original: Bright purple
"#ffeb3b" , // Added: Bright yellow
"#00bcd4" , // Added: Bright cyan
"#ff5722" , // Added: Bright red-orange
"#9c27b0" , // Added: Bright deep purple
"#3f51b5" , // Added: Bright indigo
"#009688" , // Added: Bright teal
"#cddc39" , // Added: Bright lime
"#795548" , // Added: Bright brown
"#607d8b" , // Added: Bright blue-grey
] ;
2024-01-10 12:50:21 -08:00
/ * *
* @ param { string | number } value
* @ returns { string } color
* /
export const getDefaultColor = ( value ) => {
2024-07-06 20:57:32 -07:00
if ( typeof value === "string" ) {
value = hashProjectId ( value ) ;
2024-01-10 12:50:21 -08:00
}
2024-07-06 20:57:32 -07:00
return defaultColors [ value % defaultColors . length ] ;
} ;
2024-01-10 12:50:21 -08:00
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
export const intToRgba = ( color , projectId = "Unknown" , theme = "dark" , alpha = "1" ) => {
2024-07-06 20:57:32 -07:00
const hash = hashProjectId ( projectId ) ;
2024-01-10 12:50:21 -08:00
if ( ! color || color === 0 ) {
2024-07-06 20:57:32 -07:00
return getDefaultColor ( hash ) ;
2024-01-10 12:50:21 -08:00
}
// if color is a string, return that instead
2024-07-06 20:57:32 -07:00
if ( typeof color === "string" ) {
return color ;
2024-01-10 12:50:21 -08:00
}
2023-12-26 14:46:32 -05:00
// Extract RGB values
2024-07-06 20:57:32 -07:00
let r = ( color >> 16 ) & 255 ;
let g = ( color >> 8 ) & 255 ;
let b = color & 255 ;
2023-12-26 14:46:32 -05:00
// Hash function to alter color slightly based on project_id
2024-07-06 20:57:32 -07:00
r = ( r + hash ) % 256 ;
g = ( g + hash ) % 256 ;
b = ( b + hash ) % 256 ;
2023-12-26 14:46:32 -05:00
// Adjust brightness for theme
2024-07-06 20:57:32 -07:00
const brightness = r * 0.299 + g * 0.587 + b * 0.114 ;
const threshold = theme === "dark" ? 50 : 200 ;
if ( theme === "dark" && brightness < threshold ) {
2023-12-26 14:46:32 -05:00
// Increase brightness for dark theme
2024-07-06 20:57:32 -07:00
r += threshold / 2 ;
g += threshold / 2 ;
b += threshold / 2 ;
} else if ( theme === "light" && brightness > threshold ) {
2023-12-26 14:46:32 -05:00
// Decrease brightness for light theme
2024-07-06 20:57:32 -07:00
r -= threshold / 4 ;
g -= threshold / 4 ;
b -= threshold / 4 ;
2023-12-26 14:46:32 -05:00
}
// Ensure RGB values are within 0-255
2024-07-06 20:57:32 -07:00
r = Math . min ( 255 , Math . max ( 0 , r ) ) ;
g = Math . min ( 255 , Math . max ( 0 , g ) ) ;
b = Math . min ( 255 , Math . max ( 0 , b ) ) ;
2023-12-26 14:46:32 -05:00
Project, Search, User redesign (#1281)
* New project page
* fix silly icon tailwind classes
* Start new versions page, add new ButtonStyled component
* Pagination and finish mocking up versions page functionality
* green download button
* hover animation
* New Modal, Avatar refactor, subpages in NavTabs
* lint
* Download modal
* New user page + fix lint
* fix ui lint
* Download animation fix
* Versions filter + finish project page
* Improve consistency of buttons on home page
* Fix ButtonStyled breaking
* Fix margin on version summary
* finish search, new modals, user + project page mobile
* fix gallery image pages
* New project header
* Fix gallery tab showing improperly
* Use auto direction + position for all popouts
* Preliminary user page
* test to see if this fixes login stuff
* remove extra slash
* Add version actions, move download button on versions page
* Listed -> public
* Shorten download modal selector height
* Fix user menu open direction
* Change breakpoint for header collapse
* Only underline title
* Tighten padding on stats a little
* New nav
* Make mobile breakpoint more consistent
* fix header breakpoint regression
* Add sign in button
* Fix edit icon color
* Fix margin at top of screen
* Fix user bios and ad width
* Fix user nav showing when there's only one type of project
* Fix plural projects on user page & extract i18n
* Remove ads on mobile for now
* Fix overflow menu showing hidden items
* NavTabs on mobile
* Fix navbar z index
* Search filter overhaul + negative filters
* fix no-max-height
* port version filters, fix following/collections, lint
* hide promos
* ui lint
* Disable modal background animation to reduce reported motion sickness
* Hide install with modrinth app button on mobile
---------
Signed-off-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
Co-authored-by: Prospector <prospectordev@gmail.com>
2024-08-20 23:03:16 -07:00
return ` rgba( ${ r } , ${ g } , ${ b } , ${ alpha } ) ` ;
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
const emptyAnalytics = {
sum : 0 ,
len : 0 ,
chart : {
labels : [ ] ,
data : [ ] ,
sumData : [
{
2024-07-06 20:57:32 -07:00
name : "" ,
2023-12-26 14:46:32 -05:00
data : [ ] ,
} ,
] ,
colors : [ ] ,
2024-01-11 16:11:26 -08:00
defaultColors : [ ] ,
2023-12-26 14:46:32 -05:00
} ,
2024-01-12 14:51:03 -08:00
projectIds : [ ] ,
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
2024-01-10 12:50:21 -08:00
export const analyticsSetToCSVString = ( analytics ) => {
if ( ! analytics ) {
2024-07-06 20:57:32 -07:00
return "" ;
2024-01-10 12:50:21 -08:00
}
2024-07-06 20:57:32 -07:00
const newline = "\n" ;
const labels = analytics . chart . labels ;
const projects = analytics . chart . data ;
2024-01-10 12:50:21 -08:00
2024-07-06 20:57:32 -07:00
const projectNames = projects . map ( ( p ) => p . name ) ;
2024-01-10 12:50:21 -08:00
2024-07-06 20:57:32 -07:00
const header = [ "Date" , ... projectNames ] . join ( "," ) ;
2024-01-10 12:50:21 -08:00
const data = labels . map ( ( label , i ) => {
2024-07-06 20:57:32 -07:00
const values = projects . map ( ( p ) => p . data ? . [ i ] || "" ) ;
return [ label , ... values ] . join ( "," ) ;
} ) ;
2024-01-10 12:50:21 -08:00
2024-07-06 20:57:32 -07:00
return [ header , ... data ] . join ( newline ) ;
} ;
2024-01-10 12:50:21 -08:00
2024-07-31 21:42:55 +02:00
export const processAnalytics = ( category , projects , labelFn , sortFn , mapFn , chartName , theme ) => {
2023-12-26 14:46:32 -05:00
if ( ! category || ! projects ) {
2024-07-06 20:57:32 -07:00
return emptyAnalytics ;
2023-12-26 14:46:32 -05:00
}
// Get an intersection of category keys and project ids
2024-07-06 20:57:32 -07:00
const projectIds = projects . map ( ( p ) => p . id ) ;
const loadedProjectIds = Object . keys ( category ) . filter ( ( id ) => projectIds . includes ( id ) ) ;
2023-12-26 14:46:32 -05:00
if ( ! loadedProjectIds ? . length ) {
2024-07-06 20:57:32 -07:00
return emptyAnalytics ;
2023-12-26 14:46:32 -05:00
}
2024-07-06 20:57:32 -07:00
const loadedProjectData = loadedProjectIds . map ( ( id ) => category [ id ] ) ;
2023-12-26 14:46:32 -05:00
// Convert each project's data into a list of [unix_ts_str, number] pairs
const projectData = loadedProjectData
. map ( ( data ) => Object . entries ( data ) )
. map ( ( data ) => data . sort ( sortFn ) )
2024-07-06 20:57:32 -07:00
. map ( ( data ) => ( mapFn ? data . map ( mapFn ) : data ) ) ;
2023-12-26 14:46:32 -05:00
// Each project may not include the same timestamps, so we should use the union of all timestamps
const timestamps = Array . from (
2024-07-06 20:57:32 -07:00
new Set ( projectData . flatMap ( ( data ) => data . map ( ( [ ts ] ) => ts ) ) ) ,
) . sort ( ) ;
2023-12-26 14:46:32 -05:00
const chartData = projectData
. map ( ( data , i ) => {
2024-07-06 20:57:32 -07:00
const project = projects . find ( ( p ) => p . id === loadedProjectIds [ i ] ) ;
2023-12-26 14:46:32 -05:00
if ( ! project ) {
2024-07-06 20:57:32 -07:00
throw new Error ( ` Project ${ loadedProjectIds [ i ] } not found ` ) ;
2023-12-26 14:46:32 -05:00
}
return {
name : ` ${ project . title } ` ,
data : timestamps . map ( ( ts ) => {
2024-07-06 20:57:32 -07:00
const entry = data . find ( ( [ ets ] ) => ets === ts ) ;
return entry ? entry [ 1 ] : 0 ;
2023-12-26 14:46:32 -05:00
} ) ,
id : project . id ,
color : project . color ,
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
} )
. sort (
( a , b ) =>
2024-07-06 20:57:32 -07:00
b . data . reduce ( ( acc , cur ) => acc + cur , 0 ) - a . data . reduce ( ( acc , cur ) => acc + cur , 0 ) ,
) ;
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
const projectIdsSortedBySum = chartData . map ( ( p ) => p . id ) ;
2024-01-12 14:51:03 -08:00
2023-12-26 14:46:32 -05:00
return {
// The total count of all the values across all projects
sum : projectData . reduce ( ( acc , cur ) => acc + cur . reduce ( ( a , c ) => a + c [ 1 ] , 0 ) , 0 ) ,
len : timestamps . length ,
chart : {
labels : timestamps . map ( labelFn ) ,
data : chartData . map ( ( x ) => ( { name : x . name , data : x . data } ) ) ,
sumData : [
{
name : chartName ,
data : timestamps . map ( ( ts ) => {
2024-07-06 20:57:32 -07:00
const entries = projectData . flat ( ) . filter ( ( [ ets ] ) => ets === ts ) ;
return entries . reduce ( ( acc , cur ) => acc + cur [ 1 ] , 0 ) ;
2023-12-26 14:46:32 -05:00
} ) ,
} ,
] ,
colors : projectData . map ( ( _ , i ) => {
2024-07-06 20:57:32 -07:00
const project = chartData [ i ] ;
2023-12-26 14:46:32 -05:00
2024-07-31 21:42:55 +02:00
return intToRgba ( project . color , project . id , theme ) ;
2023-12-26 14:46:32 -05:00
} ) ,
2024-01-11 16:11:26 -08:00
defaultColors : projectData . map ( ( _ , i ) => {
2024-07-06 20:57:32 -07:00
const project = chartData [ i ] ;
return getDefaultColor ( project . id ) ;
2024-01-11 16:11:26 -08:00
} ) ,
2023-12-26 14:46:32 -05:00
} ,
2024-01-12 14:51:03 -08:00
projectIds : projectIdsSortedBySum ,
2024-07-06 20:57:32 -07:00
} ;
} ;
2023-12-26 14:46:32 -05:00
export const processAnalyticsByCountry = ( category , projects , sortFn ) => {
if ( ! category || ! projects ) {
return {
sum : 0 ,
len : 0 ,
data : [ ] ,
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
}
// Get an intersection of category keys and project ids
2024-07-06 20:57:32 -07:00
const projectIds = projects . map ( ( p ) => p . id ) ;
const loadedProjectIds = Object . keys ( category ) . filter ( ( id ) => projectIds . includes ( id ) ) ;
2023-12-26 14:46:32 -05:00
if ( ! loadedProjectIds ? . length ) {
return {
sum : 0 ,
len : 0 ,
data : [ ] ,
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
}
2024-07-06 20:57:32 -07:00
const loadedProjectData = loadedProjectIds . map ( ( id ) => category [ id ] ) ;
2023-12-26 14:46:32 -05:00
// Convert each project's data into a list of [countrycode, number] pairs
// Fold into a single list with summed values for each country over all projects
2024-07-06 20:57:32 -07:00
const countrySums = new Map ( ) ;
2023-12-26 14:46:32 -05:00
loadedProjectData . forEach ( ( data ) => {
Object . entries ( data ) . forEach ( ( [ country , value ] ) => {
2025-04-29 08:12:38 -07:00
const countryCode = country || "XX" ;
const current = countrySums . get ( countryCode ) || 0 ;
countrySums . set ( countryCode , current + value ) ;
2024-07-06 20:57:32 -07:00
} ) ;
} ) ;
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
const entries = Array . from ( countrySums . entries ( ) ) ;
2023-12-26 14:46:32 -05:00
return {
sum : entries . reduce ( ( acc , cur ) => acc + cur [ 1 ] , 0 ) ,
len : entries . length ,
data : entries . sort ( sortFn ) ,
2024-07-06 20:57:32 -07:00
} ;
} ;
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
const sortCount = ( [ _a , a ] , [ _b , b ] ) => b - a ;
const sortTimestamp = ( [ a ] , [ b ] ) => a - b ;
const roundValue = ( [ ts , value ] ) => [ ts , Math . round ( parseFloat ( value ) * 100 ) / 100 ] ;
2023-12-26 14:46:32 -05:00
2024-07-06 20:57:32 -07:00
const processCountryAnalytics = ( c , projects ) => processAnalyticsByCountry ( c , projects , sortCount ) ;
2024-07-31 21:42:55 +02:00
const processNumberAnalytics = ( c , projects , theme ) =>
processAnalytics ( c , projects , formatTimestamp , sortTimestamp , null , "Downloads" , theme ) ;
const processRevAnalytics = ( c , projects , theme ) =>
processAnalytics ( c , projects , formatTimestamp , sortTimestamp , roundValue , "Revenue" , theme ) ;
2023-12-26 14:46:32 -05:00
const useFetchAnalytics = (
url ,
baseOptions = {
apiVersion : 3 ,
2024-07-06 20:57:32 -07:00
} ,
2023-12-26 14:46:32 -05:00
) => {
2024-07-06 20:57:32 -07:00
return useBaseFetch ( url , baseOptions ) ;
} ;
2023-12-26 14:46:32 -05:00
/ * *
2024-01-10 12:50:21 -08:00
* @ param { Ref < any [ ] > } projects
2023-12-26 14:46:32 -05:00
* @ param { undefined | ( ) => any } onDataRefresh
* /
2024-01-12 14:51:03 -08:00
export const useFetchAllAnalytics = (
onDataRefresh ,
projects ,
selectedProjects ,
2024-07-06 20:57:32 -07:00
personalRevenue = false ,
2025-01-29 02:34:28 +00:00
startDate = ref ( dayjs ( ) . subtract ( 30 , "days" ) ) ,
endDate = ref ( dayjs ( ) ) ,
timeResolution = ref ( 1440 ) ,
2024-01-12 14:51:03 -08:00
) => {
2024-07-06 20:57:32 -07:00
const downloadData = ref ( null ) ;
const viewData = ref ( null ) ;
const revenueData = ref ( null ) ;
const downloadsByCountry = ref ( null ) ;
const viewsByCountry = ref ( null ) ;
const loading = ref ( true ) ;
const error = ref ( null ) ;
2023-12-26 14:46:32 -05:00
const formattedData = computed ( ( ) => ( {
2024-01-12 14:51:03 -08:00
downloads : processNumberAnalytics ( downloadData . value , selectedProjects . value ) ,
views : processNumberAnalytics ( viewData . value , selectedProjects . value ) ,
revenue : processRevAnalytics ( revenueData . value , selectedProjects . value ) ,
downloadsByCountry : processCountryAnalytics ( downloadsByCountry . value , selectedProjects . value ) ,
viewsByCountry : processCountryAnalytics ( viewsByCountry . value , selectedProjects . value ) ,
2024-07-06 20:57:32 -07:00
} ) ) ;
2024-01-12 14:51:03 -08:00
2024-07-31 21:42:55 +02:00
const theme = useTheme ( ) ;
2024-01-12 14:51:03 -08:00
const totalData = computed ( ( ) => ( {
2024-07-31 21:42:55 +02:00
downloads : processNumberAnalytics ( downloadData . value , projects . value , theme . active ) ,
views : processNumberAnalytics ( viewData . value , projects . value , theme . active ) ,
revenue : processRevAnalytics ( revenueData . value , projects . value , theme . active ) ,
2024-07-06 20:57:32 -07:00
} ) ) ;
2023-12-26 14:46:32 -05:00
const fetchData = async ( query ) => {
2024-07-06 20:57:32 -07:00
const normalQuery = new URLSearchParams ( query ) ;
const revenueQuery = new URLSearchParams ( query ) ;
2024-01-12 14:51:03 -08:00
if ( personalRevenue ) {
2024-07-06 20:57:32 -07:00
revenueQuery . delete ( "project_ids" ) ;
2024-01-12 14:51:03 -08:00
}
2024-07-06 20:57:32 -07:00
const qs = normalQuery . toString ( ) ;
const revenueQs = revenueQuery . toString ( ) ;
2023-12-26 14:46:32 -05:00
try {
2024-07-06 20:57:32 -07:00
loading . value = true ;
error . value = null ;
2023-12-26 14:46:32 -05:00
const responses = await Promise . all ( [
useFetchAnalytics ( ` analytics/downloads? ${ qs } ` ) ,
useFetchAnalytics ( ` analytics/views? ${ qs } ` ) ,
2024-01-11 16:11:26 -08:00
useFetchAnalytics ( ` analytics/revenue? ${ revenueQs } ` ) ,
2023-12-26 14:46:32 -05:00
useFetchAnalytics ( ` analytics/countries/downloads? ${ qs } ` ) ,
useFetchAnalytics ( ` analytics/countries/views? ${ qs } ` ) ,
2024-07-06 20:57:32 -07:00
] ) ;
2023-12-26 14:46:32 -05:00
2024-01-11 16:11:26 -08:00
// collect project ids from projects.value into a set
2024-07-06 20:57:32 -07:00
const projectIds = new Set ( ) ;
2024-01-12 14:51:03 -08:00
if ( projects . value ) {
2024-07-06 20:57:32 -07:00
projects . value . forEach ( ( p ) => projectIds . add ( p . id ) ) ;
2024-01-12 14:51:03 -08:00
} else {
// if projects.value is not set, we assume that we want all project ids
2024-07-06 20:57:32 -07:00
Object . keys ( responses [ 0 ] || { } ) . forEach ( ( id ) => projectIds . add ( id ) ) ;
2024-01-12 14:51:03 -08:00
}
2024-01-11 16:11:26 -08:00
const filterProjectIds = ( data ) => {
2024-07-06 20:57:32 -07:00
const filtered = { } ;
2024-01-11 16:11:26 -08:00
Object . entries ( data ) . forEach ( ( [ id , values ] ) => {
if ( projectIds . has ( id ) ) {
2024-07-06 20:57:32 -07:00
filtered [ id ] = values ;
2024-01-11 16:11:26 -08:00
}
2024-07-06 20:57:32 -07:00
} ) ;
return filtered ;
} ;
2024-01-11 16:11:26 -08:00
2024-07-06 20:57:32 -07:00
downloadData . value = filterProjectIds ( responses [ 0 ] || { } ) ;
viewData . value = filterProjectIds ( responses [ 1 ] || { } ) ;
revenueData . value = filterProjectIds ( responses [ 2 ] || { } ) ;
2024-01-11 16:11:26 -08:00
2024-07-06 20:57:32 -07:00
downloadsByCountry . value = responses [ 3 ] || { } ;
viewsByCountry . value = responses [ 4 ] || { } ;
2023-12-26 14:46:32 -05:00
} catch ( e ) {
2024-07-06 20:57:32 -07:00
error . value = e ;
2023-12-26 14:46:32 -05:00
} finally {
2024-07-06 20:57:32 -07:00
loading . value = false ;
2023-12-26 14:46:32 -05:00
}
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
watch (
2024-01-10 12:50:21 -08:00
[ ( ) => startDate . value , ( ) => endDate . value , ( ) => timeResolution . value , ( ) => projects . value ] ,
2023-12-26 14:46:32 -05:00
async ( ) => {
const q = {
2025-01-29 02:34:28 +00:00
start _date : startDate . value . toISOString ( ) ,
end _date : endDate . value . toISOString ( ) ,
2023-12-26 14:46:32 -05:00
resolution _minutes : timeResolution . value ,
2024-07-06 20:57:32 -07:00
} ;
2023-12-26 14:46:32 -05:00
2024-01-12 14:51:03 -08:00
if ( projects . value ? . length ) {
2024-07-06 20:57:32 -07:00
q . project _ids = JSON . stringify ( projects . value . map ( ( p ) => p . id ) ) ;
2023-12-26 14:46:32 -05:00
}
2024-07-06 20:57:32 -07:00
await fetchData ( q ) ;
2023-12-26 14:46:32 -05:00
if ( onDataRefresh ) {
2024-07-06 20:57:32 -07:00
onDataRefresh ( ) ;
2023-12-26 14:46:32 -05:00
}
} ,
{
immediate : true ,
2024-07-06 20:57:32 -07:00
} ,
) ;
2023-12-26 14:46:32 -05:00
2024-01-10 12:50:21 -08:00
const validProjectIds = computed ( ( ) => {
2024-07-06 20:57:32 -07:00
const ids = new Set ( ) ;
2024-01-10 12:50:21 -08:00
if ( downloadData . value ) {
2024-07-06 20:57:32 -07:00
Object . keys ( downloadData . value ) . forEach ( ( id ) => ids . add ( id ) ) ;
2024-01-10 12:50:21 -08:00
}
if ( viewData . value ) {
2024-07-06 20:57:32 -07:00
Object . keys ( viewData . value ) . forEach ( ( id ) => ids . add ( id ) ) ;
2024-01-10 12:50:21 -08:00
}
if ( revenueData . value ) {
2024-01-12 14:51:03 -08:00
// revenue will always have all project ids, but the ids may have an empty object or a ton of keys below a cent (0.00...) as values. We want to filter those out
2024-01-10 12:50:21 -08:00
Object . entries ( revenueData . value ) . forEach ( ( [ id , data ] ) => {
if ( Object . keys ( data ) . length ) {
2024-01-12 14:51:03 -08:00
if ( Object . values ( data ) . some ( ( v ) => v >= 0.01 ) ) {
2024-07-06 20:57:32 -07:00
ids . add ( id ) ;
2024-01-12 14:51:03 -08:00
}
2024-01-10 12:50:21 -08:00
}
2024-07-06 20:57:32 -07:00
} ) ;
2024-01-10 12:50:21 -08:00
}
2024-07-06 20:57:32 -07:00
return Array . from ( ids ) ;
} ) ;
2024-01-10 12:50:21 -08:00
2023-12-26 14:46:32 -05:00
return {
// Configuration
timeResolution ,
startDate ,
endDate ,
// Data
downloadData ,
viewData ,
revenueData ,
downloadsByCountry ,
viewsByCountry ,
// Computed state
2024-01-10 12:50:21 -08:00
validProjectIds ,
2023-12-26 14:46:32 -05:00
formattedData ,
2024-01-12 14:51:03 -08:00
totalData ,
2023-12-26 14:46:32 -05:00
loading ,
error ,
2024-07-06 20:57:32 -07:00
} ;
} ;