@byline/admin 4.15.0 → 4.16.0
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/dist/abilities.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/modules/analytics/abilities.d.ts +14 -0
- package/dist/modules/analytics/abilities.js +21 -0
- package/dist/modules/analytics/components/dashboard.d.ts +20 -0
- package/dist/modules/analytics/components/dashboard.js +308 -0
- package/dist/modules/analytics/components/dashboard.module.js +29 -0
- package/dist/modules/analytics/components/dashboard.test.node.d.ts +8 -0
- package/dist/modules/analytics/components/dashboard_module.css +268 -0
- package/dist/modules/analytics/components/timeseries.d.ts +59 -0
- package/dist/modules/analytics/components/timeseries.js +253 -0
- package/dist/modules/analytics/components/timeseries.module.js +17 -0
- package/dist/modules/analytics/components/timeseries_module.css +126 -0
- package/dist/modules/analytics/index.d.ts +9 -0
- package/dist/modules/analytics/index.js +1 -0
- package/dist/modules/analytics/types.d.ts +20 -0
- package/dist/modules/analytics/types.js +1 -0
- package/package.json +17 -5
- package/src/abilities.ts +2 -0
- package/src/index.ts +1 -0
- package/src/modules/analytics/abilities.ts +33 -0
- package/src/modules/analytics/components/dashboard.module.css +330 -0
- package/src/modules/analytics/components/dashboard.test.node.ts +193 -0
- package/src/modules/analytics/components/dashboard.tsx +371 -0
- package/src/modules/analytics/components/timeseries.module.css +151 -0
- package/src/modules/analytics/components/timeseries.tsx +332 -0
- package/src/modules/analytics/index.ts +14 -0
- package/src/modules/analytics/types.ts +31 -0
package/dist/abilities.js
CHANGED
|
@@ -2,10 +2,12 @@ import { registerAdminActivityAbilities } from "./modules/admin-activity/abiliti
|
|
|
2
2
|
import { registerAdminPermissionsAbilities } from "./modules/admin-permissions/abilities.js";
|
|
3
3
|
import { registerAdminRolesAbilities } from "./modules/admin-roles/abilities.js";
|
|
4
4
|
import { registerAdminUsersAbilities } from "./modules/admin-users/abilities.js";
|
|
5
|
+
import { registerAnalyticsAbilities } from "./modules/analytics/abilities.js";
|
|
5
6
|
function registerAdminAbilities(registry) {
|
|
6
7
|
registerAdminUsersAbilities(registry);
|
|
7
8
|
registerAdminRolesAbilities(registry);
|
|
8
9
|
registerAdminPermissionsAbilities(registry);
|
|
9
10
|
registerAdminActivityAbilities(registry);
|
|
11
|
+
registerAnalyticsAbilities(registry);
|
|
10
12
|
}
|
|
11
13
|
export { registerAdminAbilities };
|
package/dist/index.d.ts
CHANGED
|
@@ -28,5 +28,6 @@ export * from './modules/admin-activity/index.js';
|
|
|
28
28
|
export * from './modules/admin-permissions/index.js';
|
|
29
29
|
export * from './modules/admin-roles/index.js';
|
|
30
30
|
export * from './modules/admin-users/index.js';
|
|
31
|
+
export * from './modules/analytics/index.js';
|
|
31
32
|
export * from './modules/auth/index.js';
|
|
32
33
|
export type { AdminStore } from './store.js';
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./modules/admin-activity/index.js";
|
|
|
3
3
|
export * from "./modules/admin-permissions/index.js";
|
|
4
4
|
export * from "./modules/admin-roles/index.js";
|
|
5
5
|
export * from "./modules/admin-users/index.js";
|
|
6
|
+
export * from "./modules/analytics/index.js";
|
|
6
7
|
export * from "./modules/auth/index.js";
|
|
7
8
|
export { registerAdminAbilities } from "./abilities.js";
|
|
8
9
|
export { assertAdminActor, requireAdminActor } from "./lib/assert-admin-actor.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import type { AbilityRegistry } from '@byline/auth';
|
|
9
|
+
export declare const ANALYTICS_ABILITIES: {
|
|
10
|
+
readonly read: 'analytics.read';
|
|
11
|
+
readonly maintain: 'analytics.maintain';
|
|
12
|
+
};
|
|
13
|
+
export type AnalyticsAbilityKey = (typeof ANALYTICS_ABILITIES)[keyof typeof ANALYTICS_ABILITIES];
|
|
14
|
+
export declare function registerAnalyticsAbilities(registry: AbilityRegistry): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const ANALYTICS_ABILITIES = {
|
|
2
|
+
read: 'analytics.read',
|
|
3
|
+
maintain: 'analytics.maintain'
|
|
4
|
+
};
|
|
5
|
+
function registerAnalyticsAbilities(registry) {
|
|
6
|
+
registry.register({
|
|
7
|
+
key: ANALYTICS_ABILITIES.read,
|
|
8
|
+
label: 'Read analytics',
|
|
9
|
+
description: 'View installation-level page, visitor, download, referrer, and country totals.',
|
|
10
|
+
group: 'analytics',
|
|
11
|
+
source: 'admin'
|
|
12
|
+
});
|
|
13
|
+
registry.register({
|
|
14
|
+
key: ANALYTICS_ABILITIES.maintain,
|
|
15
|
+
label: 'Maintain analytics',
|
|
16
|
+
description: 'Delete retained analytics events and rebuild affected daily aggregates.',
|
|
17
|
+
group: 'analytics',
|
|
18
|
+
source: 'admin'
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export { ANALYTICS_ABILITIES, registerAnalyticsAbilities };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
import type React from 'react';
|
|
9
|
+
import type { AnalyticsDashboardData, AnalyticsDashboardPeriod } from '../types.js';
|
|
10
|
+
export interface AnalyticsDashboardProps {
|
|
11
|
+
data: AnalyticsDashboardData;
|
|
12
|
+
period: AnalyticsDashboardPeriod;
|
|
13
|
+
onPeriodChange(period: AnalyticsDashboardPeriod): void;
|
|
14
|
+
}
|
|
15
|
+
export declare function AnalyticsDashboard({ data, period, onPeriodChange, }: AnalyticsDashboardProps): React.JSX.Element;
|
|
16
|
+
/** Never collapse the bar entirely: a visible sliver still encodes "smallest". */
|
|
17
|
+
export declare function shareWidth(value: number, ceiling: number): number;
|
|
18
|
+
export declare function formatShare(part: number, whole: number, locale: string): string;
|
|
19
|
+
/** Return the retained boundary only when it truncates the selected range. */
|
|
20
|
+
export declare function partialCoverageFrom(rangeFrom: string, coverageFrom: string | null): string | undefined;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { ANALYTICS_DASHBOARD_PERIODS, ANALYTICS_OVERFLOW_KEY, isAnalyticsDashboardPeriod } from "@byline/analytics/config";
|
|
5
|
+
import { ANALYTICS_IGNORE_STORAGE_KEY } from "@byline/analytics-agent";
|
|
6
|
+
import { useTranslation } from "@byline/i18n/react";
|
|
7
|
+
import { Button, Card, Container, Section, Select } from "@byline/ui/react";
|
|
8
|
+
import clsx from "clsx";
|
|
9
|
+
import dashboard_module from "./dashboard.module.js";
|
|
10
|
+
import { AnalyticsTimeseries, resolveAnalyticsChartGranularity } from "./timeseries.js";
|
|
11
|
+
function AnalyticsDashboard({ data, period, onPeriodChange }) {
|
|
12
|
+
const { locale, t } = useTranslation('byline-admin');
|
|
13
|
+
const [excluded, setExcluded] = useState(false);
|
|
14
|
+
const numbers = useMemo(()=>new Intl.NumberFormat(locale), [
|
|
15
|
+
locale
|
|
16
|
+
]);
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
try {
|
|
19
|
+
setExcluded(null != localStorage.getItem(ANALYTICS_IGNORE_STORAGE_KEY));
|
|
20
|
+
} catch {
|
|
21
|
+
setExcluded(false);
|
|
22
|
+
}
|
|
23
|
+
}, []);
|
|
24
|
+
const toggleExclusion = ()=>{
|
|
25
|
+
try {
|
|
26
|
+
if (excluded) localStorage.removeItem(ANALYTICS_IGNORE_STORAGE_KEY);
|
|
27
|
+
else localStorage.setItem(ANALYTICS_IGNORE_STORAGE_KEY, '1');
|
|
28
|
+
setExcluded(!excluded);
|
|
29
|
+
} catch {}
|
|
30
|
+
};
|
|
31
|
+
const periodItems = ANALYTICS_DASHBOARD_PERIODS.map((value)=>({
|
|
32
|
+
value: String(value),
|
|
33
|
+
label: 'number' == typeof value ? t('analytics.period.days', {
|
|
34
|
+
count: value
|
|
35
|
+
}) : t(`analytics.period.${value}`)
|
|
36
|
+
}));
|
|
37
|
+
const { views, visitors, downloads } = data.summary;
|
|
38
|
+
const days = data.summary.timeseries.length;
|
|
39
|
+
const chartGranularity = resolveAnalyticsChartGranularity(period, days);
|
|
40
|
+
return /*#__PURE__*/ jsx(Section, {
|
|
41
|
+
children: /*#__PURE__*/ jsxs(Container, {
|
|
42
|
+
children: [
|
|
43
|
+
/*#__PURE__*/ jsxs("header", {
|
|
44
|
+
className: clsx('byline-analytics-header', dashboard_module.header),
|
|
45
|
+
children: [
|
|
46
|
+
/*#__PURE__*/ jsxs("div", {
|
|
47
|
+
children: [
|
|
48
|
+
/*#__PURE__*/ jsx("h1", {
|
|
49
|
+
className: clsx('byline-analytics-title', dashboard_module.title),
|
|
50
|
+
children: t('analytics.title')
|
|
51
|
+
}),
|
|
52
|
+
/*#__PURE__*/ jsx("p", {
|
|
53
|
+
className: clsx('muted', 'byline-analytics-help', dashboard_module.help),
|
|
54
|
+
children: t('analytics.dailyUniquesHelp')
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
}),
|
|
58
|
+
/*#__PURE__*/ jsxs("div", {
|
|
59
|
+
className: clsx('byline-analytics-controls', dashboard_module.controls),
|
|
60
|
+
children: [
|
|
61
|
+
/*#__PURE__*/ jsx(Select, {
|
|
62
|
+
id: "analytics-period",
|
|
63
|
+
name: "analytics-period",
|
|
64
|
+
"aria-label": t('analytics.period.label'),
|
|
65
|
+
size: "sm",
|
|
66
|
+
value: String(period),
|
|
67
|
+
items: periodItems,
|
|
68
|
+
onValueChange: (value)=>{
|
|
69
|
+
const next = 'ytd' === value || 'all' === value ? value : Number(value);
|
|
70
|
+
if (isAnalyticsDashboardPeriod(next)) onPeriodChange(next);
|
|
71
|
+
}
|
|
72
|
+
}),
|
|
73
|
+
/*#__PURE__*/ jsx(Button, {
|
|
74
|
+
type: "button",
|
|
75
|
+
size: "sm",
|
|
76
|
+
"aria-pressed": excluded,
|
|
77
|
+
title: t('analytics.exclusion.help'),
|
|
78
|
+
onClick: toggleExclusion,
|
|
79
|
+
children: excluded ? t('analytics.exclusion.include') : t('analytics.exclusion.exclude')
|
|
80
|
+
})
|
|
81
|
+
]
|
|
82
|
+
})
|
|
83
|
+
]
|
|
84
|
+
}),
|
|
85
|
+
/*#__PURE__*/ jsxs("div", {
|
|
86
|
+
className: clsx('byline-analytics-stats', dashboard_module.stats),
|
|
87
|
+
children: [
|
|
88
|
+
/*#__PURE__*/ jsx(StatTile, {
|
|
89
|
+
tone: "views",
|
|
90
|
+
label: t('analytics.stats.views'),
|
|
91
|
+
value: numbers.format(views),
|
|
92
|
+
foot: t('analytics.stats.perDay', {
|
|
93
|
+
count: 0 === days ? 0 : Math.round(views / days)
|
|
94
|
+
})
|
|
95
|
+
}),
|
|
96
|
+
/*#__PURE__*/ jsx(StatTile, {
|
|
97
|
+
tone: "visitors",
|
|
98
|
+
label: t('analytics.stats.dailyUniques'),
|
|
99
|
+
value: numbers.format(visitors),
|
|
100
|
+
foot: t('analytics.stats.sumOfDays', {
|
|
101
|
+
count: days
|
|
102
|
+
})
|
|
103
|
+
}),
|
|
104
|
+
/*#__PURE__*/ jsx(StatTile, {
|
|
105
|
+
tone: "downloads",
|
|
106
|
+
label: t('analytics.stats.downloads'),
|
|
107
|
+
value: numbers.format(downloads),
|
|
108
|
+
foot: t('analytics.stats.shareOfViews', {
|
|
109
|
+
share: formatShare(downloads, views, locale)
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
]
|
|
113
|
+
}),
|
|
114
|
+
/*#__PURE__*/ jsxs(Card, {
|
|
115
|
+
className: clsx('byline-analytics-chart-card', dashboard_module.chartCard),
|
|
116
|
+
children: [
|
|
117
|
+
/*#__PURE__*/ jsx(Card.Header, {
|
|
118
|
+
children: /*#__PURE__*/ jsx(Card.Title, {
|
|
119
|
+
children: 'day' === chartGranularity ? t('analytics.chart.perDay') : 'seven-day' === chartGranularity ? t('analytics.chart.perSevenDays') : t('analytics.chart.perMonth')
|
|
120
|
+
})
|
|
121
|
+
}),
|
|
122
|
+
/*#__PURE__*/ jsx(Card.Content, {
|
|
123
|
+
children: /*#__PURE__*/ jsx(AnalyticsTimeseries, {
|
|
124
|
+
days: data.summary.timeseries,
|
|
125
|
+
granularity: chartGranularity,
|
|
126
|
+
locale: locale
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
}),
|
|
131
|
+
/*#__PURE__*/ jsxs("div", {
|
|
132
|
+
className: clsx('byline-analytics-lists', dashboard_module.lists),
|
|
133
|
+
children: [
|
|
134
|
+
/*#__PURE__*/ jsx(RankedList, {
|
|
135
|
+
title: t('analytics.sections.pages'),
|
|
136
|
+
caption: t('analytics.columns.viewsAndUniques'),
|
|
137
|
+
tone: "views",
|
|
138
|
+
locale: locale,
|
|
139
|
+
rows: data.pages.rows.map(toPathRow),
|
|
140
|
+
total: data.pages.total,
|
|
141
|
+
coverageFrom: partialCoverageFrom(data.range.from, data.coverage.pathsFrom)
|
|
142
|
+
}),
|
|
143
|
+
/*#__PURE__*/ jsxs("div", {
|
|
144
|
+
className: dashboard_module.stack,
|
|
145
|
+
children: [
|
|
146
|
+
/*#__PURE__*/ jsx(RankedList, {
|
|
147
|
+
title: t('analytics.sections.referrers'),
|
|
148
|
+
tone: "visitors",
|
|
149
|
+
locale: locale,
|
|
150
|
+
total: data.referrers.total,
|
|
151
|
+
coverageFrom: partialCoverageFrom(data.range.from, data.coverage.referrersFrom),
|
|
152
|
+
rows: data.referrers.rows.map((row)=>({
|
|
153
|
+
key: row.referrerHost,
|
|
154
|
+
label: row.referrerHost,
|
|
155
|
+
value: row.views,
|
|
156
|
+
visitors: row.visitors,
|
|
157
|
+
overflow: row.referrerHost === ANALYTICS_OVERFLOW_KEY
|
|
158
|
+
}))
|
|
159
|
+
}),
|
|
160
|
+
/*#__PURE__*/ jsx(RankedList, {
|
|
161
|
+
title: t('analytics.sections.countries'),
|
|
162
|
+
tone: "visitors",
|
|
163
|
+
locale: locale,
|
|
164
|
+
rows: data.countries.map((row)=>({
|
|
165
|
+
key: row.country,
|
|
166
|
+
label: row.country,
|
|
167
|
+
value: row.views,
|
|
168
|
+
visitors: row.visitors,
|
|
169
|
+
overflow: false
|
|
170
|
+
}))
|
|
171
|
+
})
|
|
172
|
+
]
|
|
173
|
+
})
|
|
174
|
+
]
|
|
175
|
+
}),
|
|
176
|
+
/*#__PURE__*/ jsx(RankedList, {
|
|
177
|
+
title: t('analytics.sections.downloads'),
|
|
178
|
+
caption: t('analytics.columns.clicksAndUniques'),
|
|
179
|
+
tone: "downloads",
|
|
180
|
+
locale: locale,
|
|
181
|
+
rows: data.downloads.rows.map(toPathRow),
|
|
182
|
+
total: data.downloads.total,
|
|
183
|
+
coverageFrom: partialCoverageFrom(data.range.from, data.coverage.pathsFrom)
|
|
184
|
+
})
|
|
185
|
+
]
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const TONE_TILE = {
|
|
190
|
+
views: dashboard_module.toneViews,
|
|
191
|
+
visitors: dashboard_module.toneVisitors,
|
|
192
|
+
downloads: dashboard_module.toneDownloads
|
|
193
|
+
};
|
|
194
|
+
const TONE_BAR = {
|
|
195
|
+
views: dashboard_module.barViews,
|
|
196
|
+
visitors: dashboard_module.barVisitors,
|
|
197
|
+
downloads: dashboard_module.barDownloads
|
|
198
|
+
};
|
|
199
|
+
function StatTile({ tone, label, value, foot }) {
|
|
200
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
201
|
+
className: clsx('byline-analytics-stat', dashboard_module.stat, TONE_TILE[tone]),
|
|
202
|
+
children: [
|
|
203
|
+
/*#__PURE__*/ jsx("span", {
|
|
204
|
+
className: clsx('byline-analytics-stat-label', dashboard_module.statLabel),
|
|
205
|
+
children: label
|
|
206
|
+
}),
|
|
207
|
+
/*#__PURE__*/ jsx("span", {
|
|
208
|
+
className: clsx('byline-analytics-stat-value', dashboard_module.statValue),
|
|
209
|
+
children: value
|
|
210
|
+
}),
|
|
211
|
+
/*#__PURE__*/ jsx("span", {
|
|
212
|
+
className: clsx('byline-analytics-stat-foot', dashboard_module.statFoot),
|
|
213
|
+
children: foot
|
|
214
|
+
})
|
|
215
|
+
]
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function toPathRow(row) {
|
|
219
|
+
return {
|
|
220
|
+
key: row.path,
|
|
221
|
+
label: row.path,
|
|
222
|
+
value: row.views,
|
|
223
|
+
visitors: row.visitors,
|
|
224
|
+
overflow: row.path === ANALYTICS_OVERFLOW_KEY
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function RankedList({ title, caption, rows, tone, locale, total, coverageFrom }) {
|
|
228
|
+
const { t } = useTranslation('byline-admin');
|
|
229
|
+
const numbers = useMemo(()=>new Intl.NumberFormat(locale), [
|
|
230
|
+
locale
|
|
231
|
+
]);
|
|
232
|
+
const ceiling = Math.max(1, ...rows.map((row)=>row.value));
|
|
233
|
+
const truncated = null != total && total > rows.length;
|
|
234
|
+
const coverageDate = useMemo(()=>new Intl.DateTimeFormat(locale, {
|
|
235
|
+
dateStyle: 'medium',
|
|
236
|
+
timeZone: 'UTC'
|
|
237
|
+
}), [
|
|
238
|
+
locale
|
|
239
|
+
]);
|
|
240
|
+
const description = [
|
|
241
|
+
truncated ? t('analytics.topOf', {
|
|
242
|
+
shown: rows.length,
|
|
243
|
+
total
|
|
244
|
+
}) : caption,
|
|
245
|
+
null == coverageFrom ? void 0 : t('analytics.coverage.since', {
|
|
246
|
+
date: coverageDate.format(new Date(`${coverageFrom}T00:00:00.000Z`))
|
|
247
|
+
})
|
|
248
|
+
].filter((value)=>null != value).join(' · ');
|
|
249
|
+
return /*#__PURE__*/ jsxs(Card, {
|
|
250
|
+
className: clsx('byline-analytics-list', dashboard_module.list),
|
|
251
|
+
children: [
|
|
252
|
+
/*#__PURE__*/ jsxs(Card.Header, {
|
|
253
|
+
children: [
|
|
254
|
+
/*#__PURE__*/ jsx(Card.Title, {
|
|
255
|
+
children: title
|
|
256
|
+
}),
|
|
257
|
+
description.length > 0 && /*#__PURE__*/ jsx(Card.Description, {
|
|
258
|
+
children: description
|
|
259
|
+
})
|
|
260
|
+
]
|
|
261
|
+
}),
|
|
262
|
+
/*#__PURE__*/ jsx(Card.Content, {
|
|
263
|
+
children: 0 === rows.length ? /*#__PURE__*/ jsx("p", {
|
|
264
|
+
className: "muted",
|
|
265
|
+
children: t('analytics.empty')
|
|
266
|
+
}) : /*#__PURE__*/ jsx("ol", {
|
|
267
|
+
className: clsx('byline-analytics-ranking', dashboard_module.ranking),
|
|
268
|
+
children: rows.map((row)=>/*#__PURE__*/ jsxs("li", {
|
|
269
|
+
className: clsx('byline-analytics-ranking-row', dashboard_module.rankingRow, TONE_BAR[tone], row.overflow && dashboard_module.rankingOverflow),
|
|
270
|
+
style: {
|
|
271
|
+
'--byline-analytics-share': `${shareWidth(row.value, ceiling)}%`
|
|
272
|
+
},
|
|
273
|
+
children: [
|
|
274
|
+
/*#__PURE__*/ jsx("span", {
|
|
275
|
+
className: dashboard_module.rankingLabel,
|
|
276
|
+
title: row.key,
|
|
277
|
+
children: row.overflow ? t('analytics.overflow') : row.label
|
|
278
|
+
}),
|
|
279
|
+
/*#__PURE__*/ jsx("span", {
|
|
280
|
+
className: dashboard_module.rankingValue,
|
|
281
|
+
children: numbers.format(row.value)
|
|
282
|
+
}),
|
|
283
|
+
/*#__PURE__*/ jsx("span", {
|
|
284
|
+
className: dashboard_module.rankingVisitors,
|
|
285
|
+
children: numbers.format(row.visitors)
|
|
286
|
+
})
|
|
287
|
+
]
|
|
288
|
+
}, row.key))
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
]
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
function shareWidth(value, ceiling) {
|
|
295
|
+
if (!Number.isFinite(value) || value <= 0 || ceiling <= 0) return 0;
|
|
296
|
+
return Math.max(3, Math.min(100, value / ceiling * 100));
|
|
297
|
+
}
|
|
298
|
+
function formatShare(part, whole, locale) {
|
|
299
|
+
const percent = new Intl.NumberFormat(locale, {
|
|
300
|
+
style: 'percent',
|
|
301
|
+
maximumFractionDigits: 1
|
|
302
|
+
});
|
|
303
|
+
return percent.format(whole <= 0 ? 0 : part / whole);
|
|
304
|
+
}
|
|
305
|
+
function partialCoverageFrom(rangeFrom, coverageFrom) {
|
|
306
|
+
return null != coverageFrom && coverageFrom > rangeFrom ? coverageFrom : void 0;
|
|
307
|
+
}
|
|
308
|
+
export { AnalyticsDashboard, formatShare, partialCoverageFrom, shareWidth };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import "./dashboard_module.css";
|
|
2
|
+
const dashboard_module = {
|
|
3
|
+
header: "header-zAoAGd",
|
|
4
|
+
title: "title-ZhxB2D",
|
|
5
|
+
help: "help-HT9JOI",
|
|
6
|
+
chartCard: "chartCard-NaXVMm",
|
|
7
|
+
list: "list-sR__nc",
|
|
8
|
+
controls: "controls-_Alpbi",
|
|
9
|
+
stats: "stats-u3kcTH",
|
|
10
|
+
stat: "stat-KhSBeS",
|
|
11
|
+
statLabel: "statLabel-X0_tdu",
|
|
12
|
+
statValue: "statValue-D32ine",
|
|
13
|
+
statFoot: "statFoot-yvtZiS",
|
|
14
|
+
toneViews: "toneViews-QGWabX",
|
|
15
|
+
toneVisitors: "toneVisitors-GTLZDo",
|
|
16
|
+
toneDownloads: "toneDownloads-WuDN7n",
|
|
17
|
+
lists: "lists-BLqFfy",
|
|
18
|
+
stack: "stack-Yzch8f",
|
|
19
|
+
ranking: "ranking-yfNSnw",
|
|
20
|
+
rankingRow: "rankingRow-CH1cHn",
|
|
21
|
+
barViews: "barViews-E6VuaR",
|
|
22
|
+
barVisitors: "barVisitors-eIANXw",
|
|
23
|
+
barDownloads: "barDownloads-Z50NxT",
|
|
24
|
+
rankingOverflow: "rankingOverflow-hUQMKU",
|
|
25
|
+
rankingLabel: "rankingLabel-wsuniC",
|
|
26
|
+
rankingValue: "rankingValue-i_vmgf",
|
|
27
|
+
rankingVisitors: "rankingVisitors-NZl_jj"
|
|
28
|
+
};
|
|
29
|
+
export default dashboard_module;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This Source Code is subject to the terms of the Mozilla Public
|
|
3
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) Infonomic Company Limited
|
|
7
|
+
*/
|
|
8
|
+
export {};
|