@gem-sdk/analytics 1.0.0-dev.21 → 1.0.0-dev.9
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/esm/components/index.d.ts +0 -3
- package/dist/esm/constants/breakdown-targets.d.ts +1 -1
- package/dist/esm/constants/index.d.ts +0 -1
- package/dist/esm/core/gemxql/builder/clauses/mode-query.d.ts +1 -1
- package/dist/esm/core/gemxql/builder/clauses/time-query.d.ts +1 -2
- package/dist/esm/core/gemxql/builder/helpers/date-query-helpers.d.ts +1 -1
- package/dist/esm/core/gemxql/helpers/extractQueryData.d.ts +1 -1
- package/dist/esm/core/gemxql/helpers/getTimeDimension.d.ts +1 -1
- package/dist/esm/core/gemxql/hooks/useAnalyticData.d.ts +1 -4
- package/dist/esm/core/gemxql/index.d.ts +6 -3
- package/dist/esm/core/gemxql/types/analytic-mode.d.ts +5 -0
- package/dist/esm/core/gemxql/types/date-filter.d.ts +10 -0
- package/dist/esm/core/gemxql/types/index.d.ts +3 -0
- package/dist/esm/{utils → core/gemxql/utils}/analytics.d.ts +1 -0
- package/dist/esm/{utils → core/gemxql/utils}/dayjs.d.ts +0 -2
- package/dist/esm/gemxql.js +205 -347
- package/dist/esm/gemxql.mjs +205 -347
- package/dist/esm/hooks/index.d.ts +1 -3
- package/dist/esm/index.d.ts +2 -4
- package/dist/esm/index.js +467 -2133
- package/dist/esm/index.mjs +467 -2133
- package/dist/esm/providers/index.d.ts +0 -2
- package/dist/esm/shared/charts/components/GPolarisViz/components/ChartErrorBoundary/ChartErrorBoundary.d.ts +1 -1
- package/dist/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getDonutChartTooltipPosition.d.ts +1 -1
- package/dist/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getLineChartTooltipPosition.d.ts +1 -1
- package/dist/esm/shared/components/index.d.ts +0 -11
- package/dist/esm/types/index.d.ts +0 -3
- package/dist/esm/types.js +1 -31
- package/dist/esm/types.mjs +1 -31
- package/dist/esm/utils/index.d.ts +0 -3
- package/dist/style.css +1 -1
- package/dist/umd/esm/components/index.d.ts +0 -3
- package/dist/umd/esm/constants/breakdown-targets.d.ts +1 -1
- package/dist/umd/esm/constants/index.d.ts +0 -1
- package/dist/umd/esm/core/gemxql/builder/clauses/mode-query.d.ts +1 -1
- package/dist/umd/esm/core/gemxql/builder/clauses/time-query.d.ts +1 -2
- package/dist/umd/esm/core/gemxql/builder/helpers/date-query-helpers.d.ts +1 -1
- package/dist/umd/esm/core/gemxql/helpers/extractQueryData.d.ts +1 -1
- package/dist/umd/esm/core/gemxql/helpers/getTimeDimension.d.ts +1 -1
- package/dist/umd/esm/core/gemxql/hooks/useAnalyticData.d.ts +1 -4
- package/dist/umd/esm/core/gemxql/index.d.ts +6 -3
- package/dist/umd/esm/core/gemxql/types/analytic-mode.d.ts +5 -0
- package/dist/umd/esm/core/gemxql/types/date-filter.d.ts +10 -0
- package/dist/umd/esm/core/gemxql/types/index.d.ts +3 -0
- package/dist/umd/esm/{utils → core/gemxql/utils}/analytics.d.ts +1 -0
- package/dist/umd/esm/{utils → core/gemxql/utils}/dayjs.d.ts +0 -2
- package/dist/umd/esm/hooks/index.d.ts +1 -3
- package/dist/umd/esm/index.d.ts +2 -4
- package/dist/umd/esm/providers/index.d.ts +0 -2
- package/dist/umd/esm/shared/charts/components/GPolarisViz/components/ChartErrorBoundary/ChartErrorBoundary.d.ts +1 -1
- package/dist/umd/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getDonutChartTooltipPosition.d.ts +1 -1
- package/dist/umd/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getLineChartTooltipPosition.d.ts +1 -1
- package/dist/umd/esm/shared/components/index.d.ts +0 -11
- package/dist/umd/esm/types/index.d.ts +0 -3
- package/dist/umd/esm/utils/index.d.ts +0 -3
- package/dist/umd/gemxql.js +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/types.js +1 -1
- package/package.json +2 -5
- package/dist/esm/components/AnalyticMode/AnalyticModeSelector.d.ts +0 -13
- package/dist/esm/components/AnalyticMode/index.d.ts +0 -2
- package/dist/esm/components/CurrencySelector/CurrencySelector.d.ts +0 -10
- package/dist/esm/components/CurrencySelector/index.d.ts +0 -2
- package/dist/esm/components/GTimePicker/GTimePicker.d.ts +0 -17
- package/dist/esm/components/GTimePicker/components/BaseTimePicker.d.ts +0 -10
- package/dist/esm/components/GTimePicker/components/CompareTimePicker.d.ts +0 -5
- package/dist/esm/components/GTimePicker/components/DateTimeFilterAddition.d.ts +0 -2
- package/dist/esm/components/GTimePicker/components/DateTimeFilterInputs.d.ts +0 -9
- package/dist/esm/components/GTimePicker/components/DateTimeFilters.d.ts +0 -15
- package/dist/esm/components/GTimePicker/components/MainTimePicker.d.ts +0 -3
- package/dist/esm/components/GTimePicker/components/index.d.ts +0 -2
- package/dist/esm/components/GTimePicker/constants/compareDateTimePicker.d.ts +0 -12
- package/dist/esm/components/GTimePicker/constants/datePicker.d.ts +0 -14
- package/dist/esm/components/GTimePicker/constants/index.d.ts +0 -2
- package/dist/esm/components/GTimePicker/constants/mainDataTimePicker.d.ts +0 -14
- package/dist/esm/components/GTimePicker/contexts/DateTimePickerProvider.d.ts +0 -15
- package/dist/esm/components/GTimePicker/contexts/index.d.ts +0 -1
- package/dist/esm/components/GTimePicker/helpers/date-range-info.d.ts +0 -16
- package/dist/esm/components/GTimePicker/helpers/index.d.ts +0 -4
- package/dist/esm/components/GTimePicker/helpers/parse-date.d.ts +0 -24
- package/dist/esm/components/GTimePicker/helpers/time-picker.d.ts +0 -76
- package/dist/esm/components/GTimePicker/helpers/version.d.ts +0 -2
- package/dist/esm/components/GTimePicker/hooks/index.d.ts +0 -3
- package/dist/esm/components/GTimePicker/hooks/useCompareDateTimePicker.d.ts +0 -25
- package/dist/esm/components/GTimePicker/hooks/useDateTimeFilter.d.ts +0 -18
- package/dist/esm/components/GTimePicker/hooks/useDateTimePicker.d.ts +0 -30
- package/dist/esm/components/GTimePicker/hooks/useVersionDateTimeFilters.d.ts +0 -9
- package/dist/esm/components/GTimePicker/index.d.ts +0 -7
- package/dist/esm/components/GTimePicker/types/index.d.ts +0 -38
- package/dist/esm/constants/currency.d.ts +0 -2
- package/dist/esm/hooks/publish/index.d.ts +0 -2
- package/dist/esm/hooks/publish/useStickyDetectById.d.ts +0 -8
- package/dist/esm/hooks/publish/useStickyFilterBoxProps.d.ts +0 -6
- package/dist/esm/hooks/useFetchCurrencyRates.d.ts +0 -1
- package/dist/esm/hooks/useToggle.d.ts +0 -12
- package/dist/esm/providers/ConvertMoneyProvider.d.ts +0 -13
- package/dist/esm/shared/components/GActivatorPopover/GActivatorPopover.d.ts +0 -23
- package/dist/esm/shared/components/GActivatorPopover/index.d.ts +0 -1
- package/dist/esm/shared/components/GButton/GButton.d.ts +0 -19
- package/dist/esm/shared/components/GButton/index.d.ts +0 -1
- package/dist/esm/shared/components/GCheckbox/GCheckbox.d.ts +0 -39
- package/dist/esm/shared/components/GCheckbox/index.d.ts +0 -1
- package/dist/esm/shared/components/GChoice/ChoiceHelpText.d.ts +0 -4
- package/dist/esm/shared/components/GChoice/GChoice.d.ts +0 -44
- package/dist/esm/shared/components/GChoice/index.d.ts +0 -2
- package/dist/esm/shared/components/GClickable/GClickable.d.ts +0 -10
- package/dist/esm/shared/components/GClickable/index.d.ts +0 -1
- package/dist/esm/shared/components/GDiv/GDiv.d.ts +0 -7
- package/dist/esm/shared/components/GDiv/index.d.ts +0 -1
- package/dist/esm/shared/components/GI18NText/GI18NText.d.ts +0 -2
- package/dist/esm/shared/components/GI18NText/index.d.ts +0 -2
- package/dist/esm/shared/components/GI18NText/types.d.ts +0 -6
- package/dist/esm/shared/components/GOptionList/GOptionList.d.ts +0 -11
- package/dist/esm/shared/components/GOptionList/index.d.ts +0 -1
- package/dist/esm/shared/components/GSelector/GSelector.d.ts +0 -27
- package/dist/esm/shared/components/GSelector/index.d.ts +0 -1
- package/dist/esm/shared/components/GTextLink/GTextLink.d.ts +0 -9
- package/dist/esm/shared/components/GTextLink/index.d.ts +0 -1
- package/dist/esm/shared/components/GViewBySelector/GViewBySelector.d.ts +0 -17
- package/dist/esm/shared/components/GViewBySelector/index.d.ts +0 -1
- package/dist/esm/stores/currencyRatesStore.d.ts +0 -7
- package/dist/esm/stores/index.d.ts +0 -2
- package/dist/esm/types/analytic-mode.d.ts +0 -5
- package/dist/esm/types/currency.d.ts +0 -329
- package/dist/esm/utils/currency.d.ts +0 -5
- package/dist/esm/utils/sort.d.ts +0 -13
- package/dist/umd/esm/components/AnalyticMode/AnalyticModeSelector.d.ts +0 -13
- package/dist/umd/esm/components/AnalyticMode/index.d.ts +0 -2
- package/dist/umd/esm/components/CurrencySelector/CurrencySelector.d.ts +0 -10
- package/dist/umd/esm/components/CurrencySelector/index.d.ts +0 -2
- package/dist/umd/esm/components/GTimePicker/GTimePicker.d.ts +0 -17
- package/dist/umd/esm/components/GTimePicker/components/BaseTimePicker.d.ts +0 -10
- package/dist/umd/esm/components/GTimePicker/components/CompareTimePicker.d.ts +0 -5
- package/dist/umd/esm/components/GTimePicker/components/DateTimeFilterAddition.d.ts +0 -2
- package/dist/umd/esm/components/GTimePicker/components/DateTimeFilterInputs.d.ts +0 -9
- package/dist/umd/esm/components/GTimePicker/components/DateTimeFilters.d.ts +0 -15
- package/dist/umd/esm/components/GTimePicker/components/MainTimePicker.d.ts +0 -3
- package/dist/umd/esm/components/GTimePicker/components/index.d.ts +0 -2
- package/dist/umd/esm/components/GTimePicker/constants/compareDateTimePicker.d.ts +0 -12
- package/dist/umd/esm/components/GTimePicker/constants/datePicker.d.ts +0 -14
- package/dist/umd/esm/components/GTimePicker/constants/index.d.ts +0 -2
- package/dist/umd/esm/components/GTimePicker/constants/mainDataTimePicker.d.ts +0 -14
- package/dist/umd/esm/components/GTimePicker/contexts/DateTimePickerProvider.d.ts +0 -15
- package/dist/umd/esm/components/GTimePicker/contexts/index.d.ts +0 -1
- package/dist/umd/esm/components/GTimePicker/helpers/date-range-info.d.ts +0 -16
- package/dist/umd/esm/components/GTimePicker/helpers/index.d.ts +0 -4
- package/dist/umd/esm/components/GTimePicker/helpers/parse-date.d.ts +0 -24
- package/dist/umd/esm/components/GTimePicker/helpers/time-picker.d.ts +0 -76
- package/dist/umd/esm/components/GTimePicker/helpers/version.d.ts +0 -2
- package/dist/umd/esm/components/GTimePicker/hooks/index.d.ts +0 -3
- package/dist/umd/esm/components/GTimePicker/hooks/useCompareDateTimePicker.d.ts +0 -25
- package/dist/umd/esm/components/GTimePicker/hooks/useDateTimeFilter.d.ts +0 -18
- package/dist/umd/esm/components/GTimePicker/hooks/useDateTimePicker.d.ts +0 -30
- package/dist/umd/esm/components/GTimePicker/hooks/useVersionDateTimeFilters.d.ts +0 -9
- package/dist/umd/esm/components/GTimePicker/index.d.ts +0 -7
- package/dist/umd/esm/components/GTimePicker/types/index.d.ts +0 -38
- package/dist/umd/esm/constants/currency.d.ts +0 -2
- package/dist/umd/esm/hooks/publish/index.d.ts +0 -2
- package/dist/umd/esm/hooks/publish/useStickyDetectById.d.ts +0 -8
- package/dist/umd/esm/hooks/publish/useStickyFilterBoxProps.d.ts +0 -6
- package/dist/umd/esm/hooks/useFetchCurrencyRates.d.ts +0 -1
- package/dist/umd/esm/hooks/useToggle.d.ts +0 -12
- package/dist/umd/esm/providers/ConvertMoneyProvider.d.ts +0 -13
- package/dist/umd/esm/shared/components/GActivatorPopover/GActivatorPopover.d.ts +0 -23
- package/dist/umd/esm/shared/components/GActivatorPopover/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GButton/GButton.d.ts +0 -19
- package/dist/umd/esm/shared/components/GButton/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GCheckbox/GCheckbox.d.ts +0 -39
- package/dist/umd/esm/shared/components/GCheckbox/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GChoice/ChoiceHelpText.d.ts +0 -4
- package/dist/umd/esm/shared/components/GChoice/GChoice.d.ts +0 -44
- package/dist/umd/esm/shared/components/GChoice/index.d.ts +0 -2
- package/dist/umd/esm/shared/components/GClickable/GClickable.d.ts +0 -10
- package/dist/umd/esm/shared/components/GClickable/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GDiv/GDiv.d.ts +0 -7
- package/dist/umd/esm/shared/components/GDiv/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GI18NText/GI18NText.d.ts +0 -2
- package/dist/umd/esm/shared/components/GI18NText/index.d.ts +0 -2
- package/dist/umd/esm/shared/components/GI18NText/types.d.ts +0 -6
- package/dist/umd/esm/shared/components/GOptionList/GOptionList.d.ts +0 -11
- package/dist/umd/esm/shared/components/GOptionList/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GSelector/GSelector.d.ts +0 -27
- package/dist/umd/esm/shared/components/GSelector/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GTextLink/GTextLink.d.ts +0 -9
- package/dist/umd/esm/shared/components/GTextLink/index.d.ts +0 -1
- package/dist/umd/esm/shared/components/GViewBySelector/GViewBySelector.d.ts +0 -17
- package/dist/umd/esm/shared/components/GViewBySelector/index.d.ts +0 -1
- package/dist/umd/esm/stores/currencyRatesStore.d.ts +0 -7
- package/dist/umd/esm/stores/index.d.ts +0 -2
- package/dist/umd/esm/types/analytic-mode.d.ts +0 -5
- package/dist/umd/esm/types/currency.d.ts +0 -329
- package/dist/umd/esm/utils/currency.d.ts +0 -5
- package/dist/umd/esm/utils/sort.d.ts +0 -13
- /package/dist/esm/{types → core/gemxql/types}/breakdown-items.d.ts +0 -0
- /package/dist/esm/hooks/{publish/useWindowSize.d.ts → useWindowSize.d.ts} +0 -0
- /package/dist/umd/esm/{types → core/gemxql/types}/breakdown-items.d.ts +0 -0
- /package/dist/umd/esm/hooks/{publish/useWindowSize.d.ts → useWindowSize.d.ts} +0 -0
package/dist/esm/index.mjs
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import
|
|
4
|
-
import React, { useMemo, useCallback, useState, useEffect, forwardRef, Fragment as Fragment$1, useRef, useImperativeHandle, createContext, useContext } from 'react';
|
|
3
|
+
import '@tanstack/react-query';
|
|
5
4
|
import dayjs from 'dayjs';
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import { create } from 'zustand';
|
|
12
|
-
import { useQuery } from '@tanstack/react-query';
|
|
5
|
+
import quarterOfYear from 'dayjs/plugin/quarterOfYear';
|
|
6
|
+
import timezone from 'dayjs/plugin/timezone';
|
|
7
|
+
import utc from 'dayjs/plugin/utc';
|
|
8
|
+
import React, { useMemo, forwardRef, useState, useRef, useImperativeHandle, useEffect } from 'react';
|
|
9
|
+
import { Box, SkeletonDisplayText, Popover, InlineStack, BlockStack, Text, List, Card, SkeletonBodyText, Icon } from '@shopify/polaris';
|
|
13
10
|
import { PolarisVizProvider, LineChart, DonutChart } from '@shopify/polaris-viz';
|
|
14
|
-
import chartStyle from '@shopify/polaris-viz/build/esm/styles.css?url';
|
|
15
11
|
|
|
16
12
|
var EMetricKey;
|
|
17
13
|
(function (EMetricKey) {
|
|
@@ -127,895 +123,8 @@ const ANALYTICS_METRIC_TOOLTIP = {
|
|
|
127
123
|
},
|
|
128
124
|
};
|
|
129
125
|
|
|
130
|
-
var EAnalyticMode;
|
|
131
|
-
(function (EAnalyticMode) {
|
|
132
|
-
EAnalyticMode["ALL_SESSION"] = "ALL_SESSION";
|
|
133
|
-
EAnalyticMode["FIRST_SESSION"] = "FIRST_SESSION";
|
|
134
|
-
EAnalyticMode["PAGE_ONLY"] = "PAGE_ONLY";
|
|
135
|
-
})(EAnalyticMode || (EAnalyticMode = {}));
|
|
136
|
-
|
|
137
|
-
var EVisitorType;
|
|
138
|
-
(function (EVisitorType) {
|
|
139
|
-
EVisitorType["NEW"] = "new";
|
|
140
|
-
EVisitorType["RETURNING"] = "returning";
|
|
141
|
-
})(EVisitorType || (EVisitorType = {}));
|
|
142
|
-
var EDeviceType;
|
|
143
|
-
(function (EDeviceType) {
|
|
144
|
-
EDeviceType["DESKTOP"] = "desktop";
|
|
145
|
-
EDeviceType["MOBILE"] = "mobile";
|
|
146
|
-
EDeviceType["TABLET"] = "tablet";
|
|
147
|
-
})(EDeviceType || (EDeviceType = {}));
|
|
148
|
-
var ETrafficSourceType;
|
|
149
|
-
(function (ETrafficSourceType) {
|
|
150
|
-
ETrafficSourceType["DIRECT"] = "direct";
|
|
151
|
-
ETrafficSourceType["EMAIL"] = "email";
|
|
152
|
-
ETrafficSourceType["REFERRAL"] = "referral";
|
|
153
|
-
ETrafficSourceType["ORGANIC_SOCIAL"] = "organic-social";
|
|
154
|
-
ETrafficSourceType["ORGANIC_SEARCH"] = "organic-search";
|
|
155
|
-
ETrafficSourceType["PAID_SOCIAL"] = "paid-social";
|
|
156
|
-
ETrafficSourceType["PAID_SEARCH"] = "paid-search";
|
|
157
|
-
ETrafficSourceType["SMS"] = "sms";
|
|
158
|
-
})(ETrafficSourceType || (ETrafficSourceType = {}));
|
|
159
|
-
|
|
160
|
-
const TARGET_VISITOR = [
|
|
161
|
-
{ value: EVisitorType.NEW, label: 'New' },
|
|
162
|
-
{ value: EVisitorType.RETURNING, label: 'Returning' },
|
|
163
|
-
];
|
|
164
|
-
const TARGET_DEVICES = [
|
|
165
|
-
{ value: EDeviceType.DESKTOP, label: 'Desktop' },
|
|
166
|
-
{ value: EDeviceType.TABLET, label: 'Tablet' },
|
|
167
|
-
{ value: EDeviceType.MOBILE, label: 'Mobile' },
|
|
168
|
-
];
|
|
169
|
-
const TARGET_CHANNEL = [
|
|
170
|
-
{ value: ETrafficSourceType.DIRECT, label: 'Direct' },
|
|
171
|
-
{ value: ETrafficSourceType.EMAIL, label: 'Email' },
|
|
172
|
-
{ value: ETrafficSourceType.REFERRAL, label: 'Referral' },
|
|
173
|
-
{ value: ETrafficSourceType.ORGANIC_SOCIAL, label: 'Organic social' },
|
|
174
|
-
{ value: ETrafficSourceType.ORGANIC_SEARCH, label: 'Organic search' },
|
|
175
|
-
{ value: ETrafficSourceType.PAID_SOCIAL, label: 'Paid social' },
|
|
176
|
-
{ value: ETrafficSourceType.PAID_SEARCH, label: 'Paid search' },
|
|
177
|
-
{ value: ETrafficSourceType.SMS, label: 'SMS' },
|
|
178
|
-
];
|
|
179
|
-
|
|
180
|
-
const CAMPAIGN_BACKGROUND_MAIN = {
|
|
181
|
-
ORIGIN: '#2C7DFF',
|
|
182
|
-
VARIANT: '#F34A70',
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const DEFAULT_CURRENT_PERIOD_LABEL = 'Current';
|
|
186
|
-
const DEFAULT_PREVIOUS_PERIOD_LABEL = 'Previous';
|
|
187
|
-
const CHART_MIN_HEIGHT = 228;
|
|
188
|
-
const SERIES_COLORS = {
|
|
189
|
-
current: 'rgba(64, 176, 230, 1)',
|
|
190
|
-
comparison: 'rgba(161, 202, 231, 1)',
|
|
191
|
-
all: ['#2C7DFF', '#F34A70'],
|
|
192
|
-
};
|
|
193
|
-
const TREND_TONE = {
|
|
194
|
-
POSITIVE: '#007F5F',
|
|
195
|
-
NEUTRAL: '#4A4A4A',
|
|
196
|
-
};
|
|
197
|
-
const PLACEHOLDER_VALUE$1 = '-';
|
|
198
|
-
|
|
199
|
-
const DEFAULT_CURRENCY_ANALYTIC = 'USD';
|
|
200
|
-
|
|
201
|
-
var THUMB_PRODUCT_DEFAULT = "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSI5MCIKICBoZWlnaHQ9IjcyIgogIHZpZXdCb3g9IjAgMCA5MCA3MiIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNDguNzUgMzQuNUM0OS45OTI2IDM0LjUgNTEgMzMuNDkyNiA1MSAzMi4yNUM1MSAzMS4wMDc0IDQ5Ljk5MjYgMzAgNDguNzUgMzBDNDcuNTA3NCAzMCA0Ni41IDMxLjAwNzQgNDYuNSAzMi4yNUM0Ni41IDMzLjQ5MjYgNDcuNTA3NCAzNC41IDQ4Ljc1IDM0LjVaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgogIDxwYXRoCiAgICBmaWxsUnVsZT0iZXZlbm9kZCIKICAgIGNsaXBSdWxlPSJldmVub2RkIgogICAgZD0iTTQzLjUyNjggMjYuMjVINDYuNDczMkM0Ny42OTI0IDI2LjI1IDQ4LjY3NTggMjYuMjUgNDkuNDcyMiAyNi4zMTVDNTAuMjkyMiAyNi4zODIgNTEuMDEyNCAyNi41MjM2IDUxLjY3ODcgMjYuODYzMUM1Mi43MzcxIDI3LjQwMjQgNTMuNTk3NiAyOC4yNjI5IDU0LjEzNjkgMjkuMzIxM0M1NC40NzY0IDI5Ljk4NzYgNTQuNjE4IDMwLjcwNzggNTQuNjg1IDMxLjUyNzhDNTQuNzUgMzIuMzI0MiA1NC43NSAzMy4zMDc2IDU0Ljc1IDM0LjUyNjhWMzcuNDczMkM1NC43NSAzOC42OTI0IDU0Ljc1IDM5LjY3NTggNTQuNjg1IDQwLjQ3MjJDNTQuNjE4IDQxLjI5MjIgNTQuNDc2NCA0Mi4wMTI0IDU0LjEzNjkgNDIuNjc4N0M1My41OTc2IDQzLjczNzEgNTIuNzM3MSA0NC41OTc2IDUxLjY3ODcgNDUuMTM2OUM1MS4wMTI0IDQ1LjQ3NjQgNTAuMjkyMiA0NS42MTggNDkuNDcyMiA0NS42ODVDNDguNjc1OCA0NS43NSA0Ny42OTI0IDQ1Ljc1IDQ2LjQ3MzIgNDUuNzVINDMuNTI2OEM0Mi4zMDc2IDQ1Ljc1IDQxLjMyNDIgNDUuNzUgNDAuNTI3OCA0NS42ODVDMzkuNzA3OCA0NS42MTggMzguOTg3NiA0NS40NzY0IDM4LjMyMTMgNDUuMTM2OUMzNy4yNjI5IDQ0LjU5NzYgMzYuNDAyNCA0My43MzcxIDM1Ljg2MzEgNDIuNjc4N0MzNS41MjM2IDQyLjAxMjQgMzUuMzgyIDQxLjI5MjIgMzUuMzE1IDQwLjQ3MjJDMzUuMjUgMzkuNjc1OCAzNS4yNSAzOC42OTI0IDM1LjI1IDM3LjQ3MzJWMzQuNTI2OEMzNS4yNSAzMy4zMDc2IDM1LjI1IDMyLjMyNDIgMzUuMzE1IDMxLjUyNzhDMzUuMzgyIDMwLjcwNzggMzUuNTIzNiAyOS45ODc2IDM1Ljg2MzEgMjkuMzIxM0MzNi40MDI0IDI4LjI2MjkgMzcuMjYyOSAyNy40MDI0IDM4LjMyMTMgMjYuODYzMUMzOC45ODc2IDI2LjUyMzYgMzkuNzA3OCAyNi4zODIgNDAuNTI3OCAyNi4zMTVDNDEuMzI0MiAyNi4yNSA0Mi4zMDc2IDI2LjI1IDQzLjUyNjggMjYuMjVaTTQwLjcxMSAyOC41NTc2QzQwLjAzMDIgMjguNjEzMiAzOS42MzkxIDI4LjcxNjkgMzkuMzQyOCAyOC44Njc5QzM4LjcwNzcgMjkuMTkxNCAzOC4xOTE0IDI5LjcwNzcgMzcuODY3OSAzMC4zNDI4QzM3LjcxNjkgMzAuNjM5MSAzNy42MTMyIDMxLjAzMDIgMzcuNTU3NiAzMS43MTFDMzcuNTAwOSAzMi40MDUgMzcuNSAzMy4yOTYzIDM3LjUgMzQuNTc1VjM2LjcxNzdMMzguNTg0MiAzNS40MTY3QzM5LjU3MjQgMzQuMjMwOSA0MS4zNjU1IDM0LjE0OTYgNDIuNDU2OSAzNS4yNDFMNDYuNSAzOS4yODQxTDQ4LjI2OTQgMzcuNTE0NkM0OS4zNzU3IDM2LjQwODMgNTEuMTk4IDM2LjUwOTMgNTIuMTc1NCAzNy43MzA5TDUyLjQ5OTUgMzguMTM2MUM1Mi41IDM3LjkxMzEgNTIuNSAzNy42NzY1IDUyLjUgMzcuNDI1VjM0LjU3NUM1Mi41IDMzLjI5NjMgNTIuNDk5MSAzMi40MDUgNTIuNDQyNCAzMS43MTFDNTIuMzg2OCAzMS4wMzAyIDUyLjI4MzEgMzAuNjM5MSA1Mi4xMzIxIDMwLjM0MjhDNTEuODA4NiAyOS43MDc3IDUxLjI5MjMgMjkuMTkxNCA1MC42NTcyIDI4Ljg2NzlDNTAuMzYwOSAyOC43MTY5IDQ5Ljk2OTggMjguNjEzMiA0OS4yODkgMjguNTU3NkM0OC41OTUgMjguNTAwOSA0Ny43MDM3IDI4LjUgNDYuNDI1IDI4LjVINDMuNTc1QzQyLjI5NjMgMjguNSA0MS40MDUgMjguNTAwOSA0MC43MTEgMjguNTU3NlpNMzcuNTU3NiA0MC4yODlDMzcuNTU0MyA0MC4yNDkyIDM3LjU1MTMgNDAuMjA4OCAzNy41NDg0IDQwLjE2NzhDMzcuNTcxMSA0MC4xNDQ4IDM3LjU5MzEgNDAuMTIwNiAzNy42MTQyIDQwLjA5NTNMNDAuMzEyNyAzNi44NTcxQzQwLjQ1MzkgMzYuNjg3NyA0MC43MSAzNi42NzYxIDQwLjg2NTkgMzYuODMyTDQ1LjcwNDUgNDEuNjcwNkM0Ni4xNDM4IDQyLjEwOTkgNDYuODU2MSA0Mi4xMDk5IDQ3LjI5NTUgNDEuNjcwNkw0OS44NjA0IDM5LjEwNTZDNTAuMDE4NSAzOC45NDc2IDUwLjI3ODggMzguOTYyIDUwLjQxODQgMzkuMTM2NUw1Mi4yMzc3IDQxLjQxMDdDNTIuMjA1NiA0MS41MDEgNTIuMTcwNCA0MS41ODIyIDUyLjEzMjEgNDEuNjU3MkM1MS44MDg2IDQyLjI5MjMgNTEuMjkyMyA0Mi44MDg2IDUwLjY1NzIgNDMuMTMyMUM1MC4zNjA5IDQzLjI4MzEgNDkuOTY5OCA0My4zODY4IDQ5LjI4OSA0My40NDI0QzQ4LjU5NSA0My40OTkxIDQ3LjcwMzcgNDMuNSA0Ni40MjUgNDMuNUg0My41NzVDNDIuMjk2MyA0My41IDQxLjQwNSA0My40OTkxIDQwLjcxMSA0My40NDI0QzQwLjAzMDIgNDMuMzg2OCAzOS42MzkxIDQzLjI4MzEgMzkuMzQyOCA0My4xMzIxQzM4LjcwNzcgNDIuODA4NiAzOC4xOTE0IDQyLjI5MjMgMzcuODY3OSA0MS42NTcyQzM3LjcxNjkgNDEuMzYwOSAzNy42MTMyIDQwLjk2OTggMzcuNTU3NiA0MC4yODlaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgo8L3N2Zz4K";
|
|
202
|
-
|
|
203
|
-
var SvgArrowRightIcon = function SvgArrowRightIcon(props) {
|
|
204
|
-
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
205
|
-
viewBox: "0 0 20 20"
|
|
206
|
-
}, props), /*#__PURE__*/React.createElement("path", {
|
|
207
|
-
fillRule: "evenodd",
|
|
208
|
-
d: "M3.5 10a.75.75 0 0 1 .75-.75h9.69l-2.72-2.72a.75.75 0 1 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06-1.06l2.72-2.72h-9.69a.75.75 0 0 1-.75-.75Z"
|
|
209
|
-
}));
|
|
210
|
-
};
|
|
211
|
-
SvgArrowRightIcon.displayName = "ArrowRightIcon";
|
|
212
|
-
|
|
213
|
-
var SvgCalendarIcon = function SvgCalendarIcon(props) {
|
|
214
|
-
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
215
|
-
viewBox: "0 0 20 20"
|
|
216
|
-
}, props), /*#__PURE__*/React.createElement("path", {
|
|
217
|
-
fillRule: "evenodd",
|
|
218
|
-
d: "M7.75 3.5a.75.75 0 0 0-1.5 0v.407a3.075 3.075 0 0 0-.702.252 3.75 3.75 0 0 0-1.64 1.639c-.226.444-.32.924-.365 1.47-.043.531-.043 1.187-.043 2v1.464c0 .813 0 1.469.043 2 .045.546.14 1.026.366 1.47a3.75 3.75 0 0 0 1.639 1.64c.444.226.924.32 1.47.365.531.043 1.187.043 2 .043h3.383c.323 0 .542 0 .735-.02a3.75 3.75 0 0 0 3.344-3.344c.02-.193.02-.412.02-.735v-2.883c0-.813 0-1.469-.043-2-.045-.546-.14-1.026-.366-1.47a3.75 3.75 0 0 0-1.639-1.64 3.076 3.076 0 0 0-.702-.251v-.407a.75.75 0 0 0-1.5 0v.259c-.373-.009-.794-.009-1.268-.009h-1.964c-.474 0-.895 0-1.268.009v-.259Zm-1.521 1.995c.197-.1.458-.17.912-.207.462-.037 1.057-.038 1.909-.038h1.9c.853 0 1.447 0 1.91.038.453.037.714.107.912.207.423.216.767.56.983.984.1.197.17.458.207.912.014.18.024.38.029.609h-9.982c.006-.228.015-.429.03-.61.036-.453.106-.714.206-.911a2.25 2.25 0 0 1 .984-.984Zm-1.229 4.005v1.2c0 .853 0 1.447.038 1.91.037.453.107.714.207.912.216.423.56.767.984.983.197.1.458.17.912.207.462.037 1.057.038 1.909.038h3.306c.385 0 .52-.001.626-.012a2.25 2.25 0 0 0 2.006-2.006c.011-.106.012-.241.012-.626v-2.606h-10Z"
|
|
219
|
-
}));
|
|
220
|
-
};
|
|
221
|
-
SvgCalendarIcon.displayName = "CalendarIcon";
|
|
222
|
-
|
|
223
|
-
var SvgCheckIcon = function SvgCheckIcon(props) {
|
|
224
|
-
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
225
|
-
viewBox: "0 0 20 20"
|
|
226
|
-
}, props), /*#__PURE__*/React.createElement("path", {
|
|
227
|
-
fillRule: "evenodd",
|
|
228
|
-
d: "M15.78 5.97a.75.75 0 0 1 0 1.06l-6.5 6.5a.75.75 0 0 1-1.06 0l-3.25-3.25a.75.75 0 1 1 1.06-1.06l2.72 2.72 5.97-5.97a.75.75 0 0 1 1.06 0Z"
|
|
229
|
-
}));
|
|
230
|
-
};
|
|
231
|
-
SvgCheckIcon.displayName = "CheckIcon";
|
|
232
|
-
|
|
233
|
-
var SvgChevronDownIcon = function SvgChevronDownIcon(props) {
|
|
234
|
-
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
235
|
-
viewBox: "0 0 20 20"
|
|
236
|
-
}, props), /*#__PURE__*/React.createElement("path", {
|
|
237
|
-
fillRule: "evenodd",
|
|
238
|
-
d: "M5.72 8.47a.75.75 0 0 1 1.06 0l3.47 3.47 3.47-3.47a.75.75 0 1 1 1.06 1.06l-4 4a.75.75 0 0 1-1.06 0l-4-4a.75.75 0 0 1 0-1.06Z"
|
|
239
|
-
}));
|
|
240
|
-
};
|
|
241
|
-
SvgChevronDownIcon.displayName = "ChevronDownIcon";
|
|
242
|
-
|
|
243
|
-
var SvgChevronRightIcon = function SvgChevronRightIcon(props) {
|
|
244
|
-
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
245
|
-
viewBox: "0 0 20 20"
|
|
246
|
-
}, props), /*#__PURE__*/React.createElement("path", {
|
|
247
|
-
fillRule: "evenodd",
|
|
248
|
-
d: "M7.72 14.53a.75.75 0 0 1 0-1.06l3.47-3.47-3.47-3.47a.75.75 0 0 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06 0Z"
|
|
249
|
-
}));
|
|
250
|
-
};
|
|
251
|
-
SvgChevronRightIcon.displayName = "ChevronRightIcon";
|
|
252
|
-
|
|
253
|
-
var SvgChevronUpIcon = function SvgChevronUpIcon(props) {
|
|
254
|
-
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
255
|
-
viewBox: "0 0 20 20"
|
|
256
|
-
}, props), /*#__PURE__*/React.createElement("path", {
|
|
257
|
-
fillRule: "evenodd",
|
|
258
|
-
d: "M14.53 12.28a.75.75 0 0 1-1.06 0l-3.47-3.47-3.47 3.47a.75.75 0 0 1-1.06-1.06l4-4a.75.75 0 0 1 1.06 0l4 4a.75.75 0 0 1 0 1.06Z"
|
|
259
|
-
}));
|
|
260
|
-
};
|
|
261
|
-
SvgChevronUpIcon.displayName = "ChevronUpIcon";
|
|
262
|
-
|
|
263
|
-
const TRIM_DECIMAL_ZEROS_REGEX = /\.0+$/;
|
|
264
|
-
const DEFAULT_DECIMALS = 2;
|
|
265
|
-
const trimDecimalZeros = (number) => {
|
|
266
|
-
return `${number}`.replace(TRIM_DECIMAL_ZEROS_REGEX, '');
|
|
267
|
-
};
|
|
268
|
-
const cleanDecimal = (number, decimals = DEFAULT_DECIMALS) => {
|
|
269
|
-
return trimDecimalZeros(number.toFixed(decimals));
|
|
270
|
-
};
|
|
271
|
-
const semverToNum = (v) => {
|
|
272
|
-
const [major, minor, patch] = v.split('.').map((n) => Number(n));
|
|
273
|
-
return (major ?? 0) * 1_000_000 + (minor ?? 0) * 1_000 + (patch ?? 0);
|
|
274
|
-
};
|
|
275
|
-
const numberWithCommas = (x) => {
|
|
276
|
-
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Utility function to calculate percentage and format it.
|
|
281
|
-
* @param part - The part value.
|
|
282
|
-
* @param total - The total value.
|
|
283
|
-
* @param decimals - The number of decimal places to format the percentage to.
|
|
284
|
-
* @returns The formatted percentage as a string.
|
|
285
|
-
*/
|
|
286
|
-
const PERCENTAGE_THRESHOLD = 0.005;
|
|
287
|
-
const PERCENTAGE_THRESHOLD_STRING = '~0%';
|
|
288
|
-
const calcPercentage = (part, total, decimals = DEFAULT_DECIMALS) => {
|
|
289
|
-
if (typeof part !== 'number' || !total)
|
|
290
|
-
return undefined;
|
|
291
|
-
if (part === 0)
|
|
292
|
-
return 0;
|
|
293
|
-
const percentage = (part / total) * 100;
|
|
294
|
-
return parseFloat(cleanDecimal(percentage, decimals));
|
|
295
|
-
};
|
|
296
|
-
const isLessThanThreshold = (percentage) => percentage > 0 && percentage < PERCENTAGE_THRESHOLD;
|
|
297
|
-
const calcPercentageString = (part, total, decimals = 2) => {
|
|
298
|
-
const percentage = calcPercentage(part, total, decimals);
|
|
299
|
-
if (typeof percentage !== 'number')
|
|
300
|
-
return undefined;
|
|
301
|
-
if (isLessThanThreshold(percentage)) {
|
|
302
|
-
return PERCENTAGE_THRESHOLD_STRING;
|
|
303
|
-
}
|
|
304
|
-
return `${percentage}%`;
|
|
305
|
-
};
|
|
306
|
-
const formatPercentage = (percentage, decimals = DEFAULT_DECIMALS) => {
|
|
307
|
-
if (isLessThanThreshold(percentage)) {
|
|
308
|
-
return PERCENTAGE_THRESHOLD_STRING;
|
|
309
|
-
}
|
|
310
|
-
return `${cleanDecimal(percentage, decimals)}%`;
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
function toVal(mix) {
|
|
314
|
-
if (typeof mix === 'string') {
|
|
315
|
-
return mix;
|
|
316
|
-
}
|
|
317
|
-
else if (typeof mix === 'object' && mix !== null) {
|
|
318
|
-
return Object.keys(mix)
|
|
319
|
-
.filter((key) => mix[key])
|
|
320
|
-
.join(' ');
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
return false;
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
function cls(...classes) {
|
|
327
|
-
return classes.map(toVal).filter(Boolean).join(' ');
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function compareValues(a, b, order = 'asc') {
|
|
331
|
-
if (a === b)
|
|
332
|
-
return 0;
|
|
333
|
-
if (a === undefined || b === undefined) {
|
|
334
|
-
if (a === undefined && b !== undefined)
|
|
335
|
-
return order === 'asc' ? -1 : 1;
|
|
336
|
-
if (b === undefined && a !== undefined)
|
|
337
|
-
return order === 'asc' ? 1 : -1;
|
|
338
|
-
return 0;
|
|
339
|
-
}
|
|
340
|
-
const isDate = (val) => typeof val !== 'boolean' && !isNaN(Date.parse(val));
|
|
341
|
-
const isString = (val) => typeof val === 'string';
|
|
342
|
-
let comparison = 0;
|
|
343
|
-
if (isDate(a) && isDate(b)) {
|
|
344
|
-
const dateA = a instanceof Date ? a : new Date(a);
|
|
345
|
-
const dateB = b instanceof Date ? b : new Date(b);
|
|
346
|
-
comparison = dateA > dateB ? 1 : -1;
|
|
347
|
-
}
|
|
348
|
-
else if (isString(a) && isString(b)) {
|
|
349
|
-
comparison = a > b ? 1 : -1;
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
comparison = a > b ? 1 : -1;
|
|
353
|
-
}
|
|
354
|
-
return order === 'asc' ? -comparison : comparison;
|
|
355
|
-
}
|
|
356
|
-
function getNestedValue(obj, path) {
|
|
357
|
-
if (typeof path === 'string') {
|
|
358
|
-
return path
|
|
359
|
-
.replace(/\[(\d+)\]/g, '.$1')
|
|
360
|
-
.split('.')
|
|
361
|
-
.reduce((acc, key) => acc?.[key], obj);
|
|
362
|
-
}
|
|
363
|
-
return obj[path];
|
|
364
|
-
}
|
|
365
|
-
function sortByCondition(array, options) {
|
|
366
|
-
const { attr, order = 'asc', preferredValue, backupAttr, orderArrayAttr, orderArray } = options;
|
|
367
|
-
return array.slice().sort((a, b) => {
|
|
368
|
-
const valueA = getNestedValue(a, attr);
|
|
369
|
-
const valueB = getNestedValue(b, attr);
|
|
370
|
-
if (preferredValue !== undefined) {
|
|
371
|
-
if (valueA === preferredValue && valueB !== preferredValue)
|
|
372
|
-
return -1;
|
|
373
|
-
if (valueB === preferredValue && valueA !== preferredValue)
|
|
374
|
-
return 1;
|
|
375
|
-
}
|
|
376
|
-
if (orderArrayAttr === attr && orderArray) {
|
|
377
|
-
const orderArrayValue = orderArray[order];
|
|
378
|
-
return orderArrayValue.indexOf(valueA) - orderArrayValue.indexOf(valueB);
|
|
379
|
-
}
|
|
380
|
-
const primaryComparison = compareValues(valueA, valueB, order);
|
|
381
|
-
if (primaryComparison !== 0)
|
|
382
|
-
return primaryComparison;
|
|
383
|
-
if (backupAttr)
|
|
384
|
-
return compareValues(a[backupAttr], b[backupAttr], order);
|
|
385
|
-
return 0;
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
function sortByConditions(array, optionsArray) {
|
|
389
|
-
return optionsArray.reduce((sortedArray, options) => {
|
|
390
|
-
return sortByCondition(sortedArray, options);
|
|
391
|
-
}, array.slice());
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
dayjs.extend(utc);
|
|
395
|
-
dayjs.extend(timezone);
|
|
396
|
-
dayjs.extend(quarterOfYear);
|
|
397
|
-
let tz = 'UTC';
|
|
398
|
-
const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
|
399
|
-
function getInitialTimezone() {
|
|
400
|
-
return tz;
|
|
401
|
-
}
|
|
402
|
-
function setTz(value) {
|
|
403
|
-
tz = value;
|
|
404
|
-
dayjs.tz.setDefault(value);
|
|
405
|
-
}
|
|
406
|
-
const dayjsTz = (date) => {
|
|
407
|
-
if (!date)
|
|
408
|
-
return dayjs().tz(tz);
|
|
409
|
-
return dayjs(date).tz(tz);
|
|
410
|
-
};
|
|
411
|
-
const convertDateToTz = (date) => {
|
|
412
|
-
if (!date)
|
|
413
|
-
return dayjs.tz(dayjs().format(DEFAULT_DATE_FORMAT), tz);
|
|
414
|
-
return dayjs.tz(dayjs(date).format(DEFAULT_DATE_FORMAT), tz);
|
|
415
|
-
};
|
|
416
|
-
const dayjsTzToLocalTZ = (date) => {
|
|
417
|
-
if (!date)
|
|
418
|
-
return dayjs(dayjsTz().format(DEFAULT_DATE_FORMAT));
|
|
419
|
-
return dayjs(dayjsTz(date).format(DEFAULT_DATE_FORMAT));
|
|
420
|
-
};
|
|
421
|
-
const dayjsTzToDate = (date) => {
|
|
422
|
-
return dayjsTzToLocalTZ(date).toDate();
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
var AnalyticInterval;
|
|
426
|
-
(function (AnalyticInterval) {
|
|
427
|
-
AnalyticInterval["DAY"] = "DAY";
|
|
428
|
-
AnalyticInterval["HOUR"] = "HOUR";
|
|
429
|
-
AnalyticInterval["MONTH"] = "MONTH";
|
|
430
|
-
AnalyticInterval["QUARTER"] = "QUARTER";
|
|
431
|
-
AnalyticInterval["WEEK"] = "WEEK";
|
|
432
|
-
AnalyticInterval["YEAR"] = "YEAR";
|
|
433
|
-
})(AnalyticInterval || (AnalyticInterval = {}));
|
|
434
|
-
const SECONDS_IN_MINUTE = 60;
|
|
435
|
-
const SECONDS_IN_HOUR = SECONDS_IN_MINUTE * SECONDS_IN_MINUTE;
|
|
436
|
-
const getTimeDurationLabel = (valueInSeconds) => {
|
|
437
|
-
let data = valueInSeconds;
|
|
438
|
-
if (!Number.isFinite(valueInSeconds) || valueInSeconds == null) {
|
|
439
|
-
data = 0;
|
|
440
|
-
}
|
|
441
|
-
const fixedValue = cleanDecimal(data);
|
|
442
|
-
if (data >= SECONDS_IN_HOUR) {
|
|
443
|
-
const hours = Math.floor(data / SECONDS_IN_HOUR);
|
|
444
|
-
const minutes = Math.floor((data % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE);
|
|
445
|
-
const seconds = Math.floor(data % SECONDS_IN_MINUTE);
|
|
446
|
-
return `${hours}h ${minutes}m ${seconds}s`;
|
|
447
|
-
}
|
|
448
|
-
else if (data >= SECONDS_IN_MINUTE) {
|
|
449
|
-
const minutes = Math.floor(data / SECONDS_IN_MINUTE);
|
|
450
|
-
const seconds = Math.floor(data % SECONDS_IN_MINUTE);
|
|
451
|
-
return `${minutes}m ${seconds}s`;
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
454
|
-
return `${fixedValue}s`;
|
|
455
|
-
}
|
|
456
|
-
};
|
|
457
|
-
const getFormattedByInterval = (value, interval, options) => {
|
|
458
|
-
if (!value)
|
|
459
|
-
return '';
|
|
460
|
-
const optionFormat = options?.isExpandDetail
|
|
461
|
-
? {
|
|
462
|
-
formatHouse: 'MMM D, h:mm A',
|
|
463
|
-
formatDay: 'MMM D, YYYY',
|
|
464
|
-
formatMonth: 'MMM YYYY',
|
|
465
|
-
formatYear: 'MMM YYYY',
|
|
466
|
-
}
|
|
467
|
-
: {
|
|
468
|
-
formatHouse: 'h A',
|
|
469
|
-
formatDay: 'MMM D',
|
|
470
|
-
formatMonth: 'MMM YYYY',
|
|
471
|
-
formatYear: 'YYYY',
|
|
472
|
-
};
|
|
473
|
-
switch (interval) {
|
|
474
|
-
case AnalyticInterval.HOUR:
|
|
475
|
-
return dayjsTz(value).format(optionFormat.formatHouse);
|
|
476
|
-
case AnalyticInterval.DAY:
|
|
477
|
-
case AnalyticInterval.WEEK:
|
|
478
|
-
return dayjsTz(value).format(optionFormat.formatDay);
|
|
479
|
-
case AnalyticInterval.MONTH:
|
|
480
|
-
return dayjsTz(value).format(optionFormat.formatMonth);
|
|
481
|
-
case AnalyticInterval.QUARTER: {
|
|
482
|
-
const d = dayjsTz(value);
|
|
483
|
-
return `Q${d.quarter()} ${d.format('YYYY')}`;
|
|
484
|
-
}
|
|
485
|
-
case AnalyticInterval.YEAR:
|
|
486
|
-
return dayjsTz(value).format(optionFormat.formatYear);
|
|
487
|
-
}
|
|
488
|
-
return dayjsTz(value).format(optionFormat.formatMonth);
|
|
489
|
-
};
|
|
490
|
-
|
|
491
|
-
const GClickable = ({ children, fullWidth = false, cursor = 'pointer', onClick, onMouseEnter, onMouseLeave, }) => {
|
|
492
|
-
return (jsx("div", { role: "button", tabIndex: 0, className: cls({
|
|
493
|
-
'w-full': fullWidth,
|
|
494
|
-
'cursor-pointer': cursor === 'pointer',
|
|
495
|
-
'cursor-default': cursor === 'default',
|
|
496
|
-
'cursor-not-allowed': cursor === 'not-allowed',
|
|
497
|
-
}), onKeyDown: (e) => {
|
|
498
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
499
|
-
e.preventDefault();
|
|
500
|
-
onClick();
|
|
501
|
-
}
|
|
502
|
-
}, onClick: onClick, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, children: children }));
|
|
503
|
-
};
|
|
504
|
-
|
|
505
|
-
const GActivatorPopover = ({ onClick, active, content, textProps, boxProps: customBoxProps, disabled, icon: customIcon, }) => {
|
|
506
|
-
const boxProps = useMemo(() => {
|
|
507
|
-
if (disabled) {
|
|
508
|
-
return {
|
|
509
|
-
borderColor: 'border-disabled',
|
|
510
|
-
background: 'bg-surface-disabled',
|
|
511
|
-
...customBoxProps,
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
return {
|
|
515
|
-
shadow: active ? 'button-inset' : 'button',
|
|
516
|
-
background: active ? 'bg-fill-active' : 'bg-fill',
|
|
517
|
-
...customBoxProps,
|
|
518
|
-
};
|
|
519
|
-
}, [active, disabled, customBoxProps]);
|
|
520
|
-
const toneClass = useMemo(() => {
|
|
521
|
-
if (disabled) {
|
|
522
|
-
return 'text-[var(--p-color-text-disabled)]';
|
|
523
|
-
}
|
|
524
|
-
return active ? 'text-[var(--p-color-text-subdued)]' : 'text-[var(--p-color-text)]';
|
|
525
|
-
}, [active, disabled]);
|
|
526
|
-
const textComponent = useMemo(() => {
|
|
527
|
-
return (jsx(Text, { as: "span", variant: "bodyMd", fontWeight: "medium", tone: disabled ? 'inherit' : textProps?.tone, truncate: true, ...(textProps?.variant && { variant: textProps.variant }), children: content }));
|
|
528
|
-
}, [content, textProps, disabled]);
|
|
529
|
-
const handleClick = useCallback(() => {
|
|
530
|
-
if (disabled)
|
|
531
|
-
return;
|
|
532
|
-
onClick();
|
|
533
|
-
}, [disabled, onClick]);
|
|
534
|
-
return (jsx(GClickable, { cursor: disabled ? 'default' : 'pointer', onClick: handleClick, children: jsx("div", { className: cls(toneClass), children: jsxs(Box, { padding: "150", paddingInline: "300", paddingInlineEnd: "150", borderRadius: "200", ...boxProps, children: [customIcon && (jsxs(InlineStack, { gap: "200", align: "center", wrap: false, children: [jsx(Box, { children: jsx(Icon, { source: customIcon }) }), textComponent] })), !customIcon && (jsxs(InlineGrid, { columns: "1fr 20px", gap: "200", alignItems: "center", children: [textComponent, jsx(Icon, { source: active ? SvgChevronUpIcon : SvgChevronDownIcon })] }))] }) }) }));
|
|
535
|
-
};
|
|
536
|
-
|
|
537
|
-
const GBlockCenter = ({ height, align, inlineAlign, display, ...props }) => {
|
|
538
|
-
const stickyStyle = useMemo(() => {
|
|
539
|
-
if (props.position !== 'sticky')
|
|
540
|
-
return {};
|
|
541
|
-
const style = {
|
|
542
|
-
position: 'sticky',
|
|
543
|
-
};
|
|
544
|
-
if (props.insetInlineStart)
|
|
545
|
-
style.insetInlineStart = Number(props.insetInlineStart) * 4;
|
|
546
|
-
if (props.insetInlineEnd)
|
|
547
|
-
style.insetInlineEnd = Number(props.insetInlineEnd) * 4;
|
|
548
|
-
if (props.insetBlockStart)
|
|
549
|
-
style.insetBlockStart = Number(props.insetBlockStart) * 4;
|
|
550
|
-
if (props.insetBlockEnd)
|
|
551
|
-
style.insetBlockEnd = Number(props.insetBlockEnd) * 4;
|
|
552
|
-
return style;
|
|
553
|
-
}, [props.position, props.insetInlineStart, props.insetInlineEnd, props.insetBlockStart, props.insetBlockEnd]);
|
|
554
|
-
return (jsx("div", { className: "Polaris-GBlockCenter", style: {
|
|
555
|
-
...stickyStyle,
|
|
556
|
-
'--gp-block-center-height': height,
|
|
557
|
-
'--gp-block-center-display': display,
|
|
558
|
-
'--gp-block-center-align': align,
|
|
559
|
-
'--gp-block-center-inline-align': inlineAlign,
|
|
560
|
-
'--gp-block-center-overflow-x': props.overflowX,
|
|
561
|
-
'--gp-block-center-overflow-y': props.overflowY,
|
|
562
|
-
}, children: jsx(Box, { ...props }) }));
|
|
563
|
-
};
|
|
564
|
-
|
|
565
|
-
const GTooltip = ({ isEnabled = true, content, maxWidth, ...props }) => {
|
|
566
|
-
const hasContent = isEnabled && !!content;
|
|
567
|
-
return hasContent ? (jsx(Tooltip, { width: "wide", hoverDelay: 500, content: content, ...props, accessibilityLabel: maxWidth?.toString() })) : (props.children);
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
const GButton = ({ activatorWrapper, children, iconRight, inset, stopPropagation = true, onClick, themeTone = 'light', variant, ...props }) => {
|
|
571
|
-
const Wrapper = activatorWrapper || 'div';
|
|
572
|
-
const isNeutral = variant === 'neutral';
|
|
573
|
-
const polarisVariant = isNeutral ? undefined : variant;
|
|
574
|
-
const handleClick = (e) => {
|
|
575
|
-
stopPropagation && e.stopPropagation();
|
|
576
|
-
if (props.disabled)
|
|
577
|
-
return;
|
|
578
|
-
onClick?.();
|
|
579
|
-
};
|
|
580
|
-
const button = (jsx(GTooltip, { activatorWrapper: "tooltip-content", ...props.tooltip, children: jsx(Wrapper, { className: cls('Polaris-GButton', {
|
|
581
|
-
'Polaris-GButton--icon-right': iconRight,
|
|
582
|
-
'Polaris-GButton--dark': themeTone === 'dark',
|
|
583
|
-
'Polaris-GButton--neutral': isNeutral,
|
|
584
|
-
'cursor-default': props.disabled,
|
|
585
|
-
'Polaris-GButton--fullWidth': props.fullWidth,
|
|
586
|
-
flex: inset,
|
|
587
|
-
}), onClick: handleClick, children: jsx(Button, { variant: polarisVariant, ...props, children: children }) }) }));
|
|
588
|
-
if (inset) {
|
|
589
|
-
return jsx(Box, { padding: "100", children: button });
|
|
590
|
-
}
|
|
591
|
-
return button;
|
|
592
|
-
};
|
|
593
|
-
|
|
594
|
-
const GCheckbox = ({ ...props }) => {
|
|
595
|
-
return props.multiple ? jsx(GCheckboxMultiple, { ...props }) : jsx(GCheckboxSingle, { ...props });
|
|
596
|
-
};
|
|
597
|
-
const GCheckboxMultiple = ({ options, onChange, onChangeSingleValue, emptySelected, selected, onHover, itemHovered, dependentDisabledValues, }) => {
|
|
598
|
-
const [settingOptions, setSettingOptions] = useState([]);
|
|
599
|
-
const handleChange = (value) => {
|
|
600
|
-
if (onChangeSingleValue) {
|
|
601
|
-
onChangeSingleValue(value);
|
|
602
|
-
}
|
|
603
|
-
const updatedOptions = settingOptions.includes(value)
|
|
604
|
-
? settingOptions.filter((item) => item !== value)
|
|
605
|
-
: [...settingOptions, value];
|
|
606
|
-
setSettingOptions(updatedOptions);
|
|
607
|
-
onChange(updatedOptions);
|
|
608
|
-
};
|
|
609
|
-
const handleHover = (value) => {
|
|
610
|
-
if (!onHover)
|
|
611
|
-
return;
|
|
612
|
-
onHover(value);
|
|
613
|
-
};
|
|
614
|
-
useEffect(() => {
|
|
615
|
-
setSettingOptions(() => {
|
|
616
|
-
if (selected) {
|
|
617
|
-
return options.filter((item) => selected.includes(item.value)).map((item) => item.value);
|
|
618
|
-
}
|
|
619
|
-
return [];
|
|
620
|
-
});
|
|
621
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
622
|
-
}, [selected]);
|
|
623
|
-
return (jsx(BlockStack, { children: options.map((item) => {
|
|
624
|
-
const hasForceUnchecked = dependentDisabledValues?.has(item.value);
|
|
625
|
-
const isOnlyOneSelected = emptySelected && options.filter((opt) => opt.selected).length === 1 && emptySelected;
|
|
626
|
-
const handleCheckboxClick = () => {
|
|
627
|
-
if (isOnlyOneSelected)
|
|
628
|
-
return;
|
|
629
|
-
handleChange(item.value);
|
|
630
|
-
};
|
|
631
|
-
return (jsx("div", { className: cls('flex w-full items-center justify-between', {
|
|
632
|
-
'cursor-not-allowed': isOnlyOneSelected,
|
|
633
|
-
'cursor-pointer': !isOnlyOneSelected,
|
|
634
|
-
'bg-surface-hover rounded-lg': itemHovered === item.value,
|
|
635
|
-
}), onClick: () => {
|
|
636
|
-
if (isOnlyOneSelected || item.disabled)
|
|
637
|
-
return;
|
|
638
|
-
handleCheckboxClick();
|
|
639
|
-
}, onMouseEnter: () => handleHover(item.value), onMouseLeave: () => handleHover(undefined), children: isOnlyOneSelected ? (jsx(GTooltip, { isEnabled: item.tooltip?.isEnabled, ...item.tooltip, children: jsx(Box, { paddingBlock: "150", paddingInline: "200", width: "100%", children: jsxs(InlineStack, { blockAlign: "center", gap: "150", children: [jsx(Checkbox, { label: item.label, labelHidden: true, checked: item.selected, disabled: true }), jsx(Text, { as: "p", variant: "bodyMd", tone: "subdued", children: item.label })] }) }) })) : (jsx(Box, { paddingBlock: "150", paddingInline: "200", minWidth: "0", children: jsxs(InlineStack, { blockAlign: "center", gap: "150", wrap: false, children: [jsx(Checkbox, { label: item.label, labelHidden: true, checked: hasForceUnchecked ? false : settingOptions.includes(item.value), onChange: handleCheckboxClick, disabled: item.disabled }), jsxs(Box, { minWidth: "0", children: [jsx(Text, { as: "p", variant: "bodyMd", truncate: true, tone: hasForceUnchecked ? 'disabled' : 'inherit', children: item.label }), item.description && (jsx(Text, { as: "p", variant: "bodySm", tone: "disabled", truncate: true, children: item.description }))] })] }) })) }, item.value));
|
|
640
|
-
}) }));
|
|
641
|
-
};
|
|
642
|
-
const GCheckboxSingle = ({ options, onChange }) => {
|
|
643
|
-
return (jsx(BlockStack, { gap: "300", children: options.map((item) => (jsx(RadioButton, { label: item.label, checked: item.selected, onChange: () => onChange(item.value), helpText: item.helpText ? jsx(ChoiceHelpText, { item: item }) : undefined }, item.value))) }));
|
|
644
|
-
};
|
|
645
|
-
|
|
646
|
-
const GDiv = forwardRef(({ children, onClick, ...props }, ref) => {
|
|
647
|
-
const onKeyDown = useCallback((e) => {
|
|
648
|
-
if (e.key === 'Enter' || e.key === ' ') {
|
|
649
|
-
e.preventDefault();
|
|
650
|
-
onClick?.();
|
|
651
|
-
}
|
|
652
|
-
}, [onClick]);
|
|
653
|
-
return (jsx("div", { ref: ref, ...props, role: "button", tabIndex: 0, onKeyDown: onKeyDown, onClick: onClick, children: children }));
|
|
654
|
-
});
|
|
655
|
-
GDiv.displayName = 'GDiv';
|
|
656
|
-
|
|
657
|
-
const TRANSFORMER_REGEX = /\[(\d+)\](.*?)\[\]/g;
|
|
658
|
-
const GI18NText = (props) => {
|
|
659
|
-
const { children, transformers } = props;
|
|
660
|
-
if (!transformers || Object.values(transformers).length === 0) {
|
|
661
|
-
return jsx(Text, { ...props, children: children });
|
|
662
|
-
}
|
|
663
|
-
const transformContent = (text) => {
|
|
664
|
-
const parts = [];
|
|
665
|
-
let lastIndex = 0;
|
|
666
|
-
text.replace(TRANSFORMER_REGEX, (match, number, childrenContent, offset) => {
|
|
667
|
-
parts.push(text.slice(lastIndex, offset));
|
|
668
|
-
const transformerFunction = transformers[number];
|
|
669
|
-
if (typeof transformerFunction === 'function') {
|
|
670
|
-
parts.push(transformerFunction(childrenContent));
|
|
671
|
-
}
|
|
672
|
-
else {
|
|
673
|
-
parts.push(match);
|
|
674
|
-
}
|
|
675
|
-
lastIndex = offset + match.length;
|
|
676
|
-
return match;
|
|
677
|
-
});
|
|
678
|
-
parts.push(text.slice(lastIndex));
|
|
679
|
-
return parts.map((part, index) => jsx(Fragment$1, { children: part }, index));
|
|
680
|
-
};
|
|
681
|
-
return jsx(Text, { ...props, children: typeof children === 'string' ? transformContent(children) : children });
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
function GOptionList({ options, selected, onChange }) {
|
|
685
|
-
const handleSelect = (value) => {
|
|
686
|
-
onChange([value]);
|
|
687
|
-
};
|
|
688
|
-
const handleKeyDown = (event, value) => {
|
|
689
|
-
if (event.key === 'Enter' || event.key === ' ') {
|
|
690
|
-
event.preventDefault();
|
|
691
|
-
handleSelect(value);
|
|
692
|
-
}
|
|
693
|
-
};
|
|
694
|
-
return (jsx(Box, { padding: "150", children: jsx(BlockStack, { gap: "100", children: options.map((option) => {
|
|
695
|
-
const isSelected = selected.includes(option.value);
|
|
696
|
-
return (jsx("div", { role: "option", "aria-selected": isSelected, tabIndex: 0, onClick: () => handleSelect(option.value), onKeyDown: (e) => handleKeyDown(e, option.value), className: cls('p-1.5 pl-4 rounded-lg cursor-pointer', {
|
|
697
|
-
'bg-[#F1F1F1]': isSelected,
|
|
698
|
-
'hover:bg-[#F1F1F1]': !isSelected,
|
|
699
|
-
}), children: jsxs(InlineStack, { align: "space-between", blockAlign: "center", wrap: false, gap: "200", children: [jsx(Box, { minWidth: "0", children: option.label }), isSelected && (jsx(Box, { children: jsx(Icon, { source: SvgCheckIcon }) }))] }) }, option.value));
|
|
700
|
-
}) }) }));
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
const GSelector = (props) => {
|
|
704
|
-
const [popoverActive, setPopoverActive] = useState(false);
|
|
705
|
-
const { activatorText, selected, options, emptyLabel, preferredAlignment = 'right', formatActivatorContent = (text) => text.join(', '), } = props;
|
|
706
|
-
const togglePopoverActive = useCallback(() => setPopoverActive((prev) => !prev), []);
|
|
707
|
-
const selectedOption = useMemo(() => {
|
|
708
|
-
return options
|
|
709
|
-
.filter((item) => item.active || item.id === selected)
|
|
710
|
-
.map((item) => item.content || '')
|
|
711
|
-
.filter((item) => !!item);
|
|
712
|
-
}, [options, selected]);
|
|
713
|
-
const activatorContent = useMemo(() => {
|
|
714
|
-
if (selectedOption.length) {
|
|
715
|
-
const selected = formatActivatorContent(selectedOption);
|
|
716
|
-
return activatorText ? `${activatorText}: ${selected}` : selected;
|
|
717
|
-
}
|
|
718
|
-
if (emptyLabel) {
|
|
719
|
-
return activatorText ? `${activatorText}: ${emptyLabel}` : emptyLabel;
|
|
720
|
-
}
|
|
721
|
-
return activatorText;
|
|
722
|
-
}, [selectedOption, emptyLabel, activatorText, formatActivatorContent]);
|
|
723
|
-
const selectorMarkup = useMemo(() => {
|
|
724
|
-
switch (props.variant) {
|
|
725
|
-
case 'choice':
|
|
726
|
-
return jsx(GSelectorChoice, { ...props, setPopoverActive: togglePopoverActive });
|
|
727
|
-
case 'action-list':
|
|
728
|
-
return jsx(GSelectorActionList, { ...props, setPopoverActive: togglePopoverActive });
|
|
729
|
-
}
|
|
730
|
-
}, [props, togglePopoverActive]);
|
|
731
|
-
return (jsx(Popover, { active: popoverActive, activator: jsx("div", { className: "flex items-center gap-1", children: jsx(Button, { onClick: togglePopoverActive, disclosure: popoverActive ? 'up' : 'down', children: activatorContent }) }), autofocusTarget: "first-node", fluidContent: true, onClose: togglePopoverActive, preferredAlignment: preferredAlignment, children: selectorMarkup }));
|
|
732
|
-
};
|
|
733
|
-
const GSelectorChoice = ({ options, selected, onSelect, maxWidth, minWidth, clearable, setPopoverActive, }) => {
|
|
734
|
-
const { t } = useTranslation();
|
|
735
|
-
const items = useMemo(() => {
|
|
736
|
-
if (!options?.length)
|
|
737
|
-
return [];
|
|
738
|
-
return options.map((option) => ({
|
|
739
|
-
value: option.id,
|
|
740
|
-
label: option.content || '',
|
|
741
|
-
selected: false,
|
|
742
|
-
}));
|
|
743
|
-
}, [options]);
|
|
744
|
-
const handleSelection = useCallback((value) => {
|
|
745
|
-
onSelect(value);
|
|
746
|
-
}, [onSelect]);
|
|
747
|
-
return (jsx(Box, { maxWidth: maxWidth, minWidth: minWidth, paddingBlock: "150", children: jsxs(BlockStack, { children: [jsx(BlockStack, { gap: "0", children: jsx(GCheckbox, { multiple: true, options: items, selected: selected, onChange: handleSelection }) }), clearable && (jsx(Box, { paddingBlock: "150", paddingInline: "200", children: jsx(InlineStack, { blockAlign: "center", align: "start", children: jsx(Button, { disabled: !selected?.length, onClick: () => {
|
|
748
|
-
handleSelection([]);
|
|
749
|
-
setPopoverActive(false);
|
|
750
|
-
}, variant: "plain", children: t('Clear') }) }) }))] }) }));
|
|
751
|
-
};
|
|
752
|
-
const GSelectorActionList = ({ options, selected, onSelect, helpText, maxWidth, minWidth, setPopoverActive, }) => {
|
|
753
|
-
const handleSelection = useCallback((value) => {
|
|
754
|
-
onSelect(value);
|
|
755
|
-
setPopoverActive(false);
|
|
756
|
-
}, [onSelect, setPopoverActive]);
|
|
757
|
-
const items = useMemo(() => {
|
|
758
|
-
if (!options?.length)
|
|
759
|
-
return [];
|
|
760
|
-
return options.map((option) => ({
|
|
761
|
-
id: option.id,
|
|
762
|
-
content: option.content,
|
|
763
|
-
helpText: option.helpText,
|
|
764
|
-
onAction: () => handleSelection(option.id),
|
|
765
|
-
active: option.active || option.id === selected,
|
|
766
|
-
suffix: (option.active || option.id === selected) && jsx(Icon, { source: SvgCheckIcon, tone: "success" }),
|
|
767
|
-
}));
|
|
768
|
-
}, [options, selected, handleSelection]);
|
|
769
|
-
return (jsx(Box, { maxWidth: maxWidth, minWidth: minWidth, children: jsxs(BlockStack, { gap: "0", children: [jsx(ActionList, { actionRole: "menuitem", items: items }), helpText] }) }));
|
|
770
|
-
};
|
|
771
|
-
|
|
772
|
-
const GTextLink = ({ linkAction, isDisabled, disabledFocus, children }) => {
|
|
773
|
-
if (!linkAction || isDisabled) {
|
|
774
|
-
return jsx(Fragment, { children: children });
|
|
775
|
-
}
|
|
776
|
-
return (jsx("span", { className: cls('GTextLink', { 'GTextLink--disabled-focus': disabledFocus }), children: jsx(Link, { ...linkAction, children: jsx(Fragment, { children: children }) }) }));
|
|
777
|
-
};
|
|
778
|
-
|
|
779
|
-
const GSkeletonDisplayText = (props) => {
|
|
780
|
-
const height = props.height ?? '50px';
|
|
781
|
-
return (jsxs("div", { className: "Polaris-GSkeletonDisplayText", children: [jsx("style", { children: `.Polaris-GSkeletonDisplayText .Polaris-SkeletonDisplayText__DisplayText { height: ${height} !important; }` }), jsx(SkeletonDisplayText, { maxWidth: "100%", size: "extraLarge" })] }));
|
|
782
|
-
};
|
|
783
|
-
|
|
784
|
-
/**
|
|
785
|
-
* Helper function to generate a variation class name.
|
|
786
|
-
* @param name - Base name of the class.
|
|
787
|
-
* @param value - Variation value to append.
|
|
788
|
-
* @returns Combined class name.
|
|
789
|
-
*/
|
|
790
|
-
function variationName(name, value) {
|
|
791
|
-
return `${name}${value.charAt(0).toUpperCase()}${value.slice(1)}`;
|
|
792
|
-
}
|
|
793
|
-
const GThumbnail = ({ source, alt, size, grayscale, defaultSource = THUMB_PRODUCT_DEFAULT, width = '80', height = '80', classRemoved = false, }) => {
|
|
794
|
-
const sizeClass = size && variationName('Polaris-Thumbnail--size', size);
|
|
795
|
-
const filterClass = grayscale && 'Polaris-GThumbnail--filter';
|
|
796
|
-
const className = cls('Polaris-Thumbnail', sizeClass);
|
|
797
|
-
const thumbnail = (jsx("img", { onError: (e) => {
|
|
798
|
-
e.currentTarget.src = defaultSource;
|
|
799
|
-
}, alt: alt ?? 'Thumbnail', src: `${source ?? defaultSource}`, width: width, height: height, style: {
|
|
800
|
-
'--gp-grayscale-percentage': grayscale || '100%',
|
|
801
|
-
}, className: cls('Polaris-GThumbnail', filterClass) }));
|
|
802
|
-
if (classRemoved)
|
|
803
|
-
return thumbnail;
|
|
804
|
-
return jsx("span", { className: className, children: thumbnail });
|
|
805
|
-
};
|
|
806
|
-
|
|
807
|
-
const SIZE_CLASS = {
|
|
808
|
-
default: 'w-[210px]',
|
|
809
|
-
wide: 'w-[320px]',
|
|
810
|
-
large: 'w-[328px]',
|
|
811
|
-
};
|
|
812
|
-
const ALIGNMENT_MAP = {
|
|
813
|
-
start: 'flex justify-start',
|
|
814
|
-
center: 'flex justify-center',
|
|
815
|
-
end: 'flex justify-end',
|
|
816
|
-
};
|
|
817
|
-
const GTooltipCard = forwardRef((props, ref) => {
|
|
818
|
-
const { tooltip, wrapper = 'div', activatorProps, isHideBorder, alignment, delay = 500, textDecoration = 'none', popoverRef, preferredAlignment = 'left', showArrow = false, } = props;
|
|
819
|
-
const { width = 'default' } = tooltip ?? {};
|
|
820
|
-
const [isMouseEnter, setIsMouseEnter] = useState(false);
|
|
821
|
-
const TooltipCardWrapper = wrapper;
|
|
822
|
-
const sizeClass = SIZE_CLASS[width];
|
|
823
|
-
const timeoutRef = useRef(null);
|
|
824
|
-
const handleMouseEnter = () => {
|
|
825
|
-
timeoutRef.current = setTimeout(() => {
|
|
826
|
-
setIsMouseEnter(true);
|
|
827
|
-
}, delay);
|
|
828
|
-
};
|
|
829
|
-
const handleMouseLeave = () => {
|
|
830
|
-
if (timeoutRef.current) {
|
|
831
|
-
clearTimeout(timeoutRef.current);
|
|
832
|
-
timeoutRef.current = null;
|
|
833
|
-
}
|
|
834
|
-
setIsMouseEnter(false);
|
|
835
|
-
};
|
|
836
|
-
useImperativeHandle(ref, () => ({ onClose: handleMouseLeave }));
|
|
837
|
-
return (jsx(TooltipCardWrapper, { className: cls('GTooltipCard cursor-pointer', alignment && ALIGNMENT_MAP[alignment], {
|
|
838
|
-
'GTooltipCard--text-underline': textDecoration === 'underline',
|
|
839
|
-
}), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: jsx(Popover, { ref: popoverRef, activator: !isHideBorder ? (jsx(Box, { borderBlockEndWidth: "025", borderStyle: "dashed", borderColor: "border-tertiary", as: wrapper, ...activatorProps, children: props.children })) : (jsx(InlineStack, { children: props.children })), activatorWrapper: wrapper, onClose: () => { }, active: isMouseEnter, preferredPosition: "below", preferredAlignment: preferredAlignment, children: tooltip && (jsx("div", { className: cls(sizeClass, { 'GTooltipCard-arrow': showArrow }), children: jsx(Box, { padding: "400", children: jsxs(BlockStack, { gap: "200", children: [jsxs(BlockStack, { gap: "100", children: [jsx(Text, { as: "span", variant: "headingSm", fontWeight: "semibold", children: tooltip.title }), jsxs(BlockStack, { gap: "200", children: [jsx(Text, { as: "span", variant: "bodyMd", tone: "subdued", fontWeight: "medium", children: jsx("span", { dangerouslySetInnerHTML: { __html: tooltip.content } }) }), tooltip.contentList && (jsx(List, { type: "bullet", children: tooltip.contentList.map((item) => (jsx(List.Item, { children: jsx(Text, { as: "span", variant: "bodyMd", tone: "subdued", fontWeight: "medium", children: item }) }, item))) }))] })] }), tooltip.formula && (jsx("div", { className: "rounded-md font-mono", style: { fontSize: '12px' }, children: tooltip.formula }))] }) }) })) }) }));
|
|
840
|
-
});
|
|
841
|
-
GTooltipCard.displayName = 'GTooltipCard';
|
|
842
|
-
|
|
843
|
-
const GViewBySelector = ({ activatorText, selected, options, minWidth, maxWidth, preferredAlignment = 'right', onSelect, }) => {
|
|
844
|
-
const [popoverActive, setPopoverActive] = useState(false);
|
|
845
|
-
const [itemHover, setItemHover] = useState(null);
|
|
846
|
-
const togglePopoverActive = () => setPopoverActive((prev) => !prev);
|
|
847
|
-
const selectedOption = useMemo(() => {
|
|
848
|
-
return options.find((item) => item.id === selected);
|
|
849
|
-
}, [options, selected]);
|
|
850
|
-
const activatorContent = useMemo(() => {
|
|
851
|
-
if (selectedOption) {
|
|
852
|
-
const content = selectedOption.title ?? selectedOption.content;
|
|
853
|
-
return activatorText ? `${activatorText}: ${content}` : content;
|
|
854
|
-
}
|
|
855
|
-
return activatorText;
|
|
856
|
-
}, [selectedOption, activatorText]);
|
|
857
|
-
const handleSelect = (value) => {
|
|
858
|
-
onSelect(value);
|
|
859
|
-
setPopoverActive(false);
|
|
860
|
-
};
|
|
861
|
-
return (jsx(Popover, { active: popoverActive, activator: jsx(GActivatorPopover, { active: popoverActive, content: activatorContent, textProps: { variant: 'bodySm' }, onClick: togglePopoverActive }), autofocusTarget: "first-node", fluidContent: true, onClose: togglePopoverActive, preferredAlignment: preferredAlignment, children: jsx(Box, { maxWidth: maxWidth, minWidth: minWidth, padding: "200", children: jsx(BlockStack, { gap: "200", children: options.map((option) => {
|
|
862
|
-
const isSelected = option.id === selected;
|
|
863
|
-
const isHover = itemHover === option.id;
|
|
864
|
-
const borderColor = isSelected ? 'input-border' : isHover ? 'border-hover' : 'transparent';
|
|
865
|
-
return (jsx(Box, { padding: "150", borderWidth: "025", borderColor: borderColor, borderRadius: "100", children: jsx("div", { onClick: () => handleSelect(option.id), className: "cursor-pointer", onMouseEnter: () => setItemHover(option.id), onMouseLeave: () => setItemHover(null), children: jsxs(InlineStack, { gap: "300", align: "space-between", blockAlign: "center", wrap: false, children: [jsxs(InlineStack, { gap: "300", blockAlign: "center", wrap: false, children: [jsx("div", { className: "bg-surface-secondary flex items-center justify-center rounded-md min-w-[184px] h-[92px]", children: jsx("img", { src: option.icon, alt: option.content, className: "w-full h-full object-contain" }) }), jsxs(BlockStack, { gap: "100", children: [jsx(Text, { as: "span", variant: "bodyMd", fontWeight: "semibold", children: option.content }), jsx(Text, { as: "p", variant: "bodyMd", tone: "subdued", children: option.helpText })] })] }), isSelected && (jsx(Box, { children: jsx(Icon, { source: SvgCheckIcon }) }))] }) }) }, option.id));
|
|
866
|
-
}) }) }) }));
|
|
867
|
-
};
|
|
868
|
-
|
|
869
|
-
const ChoiceHelpText = ({ item }) => {
|
|
870
|
-
return (jsxs(Text, { as: "p", variant: "bodyMd", children: [item.description, item.inlineAction && (jsx(Link, { monochrome: true, onClick: () => {
|
|
871
|
-
if (item.inlineAction?.onAction) {
|
|
872
|
-
item.inlineAction?.onAction();
|
|
873
|
-
}
|
|
874
|
-
else {
|
|
875
|
-
window.open(item.inlineAction?.url, item.inlineAction?.target ?? '_blank');
|
|
876
|
-
}
|
|
877
|
-
}, children: item.inlineAction?.content }))] }));
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
const GChartSkeleton = () => {
|
|
881
|
-
return jsx(GSkeletonDisplayText, { height: "188px" });
|
|
882
|
-
};
|
|
883
|
-
|
|
884
|
-
const useCurrencyRatesStore = create((set) => ({
|
|
885
|
-
currencyRates: null,
|
|
886
|
-
setCurrencyRates: (rates) => set({ currencyRates: rates }),
|
|
887
|
-
}));
|
|
888
|
-
|
|
889
|
-
const SHOPIFY_CURRENCIES_URL = 'https://cdn.shopify.com/s/javascripts/currencies.js';
|
|
890
|
-
const parseCurrencyRates = (scriptText) => {
|
|
891
|
-
const rates = {};
|
|
892
|
-
const match = /var Currency=\{rates:\{(.*?)\}\};/s.exec(scriptText);
|
|
893
|
-
const ratesStr = match?.[1];
|
|
894
|
-
if (!ratesStr)
|
|
895
|
-
return rates;
|
|
896
|
-
const ratePattern = /([A-Z]+):\s*([\d.e+-]+),/g;
|
|
897
|
-
let m;
|
|
898
|
-
while ((m = ratePattern.exec(ratesStr)) !== null) {
|
|
899
|
-
const [, code, value] = m;
|
|
900
|
-
if (code && value)
|
|
901
|
-
rates[code] = parseFloat(value);
|
|
902
|
-
}
|
|
903
|
-
return rates;
|
|
904
|
-
};
|
|
905
|
-
const fetchCurrencyRates = async () => {
|
|
906
|
-
const res = await fetch(SHOPIFY_CURRENCIES_URL);
|
|
907
|
-
if (!res.ok)
|
|
908
|
-
throw new Error('Failed to fetch currency rates');
|
|
909
|
-
const text = await res.text();
|
|
910
|
-
return parseCurrencyRates(text);
|
|
911
|
-
};
|
|
912
|
-
const useFetchCurrencyRates = () => {
|
|
913
|
-
const setCurrencyRates = useCurrencyRatesStore((state) => state.setCurrencyRates);
|
|
914
|
-
const { data } = useQuery({
|
|
915
|
-
queryKey: ['sdk-currency-rates'],
|
|
916
|
-
queryFn: fetchCurrencyRates,
|
|
917
|
-
staleTime: 1000 * 60 * 60, // 1 hour — rates don't change often
|
|
918
|
-
});
|
|
919
|
-
useEffect(() => {
|
|
920
|
-
if (data)
|
|
921
|
-
setCurrencyRates(data);
|
|
922
|
-
}, [data, setCurrencyRates]);
|
|
923
|
-
};
|
|
924
|
-
|
|
925
|
-
const getPriceByCurrency = (price, currency = DEFAULT_CURRENCY_ANALYTIC, options) => {
|
|
926
|
-
if (typeof price === 'string')
|
|
927
|
-
return price;
|
|
928
|
-
if (typeof price !== 'number')
|
|
929
|
-
return;
|
|
930
|
-
// Support legacy 3rd arg as locale string
|
|
931
|
-
const opts = typeof options === 'string' ? { locale: options } : options;
|
|
932
|
-
const locale = opts?.locale ?? 'en-US';
|
|
933
|
-
if (price >= 1_000_000_000) {
|
|
934
|
-
return `${new Intl.NumberFormat(locale, {
|
|
935
|
-
style: 'currency',
|
|
936
|
-
currency,
|
|
937
|
-
minimumFractionDigits: 2,
|
|
938
|
-
maximumFractionDigits: 2,
|
|
939
|
-
}).format(price / 1_000_000_000)}B`;
|
|
940
|
-
}
|
|
941
|
-
if (price >= 1_000_000) {
|
|
942
|
-
return `${new Intl.NumberFormat(locale, {
|
|
943
|
-
style: 'currency',
|
|
944
|
-
currency,
|
|
945
|
-
minimumFractionDigits: 2,
|
|
946
|
-
maximumFractionDigits: 2,
|
|
947
|
-
}).format(price / 1_000_000)}M`;
|
|
948
|
-
}
|
|
949
|
-
if (opts?.compact && Math.abs(price) >= 1_000) {
|
|
950
|
-
return `${new Intl.NumberFormat(locale, {
|
|
951
|
-
style: 'currency',
|
|
952
|
-
currency,
|
|
953
|
-
minimumFractionDigits: 1,
|
|
954
|
-
maximumFractionDigits: 1,
|
|
955
|
-
}).format(price / 1_000)}K`;
|
|
956
|
-
}
|
|
957
|
-
return new Intl.NumberFormat(locale, {
|
|
958
|
-
style: 'currency',
|
|
959
|
-
currency,
|
|
960
|
-
}).format(price);
|
|
961
|
-
};
|
|
962
|
-
|
|
963
|
-
const ConvertMoneyContext = createContext({
|
|
964
|
-
getTextPrice: (price) => {
|
|
965
|
-
if (typeof price === 'string')
|
|
966
|
-
return price;
|
|
967
|
-
return `${price ?? 0}`;
|
|
968
|
-
},
|
|
969
|
-
});
|
|
970
|
-
const convertAmount = (amount, from, to, rates) => {
|
|
971
|
-
if (from === to || !rates[from] || !rates[to])
|
|
972
|
-
return amount;
|
|
973
|
-
const converted = (amount * rates[from]) / rates[to];
|
|
974
|
-
return converted ? Number(converted.toFixed(2)) : amount;
|
|
975
|
-
};
|
|
976
|
-
const ConvertMoneyProvider = ({ children, currency, locale = 'en-US' }) => {
|
|
977
|
-
useFetchCurrencyRates();
|
|
978
|
-
const currencyRates = useCurrencyRatesStore((state) => state.currencyRates);
|
|
979
|
-
const getTextPrice = useCallback((price, _hasCurrency, options) => {
|
|
980
|
-
if (typeof price === 'string')
|
|
981
|
-
return price;
|
|
982
|
-
if (typeof price !== 'number')
|
|
983
|
-
return '0';
|
|
984
|
-
if (!currency)
|
|
985
|
-
return price.toString();
|
|
986
|
-
const converted = currencyRates
|
|
987
|
-
? convertAmount(price, DEFAULT_CURRENCY_ANALYTIC, currency, currencyRates)
|
|
988
|
-
: price;
|
|
989
|
-
return trimDecimalZeros(getPriceByCurrency(converted, currency, { locale, compact: options?.compact }) ?? '0');
|
|
990
|
-
}, [currency, locale, currencyRates]);
|
|
991
|
-
const value = useMemo(() => ({ getTextPrice }), [getTextPrice]);
|
|
992
|
-
return jsx(ConvertMoneyContext.Provider, { value: value, children: children });
|
|
993
|
-
};
|
|
994
|
-
const useConvertMoneyContext = () => useContext(ConvertMoneyContext);
|
|
995
|
-
|
|
996
|
-
const LINE_SERIES_COLORS = {
|
|
997
|
-
comparison: SERIES_COLORS.comparison,
|
|
998
|
-
single: SERIES_COLORS.current,
|
|
999
|
-
all: [...SERIES_COLORS.all],
|
|
1000
|
-
};
|
|
1001
|
-
const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesColors = LINE_SERIES_COLORS, }) => {
|
|
1002
|
-
return (jsxs(Fragment, { children: [jsx("link", { rel: "stylesheet", href: chartStyle }), jsx(PolarisVizProvider, { themes: {
|
|
1003
|
-
Light: {
|
|
1004
|
-
chartContainer: {
|
|
1005
|
-
minHeight,
|
|
1006
|
-
},
|
|
1007
|
-
grid: {
|
|
1008
|
-
horizontalOverflow: true,
|
|
1009
|
-
verticalOverflow: true,
|
|
1010
|
-
horizontalMargin: 0,
|
|
1011
|
-
},
|
|
1012
|
-
seriesColors,
|
|
1013
|
-
},
|
|
1014
|
-
}, children: children })] }));
|
|
1015
|
-
};
|
|
1016
|
-
|
|
1017
126
|
const NONE_VALUE = 'None';
|
|
1018
|
-
const PLACEHOLDER_VALUE = '-';
|
|
127
|
+
const PLACEHOLDER_VALUE$1 = '-';
|
|
1019
128
|
|
|
1020
129
|
const TOTALS_SUFFIX = '___totals';
|
|
1021
130
|
const COMPARE_PREFIX = 'comparison___';
|
|
@@ -1049,12 +158,42 @@ var EAnalyticColumnKey;
|
|
|
1049
158
|
EAnalyticColumnKey["TRAFFIC_SOURCE_ITEMS"] = "traffic_source_items";
|
|
1050
159
|
})(EAnalyticColumnKey || (EAnalyticColumnKey = {}));
|
|
1051
160
|
|
|
161
|
+
var EAnalyticMode;
|
|
162
|
+
(function (EAnalyticMode) {
|
|
163
|
+
EAnalyticMode["ALL_SESSION"] = "ALL_SESSION";
|
|
164
|
+
EAnalyticMode["FIRST_SESSION"] = "FIRST_SESSION";
|
|
165
|
+
EAnalyticMode["PAGE_ONLY"] = "PAGE_ONLY";
|
|
166
|
+
})(EAnalyticMode || (EAnalyticMode = {}));
|
|
167
|
+
|
|
1052
168
|
var EAnalyticSource;
|
|
1053
169
|
(function (EAnalyticSource) {
|
|
1054
170
|
EAnalyticSource["SESSIONS"] = "sessions";
|
|
1055
171
|
EAnalyticSource["SALES"] = "sales";
|
|
1056
172
|
})(EAnalyticSource || (EAnalyticSource = {}));
|
|
1057
173
|
|
|
174
|
+
var EVisitorType;
|
|
175
|
+
(function (EVisitorType) {
|
|
176
|
+
EVisitorType["NEW"] = "new";
|
|
177
|
+
EVisitorType["RETURNING"] = "returning";
|
|
178
|
+
})(EVisitorType || (EVisitorType = {}));
|
|
179
|
+
var EDeviceType;
|
|
180
|
+
(function (EDeviceType) {
|
|
181
|
+
EDeviceType["DESKTOP"] = "desktop";
|
|
182
|
+
EDeviceType["MOBILE"] = "mobile";
|
|
183
|
+
EDeviceType["TABLET"] = "tablet";
|
|
184
|
+
})(EDeviceType || (EDeviceType = {}));
|
|
185
|
+
var ETrafficSourceType;
|
|
186
|
+
(function (ETrafficSourceType) {
|
|
187
|
+
ETrafficSourceType["DIRECT"] = "direct";
|
|
188
|
+
ETrafficSourceType["EMAIL"] = "email";
|
|
189
|
+
ETrafficSourceType["REFERRAL"] = "referral";
|
|
190
|
+
ETrafficSourceType["ORGANIC_SOCIAL"] = "organic-social";
|
|
191
|
+
ETrafficSourceType["ORGANIC_SEARCH"] = "organic-search";
|
|
192
|
+
ETrafficSourceType["PAID_SOCIAL"] = "paid-social";
|
|
193
|
+
ETrafficSourceType["PAID_SEARCH"] = "paid-search";
|
|
194
|
+
ETrafficSourceType["SMS"] = "sms";
|
|
195
|
+
})(ETrafficSourceType || (ETrafficSourceType = {}));
|
|
196
|
+
|
|
1058
197
|
var EComparisonOperator;
|
|
1059
198
|
(function (EComparisonOperator) {
|
|
1060
199
|
EComparisonOperator["EQ"] = "=";
|
|
@@ -1161,6 +300,175 @@ var ETimeDimension;
|
|
|
1161
300
|
[ERowReaderMode.COMPARISON_TOTALS]: { prefix: COMPARE_PREFIX, suffix: COMPARE_TOTALS_SUFFIX },
|
|
1162
301
|
});
|
|
1163
302
|
|
|
303
|
+
EGroupOperator.OR;
|
|
304
|
+
|
|
305
|
+
[
|
|
306
|
+
{
|
|
307
|
+
operator: EOperatorField.DEVICE_OPERATOR,
|
|
308
|
+
singleField: EFilterField.DEVICE,
|
|
309
|
+
multiField: EFilterField.DEVICES,
|
|
310
|
+
fieldName: EFilterField.DEVICE,
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
operator: EOperatorField.VISITOR_OPERATOR,
|
|
314
|
+
singleField: EFilterField.VISITOR,
|
|
315
|
+
multiField: EFilterField.VISITORS,
|
|
316
|
+
fieldName: EFilterField.VISITOR,
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
operator: EOperatorField.TRAFFIC_SOURCE_OPERATOR,
|
|
320
|
+
singleField: EFilterField.TRAFFIC_SOURCE,
|
|
321
|
+
multiField: EFilterField.TRAFFIC_SOURCES,
|
|
322
|
+
fieldName: EFilterField.TRAFFIC_SOURCE,
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
operator: EOperatorField.VERSION_OPERATOR,
|
|
326
|
+
singleField: EFilterField.VERSION,
|
|
327
|
+
multiField: EFilterField.VERSIONS,
|
|
328
|
+
fieldName: EFilterField.VERSION,
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
operator: EOperatorField.PAGE_OPERATOR,
|
|
332
|
+
singleField: EFilterField.SINGLE_PAGE,
|
|
333
|
+
multiField: EFilterField.LIST_PAGE,
|
|
334
|
+
fieldName: EFilterField.SINGLE_PAGE,
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
operator: EOperatorField.CAMPAIGN_ITEM_OPERATOR,
|
|
338
|
+
singleField: EFilterField.GROUP_CAMPAIGN_ITEM,
|
|
339
|
+
multiField: EFilterField.GROUP_CAMPAIGN_ITEMS,
|
|
340
|
+
condition: EFilterField.GROUP_CAMPAIGN,
|
|
341
|
+
fieldName: EFilterField.SINGLE_CAMPAIGN,
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
operatorVal: OPERATOR_IS,
|
|
345
|
+
singleField: EFilterField.SINGLE_CAMPAIGN,
|
|
346
|
+
multiField: EFilterField.GROUP_CAMPAIGN,
|
|
347
|
+
},
|
|
348
|
+
];
|
|
349
|
+
|
|
350
|
+
dayjs.extend(utc);
|
|
351
|
+
dayjs.extend(timezone);
|
|
352
|
+
dayjs.extend(quarterOfYear);
|
|
353
|
+
let tz = 'UTC';
|
|
354
|
+
const dayjsTz = (date) => {
|
|
355
|
+
if (!date)
|
|
356
|
+
return dayjs().tz(tz);
|
|
357
|
+
return dayjs(date).tz(tz);
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const TRIM_DECIMAL_ZEROS_REGEX = /\.0+$/;
|
|
361
|
+
const DEFAULT_DECIMALS = 2;
|
|
362
|
+
const trimDecimalZeros = (number) => {
|
|
363
|
+
return `${number}`.replace(TRIM_DECIMAL_ZEROS_REGEX, '');
|
|
364
|
+
};
|
|
365
|
+
const cleanDecimal = (number, decimals = DEFAULT_DECIMALS) => {
|
|
366
|
+
return trimDecimalZeros(number.toFixed(decimals));
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Utility function to calculate percentage and format it.
|
|
371
|
+
* @param part - The part value.
|
|
372
|
+
* @param total - The total value.
|
|
373
|
+
* @param decimals - The number of decimal places to format the percentage to.
|
|
374
|
+
* @returns The formatted percentage as a string.
|
|
375
|
+
*/
|
|
376
|
+
const PERCENTAGE_THRESHOLD = 0.005;
|
|
377
|
+
const PERCENTAGE_THRESHOLD_STRING = '~0%';
|
|
378
|
+
const calcPercentage = (part, total, decimals = DEFAULT_DECIMALS) => {
|
|
379
|
+
if (typeof part !== 'number' || !total)
|
|
380
|
+
return undefined;
|
|
381
|
+
if (part === 0)
|
|
382
|
+
return 0;
|
|
383
|
+
const percentage = (part / total) * 100;
|
|
384
|
+
return parseFloat(cleanDecimal(percentage, decimals));
|
|
385
|
+
};
|
|
386
|
+
const isLessThanThreshold = (percentage) => percentage > 0 && percentage < PERCENTAGE_THRESHOLD;
|
|
387
|
+
const calcPercentageString = (part, total, decimals = 2) => {
|
|
388
|
+
const percentage = calcPercentage(part, total, decimals);
|
|
389
|
+
if (typeof percentage !== 'number')
|
|
390
|
+
return undefined;
|
|
391
|
+
if (isLessThanThreshold(percentage)) {
|
|
392
|
+
return PERCENTAGE_THRESHOLD_STRING;
|
|
393
|
+
}
|
|
394
|
+
return `${percentage}%`;
|
|
395
|
+
};
|
|
396
|
+
const formatPercentage = (percentage, decimals = DEFAULT_DECIMALS) => {
|
|
397
|
+
if (isLessThanThreshold(percentage)) {
|
|
398
|
+
return PERCENTAGE_THRESHOLD_STRING;
|
|
399
|
+
}
|
|
400
|
+
return `${cleanDecimal(percentage, decimals)}%`;
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
var AnalyticInterval;
|
|
404
|
+
(function (AnalyticInterval) {
|
|
405
|
+
AnalyticInterval["DAY"] = "DAY";
|
|
406
|
+
AnalyticInterval["HOUR"] = "HOUR";
|
|
407
|
+
AnalyticInterval["MONTH"] = "MONTH";
|
|
408
|
+
AnalyticInterval["QUARTER"] = "QUARTER";
|
|
409
|
+
AnalyticInterval["WEEK"] = "WEEK";
|
|
410
|
+
AnalyticInterval["YEAR"] = "YEAR";
|
|
411
|
+
})(AnalyticInterval || (AnalyticInterval = {}));
|
|
412
|
+
function numberWithCommas(x) {
|
|
413
|
+
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
414
|
+
}
|
|
415
|
+
const SECONDS_IN_MINUTE = 60;
|
|
416
|
+
const SECONDS_IN_HOUR = SECONDS_IN_MINUTE * SECONDS_IN_MINUTE;
|
|
417
|
+
const getTimeDurationLabel = (valueInSeconds) => {
|
|
418
|
+
let data = valueInSeconds;
|
|
419
|
+
if (!Number.isFinite(valueInSeconds) || valueInSeconds == null) {
|
|
420
|
+
data = 0;
|
|
421
|
+
}
|
|
422
|
+
const fixedValue = cleanDecimal(data);
|
|
423
|
+
if (data >= SECONDS_IN_HOUR) {
|
|
424
|
+
const hours = Math.floor(data / SECONDS_IN_HOUR);
|
|
425
|
+
const minutes = Math.floor((data % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE);
|
|
426
|
+
const seconds = Math.floor(data % SECONDS_IN_MINUTE);
|
|
427
|
+
return `${hours}h ${minutes}m ${seconds}s`;
|
|
428
|
+
}
|
|
429
|
+
else if (data >= SECONDS_IN_MINUTE) {
|
|
430
|
+
const minutes = Math.floor(data / SECONDS_IN_MINUTE);
|
|
431
|
+
const seconds = Math.floor(data % SECONDS_IN_MINUTE);
|
|
432
|
+
return `${minutes}m ${seconds}s`;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
return `${fixedValue}s`;
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
const getFormattedByInterval = (value, interval, options) => {
|
|
439
|
+
if (!value)
|
|
440
|
+
return '';
|
|
441
|
+
const optionFormat = options?.isExpandDetail
|
|
442
|
+
? {
|
|
443
|
+
formatHouse: 'MMM D, h:mm A',
|
|
444
|
+
formatDay: 'MMM D, YYYY',
|
|
445
|
+
formatMonth: 'MMM YYYY',
|
|
446
|
+
formatYear: 'MMM YYYY',
|
|
447
|
+
}
|
|
448
|
+
: {
|
|
449
|
+
formatHouse: 'h A',
|
|
450
|
+
formatDay: 'MMM D',
|
|
451
|
+
formatMonth: 'MMM YYYY',
|
|
452
|
+
formatYear: 'YYYY',
|
|
453
|
+
};
|
|
454
|
+
switch (interval) {
|
|
455
|
+
case AnalyticInterval.HOUR:
|
|
456
|
+
return dayjsTz(value).format(optionFormat.formatHouse);
|
|
457
|
+
case AnalyticInterval.DAY:
|
|
458
|
+
case AnalyticInterval.WEEK:
|
|
459
|
+
return dayjsTz(value).format(optionFormat.formatDay);
|
|
460
|
+
case AnalyticInterval.MONTH:
|
|
461
|
+
return dayjsTz(value).format(optionFormat.formatMonth);
|
|
462
|
+
case AnalyticInterval.QUARTER: {
|
|
463
|
+
const d = dayjsTz(value);
|
|
464
|
+
return `Q${d.quarter()} ${d.format('YYYY')}`;
|
|
465
|
+
}
|
|
466
|
+
case AnalyticInterval.YEAR:
|
|
467
|
+
return dayjsTz(value).format(optionFormat.formatYear);
|
|
468
|
+
}
|
|
469
|
+
return dayjsTz(value).format(optionFormat.formatMonth);
|
|
470
|
+
};
|
|
471
|
+
|
|
1164
472
|
const formatAnalyticDate = (dateString) => {
|
|
1165
473
|
if (!dateString)
|
|
1166
474
|
return 'None';
|
|
@@ -1240,62 +548,235 @@ const formatAnalyticData = ({ value, formatter, getTextPrice, name, }) => {
|
|
|
1240
548
|
}
|
|
1241
549
|
};
|
|
1242
550
|
|
|
1243
|
-
const SESSION_KEY = 'sessions';
|
|
1244
|
-
const hasMetricData = (metric) => {
|
|
1245
|
-
const sessions = metric?.[SESSION_KEY];
|
|
1246
|
-
return typeof sessions === 'number' && sessions > 0;
|
|
551
|
+
const SESSION_KEY = 'sessions';
|
|
552
|
+
const hasMetricData = (metric) => {
|
|
553
|
+
const sessions = metric?.[SESSION_KEY];
|
|
554
|
+
return typeof sessions === 'number' && sessions > 0;
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const parseRawJson = (raw) => {
|
|
558
|
+
if (!raw)
|
|
559
|
+
return undefined;
|
|
560
|
+
return typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
561
|
+
};
|
|
562
|
+
const parseJsonArray = (raw) => {
|
|
563
|
+
try {
|
|
564
|
+
const parsed = parseRawJson(raw);
|
|
565
|
+
if (!Array.isArray(parsed))
|
|
566
|
+
return undefined;
|
|
567
|
+
return parsed;
|
|
568
|
+
}
|
|
569
|
+
catch {
|
|
570
|
+
return undefined;
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
const parseBreakdownItems = (raw) => parseJsonArray(raw)?.map((item) => ({ ...item, total: Number(item.total) }));
|
|
574
|
+
|
|
575
|
+
const readNumeric = (metric, key) => {
|
|
576
|
+
const raw = metric?.[key];
|
|
577
|
+
return typeof raw === 'number' ? raw : 0;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
const useAnalyticData = (getTextPrice) => {
|
|
581
|
+
const formatData = ({ value, formatter, name }) => {
|
|
582
|
+
return formatAnalyticData({ value, formatter, getTextPrice, name });
|
|
583
|
+
};
|
|
584
|
+
const computeMetric = ({ metric, previousMetric, metricKey, formatter, }) => {
|
|
585
|
+
if (!hasMetricData(metric))
|
|
586
|
+
return { value: 0, change: PLACEHOLDER_VALUE$1 };
|
|
587
|
+
const currentValue = readNumeric(metric, metricKey);
|
|
588
|
+
const previousValue = readNumeric(previousMetric, metricKey);
|
|
589
|
+
const value = formatData({ value: currentValue, formatter, name: metricKey });
|
|
590
|
+
if (currentValue === 0 && previousValue !== 0)
|
|
591
|
+
return { value, change: -100 };
|
|
592
|
+
if (previousValue === 0)
|
|
593
|
+
return { value, change: PLACEHOLDER_VALUE$1 };
|
|
594
|
+
const change = ((currentValue - previousValue) / previousValue) * 100;
|
|
595
|
+
return { value, change };
|
|
596
|
+
};
|
|
597
|
+
return { formatData, computeMetric };
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
var GPaginationDirection;
|
|
601
|
+
(function (GPaginationDirection) {
|
|
602
|
+
GPaginationDirection["NEXT"] = "NEXT";
|
|
603
|
+
GPaginationDirection["PREV"] = "PREV";
|
|
604
|
+
})(GPaginationDirection || (GPaginationDirection = {}));
|
|
605
|
+
|
|
606
|
+
const TARGET_VISITOR = [
|
|
607
|
+
{ value: EVisitorType.NEW, label: 'New' },
|
|
608
|
+
{ value: EVisitorType.RETURNING, label: 'Returning' },
|
|
609
|
+
];
|
|
610
|
+
const TARGET_DEVICES = [
|
|
611
|
+
{ value: EDeviceType.DESKTOP, label: 'Desktop' },
|
|
612
|
+
{ value: EDeviceType.TABLET, label: 'Tablet' },
|
|
613
|
+
{ value: EDeviceType.MOBILE, label: 'Mobile' },
|
|
614
|
+
];
|
|
615
|
+
const TARGET_CHANNEL = [
|
|
616
|
+
{ value: ETrafficSourceType.DIRECT, label: 'Direct' },
|
|
617
|
+
{ value: ETrafficSourceType.EMAIL, label: 'Email' },
|
|
618
|
+
{ value: ETrafficSourceType.REFERRAL, label: 'Referral' },
|
|
619
|
+
{ value: ETrafficSourceType.ORGANIC_SOCIAL, label: 'Organic social' },
|
|
620
|
+
{ value: ETrafficSourceType.ORGANIC_SEARCH, label: 'Organic search' },
|
|
621
|
+
{ value: ETrafficSourceType.PAID_SOCIAL, label: 'Paid social' },
|
|
622
|
+
{ value: ETrafficSourceType.PAID_SEARCH, label: 'Paid search' },
|
|
623
|
+
{ value: ETrafficSourceType.SMS, label: 'SMS' },
|
|
624
|
+
];
|
|
625
|
+
|
|
626
|
+
const CAMPAIGN_BACKGROUND_MAIN = {
|
|
627
|
+
ORIGIN: '#2C7DFF',
|
|
628
|
+
VARIANT: '#F34A70',
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
const DEFAULT_CURRENT_PERIOD_LABEL = 'Current';
|
|
632
|
+
const DEFAULT_PREVIOUS_PERIOD_LABEL = 'Previous';
|
|
633
|
+
const CHART_MIN_HEIGHT = 228;
|
|
634
|
+
const SERIES_COLORS = {
|
|
635
|
+
current: 'rgba(64, 176, 230, 1)',
|
|
636
|
+
comparison: 'rgba(161, 202, 231, 1)',
|
|
637
|
+
all: ['#2C7DFF', '#F34A70'],
|
|
638
|
+
};
|
|
639
|
+
const TREND_TONE = {
|
|
640
|
+
POSITIVE: '#007F5F',
|
|
641
|
+
NEUTRAL: '#4A4A4A',
|
|
642
|
+
};
|
|
643
|
+
const PLACEHOLDER_VALUE = '-';
|
|
644
|
+
|
|
645
|
+
var THUMB_PRODUCT_DEFAULT = "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSI5MCIKICBoZWlnaHQ9IjcyIgogIHZpZXdCb3g9IjAgMCA5MCA3MiIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNDguNzUgMzQuNUM0OS45OTI2IDM0LjUgNTEgMzMuNDkyNiA1MSAzMi4yNUM1MSAzMS4wMDc0IDQ5Ljk5MjYgMzAgNDguNzUgMzBDNDcuNTA3NCAzMCA0Ni41IDMxLjAwNzQgNDYuNSAzMi4yNUM0Ni41IDMzLjQ5MjYgNDcuNTA3NCAzNC41IDQ4Ljc1IDM0LjVaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgogIDxwYXRoCiAgICBmaWxsUnVsZT0iZXZlbm9kZCIKICAgIGNsaXBSdWxlPSJldmVub2RkIgogICAgZD0iTTQzLjUyNjggMjYuMjVINDYuNDczMkM0Ny42OTI0IDI2LjI1IDQ4LjY3NTggMjYuMjUgNDkuNDcyMiAyNi4zMTVDNTAuMjkyMiAyNi4zODIgNTEuMDEyNCAyNi41MjM2IDUxLjY3ODcgMjYuODYzMUM1Mi43MzcxIDI3LjQwMjQgNTMuNTk3NiAyOC4yNjI5IDU0LjEzNjkgMjkuMzIxM0M1NC40NzY0IDI5Ljk4NzYgNTQuNjE4IDMwLjcwNzggNTQuNjg1IDMxLjUyNzhDNTQuNzUgMzIuMzI0MiA1NC43NSAzMy4zMDc2IDU0Ljc1IDM0LjUyNjhWMzcuNDczMkM1NC43NSAzOC42OTI0IDU0Ljc1IDM5LjY3NTggNTQuNjg1IDQwLjQ3MjJDNTQuNjE4IDQxLjI5MjIgNTQuNDc2NCA0Mi4wMTI0IDU0LjEzNjkgNDIuNjc4N0M1My41OTc2IDQzLjczNzEgNTIuNzM3MSA0NC41OTc2IDUxLjY3ODcgNDUuMTM2OUM1MS4wMTI0IDQ1LjQ3NjQgNTAuMjkyMiA0NS42MTggNDkuNDcyMiA0NS42ODVDNDguNjc1OCA0NS43NSA0Ny42OTI0IDQ1Ljc1IDQ2LjQ3MzIgNDUuNzVINDMuNTI2OEM0Mi4zMDc2IDQ1Ljc1IDQxLjMyNDIgNDUuNzUgNDAuNTI3OCA0NS42ODVDMzkuNzA3OCA0NS42MTggMzguOTg3NiA0NS40NzY0IDM4LjMyMTMgNDUuMTM2OUMzNy4yNjI5IDQ0LjU5NzYgMzYuNDAyNCA0My43MzcxIDM1Ljg2MzEgNDIuNjc4N0MzNS41MjM2IDQyLjAxMjQgMzUuMzgyIDQxLjI5MjIgMzUuMzE1IDQwLjQ3MjJDMzUuMjUgMzkuNjc1OCAzNS4yNSAzOC42OTI0IDM1LjI1IDM3LjQ3MzJWMzQuNTI2OEMzNS4yNSAzMy4zMDc2IDM1LjI1IDMyLjMyNDIgMzUuMzE1IDMxLjUyNzhDMzUuMzgyIDMwLjcwNzggMzUuNTIzNiAyOS45ODc2IDM1Ljg2MzEgMjkuMzIxM0MzNi40MDI0IDI4LjI2MjkgMzcuMjYyOSAyNy40MDI0IDM4LjMyMTMgMjYuODYzMUMzOC45ODc2IDI2LjUyMzYgMzkuNzA3OCAyNi4zODIgNDAuNTI3OCAyNi4zMTVDNDEuMzI0MiAyNi4yNSA0Mi4zMDc2IDI2LjI1IDQzLjUyNjggMjYuMjVaTTQwLjcxMSAyOC41NTc2QzQwLjAzMDIgMjguNjEzMiAzOS42MzkxIDI4LjcxNjkgMzkuMzQyOCAyOC44Njc5QzM4LjcwNzcgMjkuMTkxNCAzOC4xOTE0IDI5LjcwNzcgMzcuODY3OSAzMC4zNDI4QzM3LjcxNjkgMzAuNjM5MSAzNy42MTMyIDMxLjAzMDIgMzcuNTU3NiAzMS43MTFDMzcuNTAwOSAzMi40MDUgMzcuNSAzMy4yOTYzIDM3LjUgMzQuNTc1VjM2LjcxNzdMMzguNTg0MiAzNS40MTY3QzM5LjU3MjQgMzQuMjMwOSA0MS4zNjU1IDM0LjE0OTYgNDIuNDU2OSAzNS4yNDFMNDYuNSAzOS4yODQxTDQ4LjI2OTQgMzcuNTE0NkM0OS4zNzU3IDM2LjQwODMgNTEuMTk4IDM2LjUwOTMgNTIuMTc1NCAzNy43MzA5TDUyLjQ5OTUgMzguMTM2MUM1Mi41IDM3LjkxMzEgNTIuNSAzNy42NzY1IDUyLjUgMzcuNDI1VjM0LjU3NUM1Mi41IDMzLjI5NjMgNTIuNDk5MSAzMi40MDUgNTIuNDQyNCAzMS43MTFDNTIuMzg2OCAzMS4wMzAyIDUyLjI4MzEgMzAuNjM5MSA1Mi4xMzIxIDMwLjM0MjhDNTEuODA4NiAyOS43MDc3IDUxLjI5MjMgMjkuMTkxNCA1MC42NTcyIDI4Ljg2NzlDNTAuMzYwOSAyOC43MTY5IDQ5Ljk2OTggMjguNjEzMiA0OS4yODkgMjguNTU3NkM0OC41OTUgMjguNTAwOSA0Ny43MDM3IDI4LjUgNDYuNDI1IDI4LjVINDMuNTc1QzQyLjI5NjMgMjguNSA0MS40MDUgMjguNTAwOSA0MC43MTEgMjguNTU3NlpNMzcuNTU3NiA0MC4yODlDMzcuNTU0MyA0MC4yNDkyIDM3LjU1MTMgNDAuMjA4OCAzNy41NDg0IDQwLjE2NzhDMzcuNTcxMSA0MC4xNDQ4IDM3LjU5MzEgNDAuMTIwNiAzNy42MTQyIDQwLjA5NTNMNDAuMzEyNyAzNi44NTcxQzQwLjQ1MzkgMzYuNjg3NyA0MC43MSAzNi42NzYxIDQwLjg2NTkgMzYuODMyTDQ1LjcwNDUgNDEuNjcwNkM0Ni4xNDM4IDQyLjEwOTkgNDYuODU2MSA0Mi4xMDk5IDQ3LjI5NTUgNDEuNjcwNkw0OS44NjA0IDM5LjEwNTZDNTAuMDE4NSAzOC45NDc2IDUwLjI3ODggMzguOTYyIDUwLjQxODQgMzkuMTM2NUw1Mi4yMzc3IDQxLjQxMDdDNTIuMjA1NiA0MS41MDEgNTIuMTcwNCA0MS41ODIyIDUyLjEzMjEgNDEuNjU3MkM1MS44MDg2IDQyLjI5MjMgNTEuMjkyMyA0Mi44MDg2IDUwLjY1NzIgNDMuMTMyMUM1MC4zNjA5IDQzLjI4MzEgNDkuOTY5OCA0My4zODY4IDQ5LjI4OSA0My40NDI0QzQ4LjU5NSA0My40OTkxIDQ3LjcwMzcgNDMuNSA0Ni40MjUgNDMuNUg0My41NzVDNDIuMjk2MyA0My41IDQxLjQwNSA0My40OTkxIDQwLjcxMSA0My40NDI0QzQwLjAzMDIgNDMuMzg2OCAzOS42MzkxIDQzLjI4MzEgMzkuMzQyOCA0My4xMzIxQzM4LjcwNzcgNDIuODA4NiAzOC4xOTE0IDQyLjI5MjMgMzcuODY3OSA0MS42NTcyQzM3LjcxNjkgNDEuMzYwOSAzNy42MTMyIDQwLjk2OTggMzcuNTU3NiA0MC4yODlaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgo8L3N2Zz4K";
|
|
646
|
+
|
|
647
|
+
const GBlockCenter = ({ height, align, inlineAlign, display, ...props }) => {
|
|
648
|
+
const stickyStyle = useMemo(() => {
|
|
649
|
+
if (props.position !== 'sticky')
|
|
650
|
+
return {};
|
|
651
|
+
const style = {
|
|
652
|
+
position: 'sticky',
|
|
653
|
+
};
|
|
654
|
+
if (props.insetInlineStart)
|
|
655
|
+
style.insetInlineStart = Number(props.insetInlineStart) * 4;
|
|
656
|
+
if (props.insetInlineEnd)
|
|
657
|
+
style.insetInlineEnd = Number(props.insetInlineEnd) * 4;
|
|
658
|
+
if (props.insetBlockStart)
|
|
659
|
+
style.insetBlockStart = Number(props.insetBlockStart) * 4;
|
|
660
|
+
if (props.insetBlockEnd)
|
|
661
|
+
style.insetBlockEnd = Number(props.insetBlockEnd) * 4;
|
|
662
|
+
return style;
|
|
663
|
+
}, [props.position, props.insetInlineStart, props.insetInlineEnd, props.insetBlockStart, props.insetBlockEnd]);
|
|
664
|
+
return (jsx("div", { className: "Polaris-GBlockCenter", style: {
|
|
665
|
+
...stickyStyle,
|
|
666
|
+
'--gp-block-center-height': height,
|
|
667
|
+
'--gp-block-center-display': display,
|
|
668
|
+
'--gp-block-center-align': align,
|
|
669
|
+
'--gp-block-center-inline-align': inlineAlign,
|
|
670
|
+
'--gp-block-center-overflow-x': props.overflowX,
|
|
671
|
+
'--gp-block-center-overflow-y': props.overflowY,
|
|
672
|
+
}, children: jsx(Box, { ...props }) }));
|
|
1247
673
|
};
|
|
1248
674
|
|
|
1249
|
-
const
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
return typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
675
|
+
const GSkeletonDisplayText = (props) => {
|
|
676
|
+
const height = props.height ?? '50px';
|
|
677
|
+
return (jsxs("div", { className: "Polaris-GSkeletonDisplayText", children: [jsx("style", { children: `.Polaris-GSkeletonDisplayText .Polaris-SkeletonDisplayText__DisplayText { height: ${height} !important; }` }), jsx(SkeletonDisplayText, { maxWidth: "100%", size: "extraLarge" })] }));
|
|
1253
678
|
};
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
return undefined;
|
|
1259
|
-
return parsed;
|
|
679
|
+
|
|
680
|
+
function toVal(mix) {
|
|
681
|
+
if (typeof mix === 'string') {
|
|
682
|
+
return mix;
|
|
1260
683
|
}
|
|
1261
|
-
|
|
1262
|
-
return
|
|
684
|
+
else if (typeof mix === 'object' && mix !== null) {
|
|
685
|
+
return Object.keys(mix)
|
|
686
|
+
.filter((key) => mix[key])
|
|
687
|
+
.join(' ');
|
|
1263
688
|
}
|
|
1264
|
-
|
|
1265
|
-
|
|
689
|
+
else {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
function cls(...classes) {
|
|
694
|
+
return classes.map(toVal).filter(Boolean).join(' ');
|
|
695
|
+
}
|
|
1266
696
|
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
697
|
+
/**
|
|
698
|
+
* Helper function to generate a variation class name.
|
|
699
|
+
* @param name - Base name of the class.
|
|
700
|
+
* @param value - Variation value to append.
|
|
701
|
+
* @returns Combined class name.
|
|
702
|
+
*/
|
|
703
|
+
function variationName(name, value) {
|
|
704
|
+
return `${name}${value.charAt(0).toUpperCase()}${value.slice(1)}`;
|
|
705
|
+
}
|
|
706
|
+
const GThumbnail = ({ source, alt, size, grayscale, defaultSource = THUMB_PRODUCT_DEFAULT, width = '80', height = '80', classRemoved = false, }) => {
|
|
707
|
+
const sizeClass = size && variationName('Polaris-Thumbnail--size', size);
|
|
708
|
+
const filterClass = grayscale && 'Polaris-GThumbnail--filter';
|
|
709
|
+
const className = cls('Polaris-Thumbnail', sizeClass);
|
|
710
|
+
const thumbnail = (jsx("img", { onError: (e) => {
|
|
711
|
+
e.currentTarget.src = defaultSource;
|
|
712
|
+
}, alt: alt ?? 'Thumbnail', src: `${source ?? defaultSource}`, width: width, height: height, style: {
|
|
713
|
+
'--gp-grayscale-percentage': grayscale || '100%',
|
|
714
|
+
}, className: cls('Polaris-GThumbnail', filterClass) }));
|
|
715
|
+
if (classRemoved)
|
|
716
|
+
return thumbnail;
|
|
717
|
+
return jsx("span", { className: className, children: thumbnail });
|
|
1270
718
|
};
|
|
1271
719
|
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
720
|
+
const SIZE_CLASS = {
|
|
721
|
+
default: 'w-[210px]',
|
|
722
|
+
wide: 'w-[320px]',
|
|
723
|
+
large: 'w-[328px]',
|
|
724
|
+
};
|
|
725
|
+
const ALIGNMENT_MAP = {
|
|
726
|
+
start: 'flex justify-start',
|
|
727
|
+
center: 'flex justify-center',
|
|
728
|
+
end: 'flex justify-end',
|
|
729
|
+
};
|
|
730
|
+
const GTooltipCard = forwardRef((props, ref) => {
|
|
731
|
+
const { tooltip, wrapper = 'div', activatorProps, isHideBorder, alignment, delay = 500, textDecoration = 'none', popoverRef, preferredAlignment = 'left', showArrow = false, } = props;
|
|
732
|
+
const { width = 'default' } = tooltip ?? {};
|
|
733
|
+
const [isMouseEnter, setIsMouseEnter] = useState(false);
|
|
734
|
+
const TooltipCardWrapper = wrapper;
|
|
735
|
+
const sizeClass = SIZE_CLASS[width];
|
|
736
|
+
const timeoutRef = useRef(null);
|
|
737
|
+
const handleMouseEnter = () => {
|
|
738
|
+
timeoutRef.current = setTimeout(() => {
|
|
739
|
+
setIsMouseEnter(true);
|
|
740
|
+
}, delay);
|
|
1277
741
|
};
|
|
1278
|
-
const
|
|
1279
|
-
if (
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
if (currentValue === 0 && previousValue !== 0)
|
|
1285
|
-
return { value, change: -100 };
|
|
1286
|
-
if (previousValue === 0)
|
|
1287
|
-
return { value, change: PLACEHOLDER_VALUE };
|
|
1288
|
-
const change = ((currentValue - previousValue) / previousValue) * 100;
|
|
1289
|
-
return { value, change };
|
|
742
|
+
const handleMouseLeave = () => {
|
|
743
|
+
if (timeoutRef.current) {
|
|
744
|
+
clearTimeout(timeoutRef.current);
|
|
745
|
+
timeoutRef.current = null;
|
|
746
|
+
}
|
|
747
|
+
setIsMouseEnter(false);
|
|
1290
748
|
};
|
|
1291
|
-
|
|
749
|
+
useImperativeHandle(ref, () => ({ onClose: handleMouseLeave }));
|
|
750
|
+
return (jsx(TooltipCardWrapper, { className: cls('GTooltipCard cursor-pointer', alignment && ALIGNMENT_MAP[alignment], {
|
|
751
|
+
'GTooltipCard--text-underline': textDecoration === 'underline',
|
|
752
|
+
}), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: jsx(Popover, { ref: popoverRef, activator: !isHideBorder ? (jsx(Box, { borderBlockEndWidth: "025", borderStyle: "dashed", borderColor: "border-tertiary", as: wrapper, ...activatorProps, children: props.children })) : (jsx(InlineStack, { children: props.children })), activatorWrapper: wrapper, onClose: () => { }, active: isMouseEnter, preferredPosition: "below", preferredAlignment: preferredAlignment, children: tooltip && (jsx("div", { className: cls(sizeClass, { 'GTooltipCard-arrow': showArrow }), children: jsx(Box, { padding: "400", children: jsxs(BlockStack, { gap: "200", children: [jsxs(BlockStack, { gap: "100", children: [jsx(Text, { as: "span", variant: "headingSm", fontWeight: "semibold", children: tooltip.title }), jsxs(BlockStack, { gap: "200", children: [jsx(Text, { as: "span", variant: "bodyMd", tone: "subdued", fontWeight: "medium", children: jsx("span", { dangerouslySetInnerHTML: { __html: tooltip.content } }) }), tooltip.contentList && (jsx(List, { type: "bullet", children: tooltip.contentList.map((item) => (jsx(List.Item, { children: jsx(Text, { as: "span", variant: "bodyMd", tone: "subdued", fontWeight: "medium", children: item }) }, item))) }))] })] }), tooltip.formula && (jsx("div", { className: "rounded-md font-mono", style: { fontSize: '12px' }, children: tooltip.formula }))] }) }) })) }) }));
|
|
753
|
+
});
|
|
754
|
+
GTooltipCard.displayName = 'GTooltipCard';
|
|
755
|
+
|
|
756
|
+
const GChartSkeleton = () => {
|
|
757
|
+
return jsx(GSkeletonDisplayText, { height: "188px" });
|
|
1292
758
|
};
|
|
1293
759
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
}
|
|
760
|
+
const LINE_SERIES_COLORS = {
|
|
761
|
+
comparison: SERIES_COLORS.comparison,
|
|
762
|
+
single: SERIES_COLORS.current,
|
|
763
|
+
all: [...SERIES_COLORS.all],
|
|
764
|
+
};
|
|
765
|
+
const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesColors = LINE_SERIES_COLORS, }) => {
|
|
766
|
+
return (jsx(PolarisVizProvider, { themes: {
|
|
767
|
+
Light: {
|
|
768
|
+
chartContainer: {
|
|
769
|
+
minHeight,
|
|
770
|
+
},
|
|
771
|
+
grid: {
|
|
772
|
+
horizontalOverflow: true,
|
|
773
|
+
verticalOverflow: true,
|
|
774
|
+
horizontalMargin: 0,
|
|
775
|
+
},
|
|
776
|
+
seriesColors,
|
|
777
|
+
},
|
|
778
|
+
}, children: children }));
|
|
779
|
+
};
|
|
1299
780
|
|
|
1300
781
|
const useFormatLineChartData = ({ metricKey, columnTypes }) => {
|
|
1301
782
|
const { formatData } = useAnalyticData();
|
|
@@ -1311,20 +792,6 @@ const useFormatLineChartData = ({ metricKey, columnTypes }) => {
|
|
|
1311
792
|
return { formatValue, yAxisOptions };
|
|
1312
793
|
};
|
|
1313
794
|
|
|
1314
|
-
/**
|
|
1315
|
-
* Returns a stateful value, and a set of memoized functions to toggle it,
|
|
1316
|
-
* set it to true and set it to false
|
|
1317
|
-
*/
|
|
1318
|
-
function useToggle(initialState) {
|
|
1319
|
-
const [value, setState] = useState(initialState);
|
|
1320
|
-
return {
|
|
1321
|
-
value,
|
|
1322
|
-
toggle: useCallback(() => setState((state) => !state), []),
|
|
1323
|
-
setTrue: useCallback(() => setState(true), []),
|
|
1324
|
-
setFalse: useCallback(() => setState(false), []),
|
|
1325
|
-
};
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
795
|
const useWindowSize = () => {
|
|
1329
796
|
const [windowSize, setWindowSize] = useState(() => ({
|
|
1330
797
|
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
@@ -1413,7 +880,7 @@ const MetricChartTooltip = ({ data, formatValue }) => {
|
|
|
1413
880
|
const formatPercent = () => {
|
|
1414
881
|
const value = currentData.trend?.value;
|
|
1415
882
|
if (!value)
|
|
1416
|
-
return PLACEHOLDER_VALUE
|
|
883
|
+
return PLACEHOLDER_VALUE;
|
|
1417
884
|
const valueNumber = Number(value.replace(/[%~]/g, ''));
|
|
1418
885
|
if (currentData.trend?.trend === 'negative') {
|
|
1419
886
|
return valueNumber * -1;
|
|
@@ -1434,90 +901,53 @@ const MetricDonutChartSkeleton = () => {
|
|
|
1434
901
|
return (jsx(Card, { children: jsxs(BlockStack, { gap: "400", children: [jsx(MetricInfoSkeleton, { isShowOneLine: true }), jsx(GChartSkeleton, {})] }) }));
|
|
1435
902
|
};
|
|
1436
903
|
|
|
904
|
+
var SvgChevronRightIcon = function SvgChevronRightIcon(props) {
|
|
905
|
+
return /*#__PURE__*/React.createElement("svg", Object.assign({
|
|
906
|
+
viewBox: "0 0 20 20"
|
|
907
|
+
}, props), /*#__PURE__*/React.createElement("path", {
|
|
908
|
+
fillRule: "evenodd",
|
|
909
|
+
d: "M7.72 14.53a.75.75 0 0 1 0-1.06l3.47-3.47-3.47-3.47a.75.75 0 0 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06 0Z"
|
|
910
|
+
}));
|
|
911
|
+
};
|
|
912
|
+
SvgChevronRightIcon.displayName = "ChevronRightIcon";
|
|
913
|
+
|
|
1437
914
|
const MetricValueSummary = ({ totalValue, hideComparison }) => (jsx(BlockStack, { gap: "200", children: jsxs(InlineStack, { blockAlign: "center", gap: "200", wrap: false, children: [jsx(InlineStack, { blockAlign: "center", gap: "200", children: jsx(Text, { as: "span", variant: "headingSm", children: totalValue.value }) }), !hideComparison && jsx(MetricPercentage, { change: totalValue.change })] }) }));
|
|
1438
915
|
|
|
1439
916
|
const MetricInfoBlock = ({ item, isHovered, isLoading, hideComparison, titleVariant = 'headingMd', titleFontWeight, onClickTitle, }) => {
|
|
1440
917
|
const { key, title, totalValue } = item;
|
|
1441
918
|
const tooltip = ANALYTICS_METRIC_TOOLTIP[key];
|
|
1442
|
-
if (isLoading)
|
|
1443
|
-
return jsx(MetricInfoSkeleton, {});
|
|
1444
|
-
return (jsxs(BlockStack, { gap: "200", children: [jsx("div", { className: "hover:cursor-pointer hover:text-[--p-color-text-link-hover]", onClick: (e) => {
|
|
1445
|
-
e?.stopPropagation();
|
|
1446
|
-
onClickTitle?.(key);
|
|
1447
|
-
}, children: jsxs(InlineStack, { wrap: false, children: [jsx(Box, { maxWidth: "100%", overflowX: "hidden", children: jsx(GTooltipCard, { tooltip: tooltip, children: jsx(Text, { as: "span", variant: titleVariant, fontWeight: titleFontWeight, truncate: true, children: title }) }) }), isHovered && (jsx("div", { className: "flex h-[20px] w-[20px] items-center", children: jsx(Icon, { source: SvgChevronRightIcon, tone: "inherit" }) }))] }) }), jsx(MetricValueSummary, { totalValue: totalValue, hideComparison: hideComparison })] }));
|
|
1448
|
-
};
|
|
1449
|
-
|
|
1450
|
-
const MetricChartTab = ({ item, isActive, isLoading, hideComparison, onSelect, onClickTitle, }) => {
|
|
1451
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
1452
|
-
const isHighlighted = isActive || isHovered;
|
|
1453
|
-
return (jsx("div", { className: "w-full cursor-pointer overflow-hidden", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onClick: () => onSelect(item.key), children: jsx(Box, { paddingBlock: "150", paddingInline: "300", borderRadius: "200", background: isHighlighted ? 'bg-surface-active' : undefined, children: jsx(MetricInfoBlock, { item: item, isHovered: isHovered, isLoading: isLoading, hideComparison: hideComparison, titleVariant: "headingSm", titleFontWeight: "semibold", onClickTitle: onClickTitle }) }) }));
|
|
1454
|
-
};
|
|
1455
|
-
|
|
1456
|
-
const GSelectableMetricChartCard = ({ metricInfo, dataChart, defaultActiveTab, isLoading, isEmptyMetricData, hideComparison, currentPeriodLabel = DEFAULT_CURRENT_PERIOD_LABEL, previousPeriodLabel = DEFAULT_PREVIOUS_PERIOD_LABEL, columnTypes, }) => {
|
|
1457
|
-
const [activeTab, setActiveTab] = useState(defaultActiveTab);
|
|
1458
|
-
const lineChartData = useMemo(() => {
|
|
1459
|
-
const chartData = activeTab ? dataChart[activeTab] : undefined;
|
|
1460
|
-
if (!chartData)
|
|
1461
|
-
return [];
|
|
1462
|
-
const currentSeries = { name: currentPeriodLabel, data: chartData.current };
|
|
1463
|
-
if (hideComparison)
|
|
1464
|
-
return [currentSeries];
|
|
1465
|
-
return [currentSeries, { name: previousPeriodLabel, data: chartData.previous, isComparison: true }];
|
|
1466
|
-
}, [activeTab, dataChart, hideComparison, currentPeriodLabel, previousPeriodLabel]);
|
|
1467
|
-
return (jsxs(Card, { children: [jsx("div", { style: {
|
|
1468
|
-
display: 'grid',
|
|
1469
|
-
gridTemplateColumns: `repeat(${metricInfo.length}, 1fr)`,
|
|
1470
|
-
gap: '16px',
|
|
1471
|
-
marginBottom: '16px',
|
|
1472
|
-
}, children: metricInfo.map((item) => (jsx(MetricChartTab, { item: item, isActive: activeTab === item.key, isLoading: isLoading, hideComparison: hideComparison, onSelect: setActiveTab }, item.key))) }), jsx(MetricChart, { lineChartData: lineChartData, isLoading: isLoading, isEmptyMetricData: isEmptyMetricData, metricKey: activeTab, columnTypes: columnTypes })] }));
|
|
1473
|
-
};
|
|
1474
|
-
|
|
1475
|
-
EGroupOperator.OR;
|
|
1476
|
-
|
|
1477
|
-
[
|
|
1478
|
-
{
|
|
1479
|
-
operator: EOperatorField.DEVICE_OPERATOR,
|
|
1480
|
-
singleField: EFilterField.DEVICE,
|
|
1481
|
-
multiField: EFilterField.DEVICES,
|
|
1482
|
-
fieldName: EFilterField.DEVICE,
|
|
1483
|
-
},
|
|
1484
|
-
{
|
|
1485
|
-
operator: EOperatorField.VISITOR_OPERATOR,
|
|
1486
|
-
singleField: EFilterField.VISITOR,
|
|
1487
|
-
multiField: EFilterField.VISITORS,
|
|
1488
|
-
fieldName: EFilterField.VISITOR,
|
|
1489
|
-
},
|
|
1490
|
-
{
|
|
1491
|
-
operator: EOperatorField.TRAFFIC_SOURCE_OPERATOR,
|
|
1492
|
-
singleField: EFilterField.TRAFFIC_SOURCE,
|
|
1493
|
-
multiField: EFilterField.TRAFFIC_SOURCES,
|
|
1494
|
-
fieldName: EFilterField.TRAFFIC_SOURCE,
|
|
1495
|
-
},
|
|
1496
|
-
{
|
|
1497
|
-
operator: EOperatorField.VERSION_OPERATOR,
|
|
1498
|
-
singleField: EFilterField.VERSION,
|
|
1499
|
-
multiField: EFilterField.VERSIONS,
|
|
1500
|
-
fieldName: EFilterField.VERSION,
|
|
1501
|
-
},
|
|
1502
|
-
{
|
|
1503
|
-
operator: EOperatorField.PAGE_OPERATOR,
|
|
1504
|
-
singleField: EFilterField.SINGLE_PAGE,
|
|
1505
|
-
multiField: EFilterField.LIST_PAGE,
|
|
1506
|
-
fieldName: EFilterField.SINGLE_PAGE,
|
|
1507
|
-
},
|
|
1508
|
-
{
|
|
1509
|
-
operator: EOperatorField.CAMPAIGN_ITEM_OPERATOR,
|
|
1510
|
-
singleField: EFilterField.GROUP_CAMPAIGN_ITEM,
|
|
1511
|
-
multiField: EFilterField.GROUP_CAMPAIGN_ITEMS,
|
|
1512
|
-
condition: EFilterField.GROUP_CAMPAIGN,
|
|
1513
|
-
fieldName: EFilterField.SINGLE_CAMPAIGN,
|
|
1514
|
-
},
|
|
1515
|
-
{
|
|
1516
|
-
operatorVal: OPERATOR_IS,
|
|
1517
|
-
singleField: EFilterField.SINGLE_CAMPAIGN,
|
|
1518
|
-
multiField: EFilterField.GROUP_CAMPAIGN,
|
|
1519
|
-
},
|
|
1520
|
-
];
|
|
919
|
+
if (isLoading)
|
|
920
|
+
return jsx(MetricInfoSkeleton, {});
|
|
921
|
+
return (jsxs(BlockStack, { gap: "200", children: [jsx("div", { className: "hover:cursor-pointer hover:text-[--p-color-text-link-hover]", onClick: (e) => {
|
|
922
|
+
e?.stopPropagation();
|
|
923
|
+
onClickTitle?.(key);
|
|
924
|
+
}, children: jsxs(InlineStack, { wrap: false, children: [jsx(Box, { maxWidth: "100%", overflowX: "hidden", children: jsx(GTooltipCard, { tooltip: tooltip, children: jsx(Text, { as: "span", variant: titleVariant, fontWeight: titleFontWeight, truncate: true, children: title }) }) }), isHovered && (jsx("div", { className: "flex h-[20px] w-[20px] items-center", children: jsx(Icon, { source: SvgChevronRightIcon, tone: "inherit" }) }))] }) }), jsx(MetricValueSummary, { totalValue: totalValue, hideComparison: hideComparison })] }));
|
|
925
|
+
};
|
|
926
|
+
|
|
927
|
+
const MetricChartTab = ({ item, isActive, isLoading, hideComparison, onSelect, onClickTitle, }) => {
|
|
928
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
929
|
+
const isHighlighted = isActive || isHovered;
|
|
930
|
+
return (jsx("div", { className: "w-full cursor-pointer overflow-hidden", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onClick: () => onSelect(item.key), children: jsx(Box, { paddingBlock: "150", paddingInline: "300", borderRadius: "200", background: isHighlighted ? 'bg-surface-active' : undefined, children: jsx(MetricInfoBlock, { item: item, isHovered: isHovered, isLoading: isLoading, hideComparison: hideComparison, titleVariant: "headingSm", titleFontWeight: "semibold", onClickTitle: onClickTitle }) }) }));
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
const GSelectableMetricChartCard = ({ metricInfo, dataChart, defaultActiveTab, isLoading, isEmptyMetricData, hideComparison, currentPeriodLabel = DEFAULT_CURRENT_PERIOD_LABEL, previousPeriodLabel = DEFAULT_PREVIOUS_PERIOD_LABEL, columnTypes, }) => {
|
|
934
|
+
const [activeTab, setActiveTab] = useState(defaultActiveTab);
|
|
935
|
+
const lineChartData = useMemo(() => {
|
|
936
|
+
const chartData = activeTab ? dataChart[activeTab] : undefined;
|
|
937
|
+
if (!chartData)
|
|
938
|
+
return [];
|
|
939
|
+
const currentSeries = { name: currentPeriodLabel, data: chartData.current };
|
|
940
|
+
if (hideComparison)
|
|
941
|
+
return [currentSeries];
|
|
942
|
+
return [currentSeries, { name: previousPeriodLabel, data: chartData.previous, isComparison: true }];
|
|
943
|
+
}, [activeTab, dataChart, hideComparison, currentPeriodLabel, previousPeriodLabel]);
|
|
944
|
+
return (jsxs(Card, { children: [jsx("div", { style: {
|
|
945
|
+
display: 'grid',
|
|
946
|
+
gridTemplateColumns: `repeat(${metricInfo.length}, 1fr)`,
|
|
947
|
+
gap: '16px',
|
|
948
|
+
marginBottom: '16px',
|
|
949
|
+
}, children: metricInfo.map((item) => (jsx(MetricChartTab, { item: item, isActive: activeTab === item.key, isLoading: isLoading, hideComparison: hideComparison, onSelect: setActiveTab }, item.key))) }), jsx(MetricChart, { lineChartData: lineChartData, isLoading: isLoading, isEmptyMetricData: isEmptyMetricData, metricKey: activeTab, columnTypes: columnTypes })] }));
|
|
950
|
+
};
|
|
1521
951
|
|
|
1522
952
|
const calculatePercentageChange = (current, previous) => {
|
|
1523
953
|
if (current === 0 && previous === 0) {
|
|
@@ -1588,1100 +1018,4 @@ const SingleMetricChartCard = ({ metricInfo, lineChartData, isLoading, hideCompa
|
|
|
1588
1018
|
return (jsx("div", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: jsx(Card, { children: jsxs(BlockStack, { gap: "200", children: [jsx(MetricInfoBlock, { item: metricInfo, isHovered: isHovered, isLoading: isLoading, hideComparison: hideComparison, onClickTitle: onClickTitle }), jsx(MetricChart, { lineChartData: lineChartData, isLoading: isLoading, isEmptyMetricData: isEmptyMetricData, columnTypes: columnTypes, metricKey: metricInfo.key })] }) }) }));
|
|
1589
1019
|
};
|
|
1590
1020
|
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
var IMAGE_ALL_SESSION = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXAAAAC4CAMAAADNC0dgAAAAw1BMVEUAAAD39/f39/f39/f39/f39/f39/f39/f8/Pz39/fb5P////+WrPjj4+MaHB319vfe5v/s7/rp7Ovy8vLx8/nn5+fu7u7n7PzKzdDi6f1wcXL7+/vEzOTGxscphFrd5Pni4+o2OTtTnHpjZnCcsfjQ2fby9/VEk2/f5PFSVFaktvd4spewwPd6gI9mboa6yPWGmt2pqqsuMTbW3OCSwavDz/iwvcJKVHOpqqrl6feLkaGMjo6bm5x+gIA8QUqOo+t3iMFQsBsaAAAACXRSTlMA779wIIDfnxC1qPNnAAAJI0lEQVR42uzWuw3AQAgEUe5nm/4btoMLHG12SCvNK2GEgNie1a/EIa2PGX+zJw67f8lHSxzXRmwrUWLt+U4UGfGZ7JMybUbEnSjTI2ai0MMGr7WCD7xUD05mqSsSpQiuEdwdwTWCuyO4RnB3BNcI7o7gGsHdEVwjuDuCawR3R3CN4O4IrhHcHcE1grsjuEZwdwTXCO6O4BrB3RFcI7g7gmsEd/eya4a9acNAGM5XQ5iJTcIQiLAKVkbpmEZbqfuy//+v5tR1XzqnF5JzDJP2fqlaqXfvPXc+pzT/gdP6D/xfVxjgUmotRZ+SulB5nqtCi6t0LPWZ8fjApVYjq1z1Bd2kgJS8Mse6yJ01LWjxgcvi1bnKX75qEV6yCq0KKV1txTU51jZMbsM1eGMD1y9tnQ8rzUVFI/yUV4BMCqeX7+W1OJZ2AGw8C5/oIIB3Z6HEEJprAgYjB3BXmpuy9HU4lnYYIJFTQ+6AM1joIUTD4OeAqh9eg2PTrdzihjRBHMD57gGDmBh+DlQlL+9YGrZ+OEkQZwHX1r0nNcpFKEnk8JJc3rFZT3XhJHFkOMDh3jujhQgk5UbIS4IxupjjAvuk4cjwgCPdsF7Cy8cYcJTkjVFfjvnmvAaGAG4KHn4g5eULOOAoSvfkmG+uSgWFAa4xLkQ+pmpm6OuDcvemiu+Y7h+kvGlgAzchvSy3N0Mr4tZgIvp6s3x62+KBHfP797A8Nk1Dwh8+uF8+uFsjzE4pRsrnffP1jZG8pGPzGz7vW9V0YpLu15nv/g43GhrMAq7reGPvRnVMHxjwpqchCXDa4R72c8EQapLY2+CNobyk43wkang75eGAT7LpbDwu3Wm/rRDAvZVgAn/eHPa7dbp4Bf5kSwFvAI/rGNEGg9Ur8KfbI3h7z1BM4DKbmVSVSjcvFgLcs4FPNvt1arVwp/bOFAPeWCmxHSPaCfDl8gjeQYFPpi4b7FsMcM9dKeXB0HY62HvJEj+CN2qK6hjRALxCbYiDd7gdPpkNTmXufPiHezwVdcK9T0+1t1vAEl+CN2qK5BjRoK09fpb4HXjjmZUFXCIdGvzmH+45f2pmFje0NoxAHLyxBKI5RjQAV7guwRsHhgU8G/v5iqHzf+fco79StNbGLRPoePLo9Rm8cWdGcYxo3olxxG+UZ44DHO2FSuSDGCt8gvGu3SkQEEVxjGjeidGUOQZwOW6Zr8OnndkuhfwRhzBDKo5jPxpu4Y8aqNG/DsAnfj56YHT7T4KeLW9P+4+SSMxQz44RzW9gQQ04DbxDvi06zP1w+XmdfqAFkhD/fwjumI6GBopa3jlx+pIO+4TusACLc5U53r7WxzpIAiX17RjRfG3rj4xC/wjgHfKVq5Ga17hX/P0N7WqIa+TozzGikcSFN9/g3QW4uZ9J/7l4n61oz1sY3iTxv1/9UMjRo2NEo4lr7/CBd3vgUzpfuapO4/u3arYz0U6PaYMWJy83zaUy3x32ERwjGk08l/N3w7CSojNwOWhMuDIZC/32iuSqHAyydgslbdR64d4GzEdG1cctmwiOEY3uoHuJUxeVuy2itQc+PiOhKcDKmjcay0ALBdodjiOro8FttJ7EcIxodAehLaJ1AJ4NILqCSluTzGragvcmPVc7IzzOPEZwjGi0ShevbK4/oQe8oyR7wJuVhXUcq/6EHPCumrIHvFmPYR3Hqj8JPuDYif0NOLZ4OMcx6qeBTwb12vy6f9EiwIiXab1+f7f6QY14WMeR6k9aP4Pff3rVFyLjTJynQz3L7y7HT4L4PqzjSPUnbTfKL0Phm9EXZGRcm+talPfIQRHPwjqOU3/SdqP8Ye+MetOGASD87DHiWLNEg1ZFqPEDUZRsTIOhbl3//6/aUrU4LeJMclxVVb23vtydPoqdOI65y25mvZb4M3bMiLKKGYh4EDTWuGHg+BuVZdePgfAzLpi7+kEGIt7oGvNu44EXqcDlL5CYm3PUYOB9BiBe6RrzbuOB58nAGUq0I4ZwAHyGiDtBY5FbGrj9lA5Eid6k5T+ngSPipa4x7zYWuE8E3h6ujqbPmiUGHjM2YNbUNObdxgJ3icAvq6fEr1NvfSwGPsz4lr714Rvr3Hjgva6//9dvArgJEHjMAMAFjQk3GfCoOQy086snWdPr8OePNPCYcQp4N7TjG8d28/Pd3hZwE4EbKfD5JRrbdwAciQcehxR72cb2AzgALmn8+sA9GehMWnsSeNA15t3GArdkoDdpORJ4KWgscGNv7bfDwKvjQP7W/ijjBHAnaCxw4xavVtmfYeBttrn84tXmZUYGFq8kjXk3fnk2LsCvlwets6y9/PJs+zJjB5ZnJY15N/YBRFSbPdM60A8gjrV7nnH3F8yZgsYCNwwc7xvdtjcHtVvqEZuvThC/3w10D1ZnRY15N+IhMhL/EHm6al1j3o3YJjFJjtgmca6CrjHvRmwE0u51q6YDd7rGvBsArhhTFvTm8LQ6YWPebRJwy21mpKbNtJygscqN366MxW9XTqsTNubdEHCkgtjKqN3OWTtdY95tMnDPTNHSC5UgbMy7ES9VSQYUft7spI15N+61Qf4LhdWQAwrfWO3GvxiL8/gXY7EqJ2zMu3HAQSJYeGdf/cYqBY3FbvzhBnjCIA83wAr6xrwbe3wHn4eJ1wRvrrHSjT+gBiv3Jko0jld7eWPejQVuF2flFdZMl+uI6xOisdCNP2QMa2E4hWrky5l8Y60bA9wkP+TCpyz4f/IGDCdEY50bfVAkjuO1bxDu0gARjbVu1FGodFwaeUfgJhpr3fjDfqPywhFzJTrsN6pqgjdIfGO9G3Wc9UNsnhcL560RqAw/m7rqUdd1F0pAW9BY6fbxA6b/2KFjGgBgGAhi/FmXwS1d8pINwf+E3ya8CV8nvAlfJ7wJXye8CV8nvAlfJ7wJXye8CV8nvAlfJ7wJXye8CV8nvAlfJ7wJXye8CV8nvAlfJ7wJXye8CV8nvAlfJ7wJXye8CV8nvAl/7dVBCsMwDETRsSQn0f0v3JaWkpV3GTD8d4SPGO2O4GsE3x3B1wi+O4KvEXx3BDfT0TAaioZRaDaMUlfDqMSmOJ2SajRMRuktGyapD/6my9RPsioGI/VXZ+NhUbqrDM78MUfMS18vwGQ/2+yp6lQAAAAASUVORK5CYII=";
|
|
1594
|
-
|
|
1595
|
-
const VIEW_BY_OPTIONS = [
|
|
1596
|
-
{
|
|
1597
|
-
id: EAnalyticMode.ALL_SESSION,
|
|
1598
|
-
content: 'All sessions',
|
|
1599
|
-
helpText: 'Count metrics for all sessions where this page shows up anywhere in the journey: before, during, or after other pages.',
|
|
1600
|
-
icon: IMAGE_ALL_SESSION,
|
|
1601
|
-
},
|
|
1602
|
-
{
|
|
1603
|
-
id: EAnalyticMode.FIRST_SESSION,
|
|
1604
|
-
content: 'Entry session only',
|
|
1605
|
-
helpText: 'Count metrics for sessions only where this page was the very first page visited, then track how they moved through the funnel.',
|
|
1606
|
-
icon: IMAGE_FIRST_SESSION,
|
|
1607
|
-
},
|
|
1608
|
-
];
|
|
1609
|
-
const AnalyticModeSelector = ({ activatorText = 'View by', value, onChange }) => {
|
|
1610
|
-
const options = useMemo(() => {
|
|
1611
|
-
return VIEW_BY_OPTIONS.map((option) => ({
|
|
1612
|
-
...option,
|
|
1613
|
-
}));
|
|
1614
|
-
}, []);
|
|
1615
|
-
const onSelectMode = (value) => {
|
|
1616
|
-
onChange(value);
|
|
1617
|
-
};
|
|
1618
|
-
return (jsx(GViewBySelector, { activatorText: activatorText, options: options, selected: value, onSelect: onSelectMode, maxWidth: "650px" }));
|
|
1619
|
-
};
|
|
1620
|
-
|
|
1621
|
-
const EXCHANGE_RATE_HELP_URL = 'https://help.shopify.com/en/manual/international/pricing/exchange-rates#auto-convert';
|
|
1622
|
-
const CurrencySelector = ({ currencies, selected, preferredAlignment = 'left', activatorText, onSelect, }) => {
|
|
1623
|
-
const { t } = useTranslation();
|
|
1624
|
-
const onSelectRef = useRef(onSelect);
|
|
1625
|
-
const handleSelection = useCallback((value) => {
|
|
1626
|
-
onSelectRef.current?.(value);
|
|
1627
|
-
}, []);
|
|
1628
|
-
const actionItems = useMemo(() => {
|
|
1629
|
-
if (!currencies)
|
|
1630
|
-
return [];
|
|
1631
|
-
const formattedCurrencies = currencies.map((currency) => ({
|
|
1632
|
-
content: currency,
|
|
1633
|
-
id: currency,
|
|
1634
|
-
}));
|
|
1635
|
-
const hasCurrencyDefault = formattedCurrencies.some((item) => item.id === DEFAULT_CURRENCY_ANALYTIC);
|
|
1636
|
-
if (!hasCurrencyDefault) {
|
|
1637
|
-
formattedCurrencies.push({
|
|
1638
|
-
content: DEFAULT_CURRENCY_ANALYTIC,
|
|
1639
|
-
id: DEFAULT_CURRENCY_ANALYTIC,
|
|
1640
|
-
});
|
|
1641
|
-
}
|
|
1642
|
-
return sortByConditions(formattedCurrencies, [
|
|
1643
|
-
{ attr: 'content', order: 'asc', preferredValue: DEFAULT_CURRENCY_ANALYTIC },
|
|
1644
|
-
]);
|
|
1645
|
-
}, [currencies]);
|
|
1646
|
-
const actionListItems = useMemo(() => {
|
|
1647
|
-
return actionItems.map((option) => ({
|
|
1648
|
-
id: option.id,
|
|
1649
|
-
content: option.content,
|
|
1650
|
-
onAction: () => handleSelection(option.id),
|
|
1651
|
-
active: option.id === selected,
|
|
1652
|
-
suffix: option.id === selected && jsx(Icon, { source: SvgCheckIcon, tone: "success" }),
|
|
1653
|
-
helpText: option.id === DEFAULT_CURRENCY_ANALYTIC && (jsx(Text, { as: "p", fontWeight: "semibold", children: t('Default') })),
|
|
1654
|
-
}));
|
|
1655
|
-
}, [actionItems, selected, handleSelection, t]);
|
|
1656
|
-
const isHidden = useMemo(() => {
|
|
1657
|
-
if (!actionItems?.length)
|
|
1658
|
-
return true;
|
|
1659
|
-
return actionItems.length === 1 && actionItems[0]?.id === DEFAULT_CURRENCY_ANALYTIC;
|
|
1660
|
-
}, [actionItems]);
|
|
1661
|
-
useEffect(() => {
|
|
1662
|
-
onSelectRef.current = onSelect;
|
|
1663
|
-
});
|
|
1664
|
-
if (isHidden)
|
|
1665
|
-
return null;
|
|
1666
|
-
return (jsx(GSelector, { options: actionListItems, selected: selected, variant: "action-list",
|
|
1667
|
-
// value originates from our CurrencyCode option ids, so the widen-to-string round trip is safe
|
|
1668
|
-
onSelect: (value) => handleSelection(value), activatorText: activatorText ?? t('Currency'), maxWidth: "225px", preferredAlignment: preferredAlignment, helpText: jsx(Box, { padding: "200", paddingBlockStart: "300", paddingBlockEnd: "300", borderColor: "border-tertiary", background: 'bg', children: jsx(GI18NText, { as: "p", variant: "bodyMd", transformers: {
|
|
1669
|
-
1: (text) => (jsx(GTextLink, { linkAction: {
|
|
1670
|
-
url: EXCHANGE_RATE_HELP_URL,
|
|
1671
|
-
target: '_blank',
|
|
1672
|
-
}, children: text }, text + 'text-link')),
|
|
1673
|
-
}, children: t("This will follow Shopify's current exchange rate. [1]Read more[]") }) }) }));
|
|
1674
|
-
};
|
|
1675
|
-
|
|
1676
|
-
var MainDateTimePickerAlias;
|
|
1677
|
-
(function (MainDateTimePickerAlias) {
|
|
1678
|
-
MainDateTimePickerAlias["TODAY"] = "today";
|
|
1679
|
-
MainDateTimePickerAlias["YESTERDAY"] = "yesterday";
|
|
1680
|
-
MainDateTimePickerAlias["LAST_7_DAYS"] = "last7days";
|
|
1681
|
-
MainDateTimePickerAlias["LAST_30_DAYS"] = "last30days";
|
|
1682
|
-
MainDateTimePickerAlias["LAST_90_DAYS"] = "last90days";
|
|
1683
|
-
MainDateTimePickerAlias["LAST_365_DAYS"] = "last365days";
|
|
1684
|
-
MainDateTimePickerAlias["LAST_MONTH"] = "lastMonth";
|
|
1685
|
-
MainDateTimePickerAlias["LAST_12_MONTHS"] = "last12Months";
|
|
1686
|
-
MainDateTimePickerAlias["LAST_YEAR"] = "lastYear";
|
|
1687
|
-
})(MainDateTimePickerAlias || (MainDateTimePickerAlias = {}));
|
|
1688
|
-
function getDateTimeFilterMapping() {
|
|
1689
|
-
const mappings = {
|
|
1690
|
-
[MainDateTimePickerAlias.TODAY]: {
|
|
1691
|
-
title: 'Today',
|
|
1692
|
-
alias: MainDateTimePickerAlias.TODAY,
|
|
1693
|
-
getDateRange: getToday,
|
|
1694
|
-
},
|
|
1695
|
-
[MainDateTimePickerAlias.YESTERDAY]: {
|
|
1696
|
-
title: 'Yesterday',
|
|
1697
|
-
alias: MainDateTimePickerAlias.YESTERDAY,
|
|
1698
|
-
getDateRange: getYesterday,
|
|
1699
|
-
},
|
|
1700
|
-
[MainDateTimePickerAlias.LAST_7_DAYS]: {
|
|
1701
|
-
title: 'Last 7 days',
|
|
1702
|
-
alias: MainDateTimePickerAlias.LAST_7_DAYS,
|
|
1703
|
-
getDateRange: getLast7Days,
|
|
1704
|
-
},
|
|
1705
|
-
[MainDateTimePickerAlias.LAST_30_DAYS]: {
|
|
1706
|
-
title: 'Last 30 days',
|
|
1707
|
-
alias: MainDateTimePickerAlias.LAST_30_DAYS,
|
|
1708
|
-
getDateRange: getLast30Days,
|
|
1709
|
-
},
|
|
1710
|
-
[MainDateTimePickerAlias.LAST_90_DAYS]: {
|
|
1711
|
-
title: 'Last 90 days',
|
|
1712
|
-
alias: MainDateTimePickerAlias.LAST_90_DAYS,
|
|
1713
|
-
getDateRange: getLast90Days,
|
|
1714
|
-
},
|
|
1715
|
-
[MainDateTimePickerAlias.LAST_365_DAYS]: {
|
|
1716
|
-
title: 'Last 365 days',
|
|
1717
|
-
alias: MainDateTimePickerAlias.LAST_365_DAYS,
|
|
1718
|
-
getDateRange: getLast365Days,
|
|
1719
|
-
},
|
|
1720
|
-
[MainDateTimePickerAlias.LAST_MONTH]: {
|
|
1721
|
-
title: 'Last month',
|
|
1722
|
-
alias: MainDateTimePickerAlias.LAST_MONTH,
|
|
1723
|
-
getDateRange: getLastMonth,
|
|
1724
|
-
},
|
|
1725
|
-
[MainDateTimePickerAlias.LAST_12_MONTHS]: {
|
|
1726
|
-
title: 'Last 12 months',
|
|
1727
|
-
alias: MainDateTimePickerAlias.LAST_12_MONTHS,
|
|
1728
|
-
getDateRange: getLast12Months,
|
|
1729
|
-
},
|
|
1730
|
-
[MainDateTimePickerAlias.LAST_YEAR]: {
|
|
1731
|
-
title: 'Last year',
|
|
1732
|
-
alias: MainDateTimePickerAlias.LAST_YEAR,
|
|
1733
|
-
getDateRange: getLastYear,
|
|
1734
|
-
},
|
|
1735
|
-
};
|
|
1736
|
-
return mappings;
|
|
1737
|
-
}
|
|
1738
|
-
function getDateTimeFilterByAlias(alias) {
|
|
1739
|
-
const mappings = getDateTimeFilterMapping();
|
|
1740
|
-
return mappings[alias];
|
|
1741
|
-
}
|
|
1742
|
-
|
|
1743
|
-
const DATE_FORMAT = {
|
|
1744
|
-
YMD: 'YYYY-MM-DD', // 2025-01-01
|
|
1745
|
-
MONTH_YEAR: 'MMM YYYY', // Jan 2025
|
|
1746
|
-
FULL: 'MMMM D, YYYY', // January 1, 2025
|
|
1747
|
-
FULL_WITH_TIME: 'MMMM D, YYYY [at] h:mm A', // January 1, 2025 at 12:00 AM
|
|
1748
|
-
SHORT: 'MMM DD, YYYY', // Jan 01, 2025
|
|
1749
|
-
SHORT_NO_PAD: 'MMM D, YYYY', // Jan 1, 2025
|
|
1750
|
-
SHORT_WITH_TIME: 'MMM D, YYYY [at] h:mm A', // Jan 1, 2025 at 12:00 AM
|
|
1751
|
-
MONTH_DAY: 'MMM D', // Jan 1
|
|
1752
|
-
DAY_YEAR: 'D, YYYY', // 1, 2025
|
|
1753
|
-
TIME: 'h:mm A', // 12:00 AM
|
|
1754
|
-
MONTH_DAY_WITH_TIME: 'MMM D [at] h:mm A', // Jan 1 at 12:00 AM
|
|
1755
|
-
YEAR: 'YYYY', // 2025
|
|
1756
|
-
};
|
|
1757
|
-
|
|
1758
|
-
function parseYearMonthDayDateString(input) {
|
|
1759
|
-
// Date-only strings (e.g. "1970-01-01") are treated as UTC, not local time
|
|
1760
|
-
// when using new Date()
|
|
1761
|
-
// We need to split year, month, day to pass into new Date() separately
|
|
1762
|
-
// to get a localized Date
|
|
1763
|
-
return dayjs(input).valueOf();
|
|
1764
|
-
}
|
|
1765
|
-
const VALID_YYYY_MM_DD_DATE_REGEX = /^\d{4}-\d{1,2}-\d{1,2}/;
|
|
1766
|
-
function isDate(date) {
|
|
1767
|
-
return !isNaN(new Date(date).getDate());
|
|
1768
|
-
}
|
|
1769
|
-
function isValidYearMonthDayDateString(date) {
|
|
1770
|
-
return VALID_YYYY_MM_DD_DATE_REGEX.test(date) && isDate(date);
|
|
1771
|
-
}
|
|
1772
|
-
function isValidDate(date) {
|
|
1773
|
-
return date.length === 10 && isValidYearMonthDayDateString(date);
|
|
1774
|
-
}
|
|
1775
|
-
function formatDate(timestamp, type) {
|
|
1776
|
-
const date = convertDateToTz(timestamp);
|
|
1777
|
-
if (type === 'YMD') {
|
|
1778
|
-
return date.format(DATE_FORMAT.YMD);
|
|
1779
|
-
}
|
|
1780
|
-
if (type === 'MY') {
|
|
1781
|
-
return date.format(DATE_FORMAT.MONTH_YEAR);
|
|
1782
|
-
}
|
|
1783
|
-
if (type === 'FULL') {
|
|
1784
|
-
return date.format(DATE_FORMAT.FULL);
|
|
1785
|
-
}
|
|
1786
|
-
if (type === 'FULL_WITH_TIME') {
|
|
1787
|
-
return date.format(DATE_FORMAT.FULL_WITH_TIME);
|
|
1788
|
-
}
|
|
1789
|
-
return date.format(DATE_FORMAT.SHORT);
|
|
1790
|
-
}
|
|
1791
|
-
function formatTime(timestamp) {
|
|
1792
|
-
const date = convertDateToTz(timestamp);
|
|
1793
|
-
return date.format(DATE_FORMAT.TIME);
|
|
1794
|
-
}
|
|
1795
|
-
function isSameDayTimestamp(since, until) {
|
|
1796
|
-
const sinceDate = convertDateToTz(since);
|
|
1797
|
-
const untilDate = convertDateToTz(until);
|
|
1798
|
-
return sinceDate.isSame(untilDate, 'day');
|
|
1799
|
-
}
|
|
1800
|
-
function formatTimeRange(data) {
|
|
1801
|
-
const { since, until, format = DATE_FORMAT.TIME, showNow = false } = data;
|
|
1802
|
-
const sinceDate = convertDateToTz(since);
|
|
1803
|
-
const untilDate = convertDateToTz(until);
|
|
1804
|
-
return `${sinceDate.format(format)} - ${showNow ? 'Now' : untilDate.format(format)}`;
|
|
1805
|
-
}
|
|
1806
|
-
function formatDateTimeRange(data) {
|
|
1807
|
-
const { since, until, isShowNow } = data;
|
|
1808
|
-
const sinceDate = convertDateToTz(since);
|
|
1809
|
-
const untilDate = convertDateToTz(until);
|
|
1810
|
-
const isToday = sinceDate.isSame(dayjsTz(), 'day');
|
|
1811
|
-
const startTime = sinceDate.format(DATE_FORMAT.TIME);
|
|
1812
|
-
const endTime = untilDate.format(DATE_FORMAT.TIME);
|
|
1813
|
-
if (isToday) {
|
|
1814
|
-
const formatEndTime = isShowNow ? 'Now' : endTime;
|
|
1815
|
-
return `Today at ${startTime} - ${formatEndTime}`;
|
|
1816
|
-
}
|
|
1817
|
-
if (isShowNow) {
|
|
1818
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - Now`;
|
|
1819
|
-
}
|
|
1820
|
-
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1821
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - ${endTime}`;
|
|
1822
|
-
}
|
|
1823
|
-
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1824
|
-
const time = formatTimeRange({ since, until });
|
|
1825
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT)} (${time})`;
|
|
1826
|
-
}
|
|
1827
|
-
if (sinceDate.isSame(untilDate, 'year')) {
|
|
1828
|
-
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY_WITH_TIME)} - ${untilDate.format(DATE_FORMAT.MONTH_DAY_WITH_TIME)}, ${untilDate.format(DATE_FORMAT.YEAR)}`;
|
|
1829
|
-
}
|
|
1830
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - ${untilDate.format(DATE_FORMAT.SHORT_WITH_TIME)}`;
|
|
1831
|
-
}
|
|
1832
|
-
const formatDayjs = (date, isEndDay = false, formatTemplate) => {
|
|
1833
|
-
// const isUTC = date.isUTC?.() ?? false;
|
|
1834
|
-
// if (isUTC) return date.format();
|
|
1835
|
-
if (isEndDay && isMidnight(date)) {
|
|
1836
|
-
return date.endOf('day').format(formatTemplate);
|
|
1837
|
-
}
|
|
1838
|
-
return date.format(formatTemplate);
|
|
1839
|
-
};
|
|
1840
|
-
const getEndOfDayBy = (value, formatTemplate) => {
|
|
1841
|
-
if (!value) {
|
|
1842
|
-
return formatDayjs(dayjsTz().endOf('day'), false, formatTemplate);
|
|
1843
|
-
}
|
|
1844
|
-
return formatDayjs(dayjsTz(value).endOf('day'), false, formatTemplate);
|
|
1845
|
-
};
|
|
1846
|
-
const isMidnight = (date) => {
|
|
1847
|
-
return date.hour() === 0 && date.minute() === 0;
|
|
1848
|
-
};
|
|
1849
|
-
const formatMs = (ms) => {
|
|
1850
|
-
const totalSeconds = Math.floor(ms / 1000);
|
|
1851
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
1852
|
-
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
1853
|
-
const seconds = totalSeconds % 60;
|
|
1854
|
-
return [hours, minutes, seconds].map((v) => String(v).padStart(2, '0')).join(':');
|
|
1855
|
-
};
|
|
1856
|
-
|
|
1857
|
-
function getDateRangeTitle(since, until) {
|
|
1858
|
-
const sinceDate = convertDateToTz(since);
|
|
1859
|
-
const untilDate = convertDateToTz(until);
|
|
1860
|
-
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1861
|
-
return sinceDate.format(DATE_FORMAT.SHORT);
|
|
1862
|
-
}
|
|
1863
|
-
if (sinceDate.isSame(untilDate, 'month') && sinceDate.isSame(untilDate, 'year')) {
|
|
1864
|
-
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY)} - ${untilDate.format(DATE_FORMAT.DAY_YEAR)}`;
|
|
1865
|
-
}
|
|
1866
|
-
if (sinceDate.isSame(untilDate, 'year')) {
|
|
1867
|
-
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY)} - ${untilDate.format(DATE_FORMAT.SHORT_NO_PAD)}`;
|
|
1868
|
-
}
|
|
1869
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_NO_PAD)} - ${untilDate.format(DATE_FORMAT.SHORT_NO_PAD)}`;
|
|
1870
|
-
}
|
|
1871
|
-
/**
|
|
1872
|
-
* Resolves a { title, alias } pair from a since/until date range.
|
|
1873
|
-
* Matches against known presets (today, last 7 days, …); falls back to
|
|
1874
|
-
* a formatted custom range with alias "custom".
|
|
1875
|
-
*/
|
|
1876
|
-
function getDateTimeFilterBase(since, until) {
|
|
1877
|
-
const now = dayjsTz();
|
|
1878
|
-
const sinceDate = convertDateToTz(since);
|
|
1879
|
-
const untilDate = convertDateToTz(until);
|
|
1880
|
-
const mappings = getDateTimeFilterMapping();
|
|
1881
|
-
for (const mapping of Object.values(mappings)) {
|
|
1882
|
-
const range = mapping.getDateRange(now);
|
|
1883
|
-
const expectedSince = convertDateToTz(range.since);
|
|
1884
|
-
const expectedUntil = convertDateToTz(range.until);
|
|
1885
|
-
const isSameSince = sinceDate.isSame(expectedSince, 'day');
|
|
1886
|
-
const isSameUntil = untilDate.isSame(expectedUntil, 'day');
|
|
1887
|
-
if (isSameSince && isSameUntil) {
|
|
1888
|
-
return { title: mapping.title, alias: mapping.alias };
|
|
1889
|
-
}
|
|
1890
|
-
}
|
|
1891
|
-
return {
|
|
1892
|
-
title: getDateRangeTitle(since, until),
|
|
1893
|
-
alias: 'custom',
|
|
1894
|
-
};
|
|
1895
|
-
}
|
|
1896
|
-
function getVersionDateRangeTitle(data) {
|
|
1897
|
-
const { since, until, isShowNow } = data;
|
|
1898
|
-
const sinceDate = convertDateToTz(since);
|
|
1899
|
-
const isToday = sinceDate.isSame(dayjsTz(), 'day');
|
|
1900
|
-
if (isToday)
|
|
1901
|
-
return getDateTimeFilterByAlias(MainDateTimePickerAlias.TODAY).title;
|
|
1902
|
-
if (isShowNow)
|
|
1903
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_NO_PAD)} - Now`;
|
|
1904
|
-
return getDateRangeTitle(since, until);
|
|
1905
|
-
}
|
|
1906
|
-
const getVersionDateDescription = ({ since, until, isShowNow }) => {
|
|
1907
|
-
const isSameDay = isSameDayTimestamp(since, until);
|
|
1908
|
-
if (!isSameDay)
|
|
1909
|
-
return undefined;
|
|
1910
|
-
return formatTimeRange({ since, until, showNow: isShowNow });
|
|
1911
|
-
};
|
|
1912
|
-
|
|
1913
|
-
const convertToDateTimeFilters = (versions) => {
|
|
1914
|
-
const dataVersions = [...versions].sort((a, b) => semverToNum(b.version) - semverToNum(a.version));
|
|
1915
|
-
return dataVersions
|
|
1916
|
-
.map((item) => {
|
|
1917
|
-
if (!item.startedAt)
|
|
1918
|
-
return false;
|
|
1919
|
-
const isCurrentVersion = !item.completedAt;
|
|
1920
|
-
const since = dayjsTzToLocalTZ(item.startedAt).valueOf();
|
|
1921
|
-
const until = isCurrentVersion
|
|
1922
|
-
? dayjsTzToLocalTZ(getEndOfDayBy()).valueOf()
|
|
1923
|
-
: dayjsTzToLocalTZ(item.completedAt).valueOf();
|
|
1924
|
-
const title = getVersionDateRangeTitle({ since, until, isShowNow: isCurrentVersion });
|
|
1925
|
-
const description = getVersionDateDescription({ since, until, isShowNow: isCurrentVersion });
|
|
1926
|
-
return {
|
|
1927
|
-
title,
|
|
1928
|
-
alias: `${item.version}`,
|
|
1929
|
-
since,
|
|
1930
|
-
until,
|
|
1931
|
-
isVersion: true,
|
|
1932
|
-
isCurrentVersion,
|
|
1933
|
-
description,
|
|
1934
|
-
versionId: item.id,
|
|
1935
|
-
};
|
|
1936
|
-
})
|
|
1937
|
-
.filter(Boolean);
|
|
1938
|
-
};
|
|
1939
|
-
|
|
1940
|
-
const getNoComparison = () => {
|
|
1941
|
-
return {
|
|
1942
|
-
since: 0,
|
|
1943
|
-
until: 0,
|
|
1944
|
-
};
|
|
1945
|
-
};
|
|
1946
|
-
const getPreviousPeriod = (value) => {
|
|
1947
|
-
const { since, until, alias } = value;
|
|
1948
|
-
const sinceDate = dayjs(since);
|
|
1949
|
-
const untilDate = dayjs(until);
|
|
1950
|
-
if (alias === MainDateTimePickerAlias.LAST_MONTH) {
|
|
1951
|
-
return getLastMonth(sinceDate);
|
|
1952
|
-
}
|
|
1953
|
-
if (alias === MainDateTimePickerAlias.LAST_12_MONTHS) {
|
|
1954
|
-
return getLast12Months(sinceDate);
|
|
1955
|
-
}
|
|
1956
|
-
if (alias === MainDateTimePickerAlias.LAST_YEAR) {
|
|
1957
|
-
return getLastYear(sinceDate);
|
|
1958
|
-
}
|
|
1959
|
-
const duration = untilDate.diff(sinceDate, 'day') + 1;
|
|
1960
|
-
const previousSince = sinceDate.subtract(duration, 'day');
|
|
1961
|
-
const previousUntil = untilDate.subtract(duration, 'day');
|
|
1962
|
-
return {
|
|
1963
|
-
since: previousSince.valueOf(),
|
|
1964
|
-
until: previousUntil.valueOf(),
|
|
1965
|
-
};
|
|
1966
|
-
};
|
|
1967
|
-
const createPreviousRange = (subtractAmount, subtractUnit) => (value) => {
|
|
1968
|
-
const { since, until } = value;
|
|
1969
|
-
const sinceDate = dayjs(since);
|
|
1970
|
-
const untilDate = dayjs(until);
|
|
1971
|
-
const duration = untilDate.diff(sinceDate, 'day');
|
|
1972
|
-
const previousSince = sinceDate.subtract(subtractAmount, subtractUnit);
|
|
1973
|
-
const previousUntil = previousSince.add(duration, 'day');
|
|
1974
|
-
return {
|
|
1975
|
-
since: previousSince.valueOf(),
|
|
1976
|
-
until: previousUntil.valueOf(),
|
|
1977
|
-
};
|
|
1978
|
-
};
|
|
1979
|
-
const getPreviousWeek = createPreviousRange(7, 'day');
|
|
1980
|
-
const getPreviousQuarter = createPreviousRange(3, 'month');
|
|
1981
|
-
const getPreviousMonth = createPreviousRange(1, 'month');
|
|
1982
|
-
const getPreviousYear = createPreviousRange(1, 'year');
|
|
1983
|
-
const createLastDaysRange = (subtractAmount) => (date) => {
|
|
1984
|
-
return {
|
|
1985
|
-
since: date.subtract(subtractAmount, 'day').valueOf(),
|
|
1986
|
-
until: date.valueOf(),
|
|
1987
|
-
};
|
|
1988
|
-
};
|
|
1989
|
-
const getToday = (currentDate) => {
|
|
1990
|
-
return {
|
|
1991
|
-
since: currentDate.valueOf(),
|
|
1992
|
-
until: currentDate.valueOf(),
|
|
1993
|
-
};
|
|
1994
|
-
};
|
|
1995
|
-
const getYesterday = (date) => {
|
|
1996
|
-
return {
|
|
1997
|
-
since: date.subtract(1, 'day').valueOf(),
|
|
1998
|
-
until: date.subtract(1, 'day').valueOf(),
|
|
1999
|
-
};
|
|
2000
|
-
};
|
|
2001
|
-
const getLast7Days = createLastDaysRange(6);
|
|
2002
|
-
const getLast30Days = createLastDaysRange(29);
|
|
2003
|
-
const getLast90Days = createLastDaysRange(89);
|
|
2004
|
-
const getLast365Days = createLastDaysRange(364);
|
|
2005
|
-
function getLastMonth(date) {
|
|
2006
|
-
return {
|
|
2007
|
-
since: date.subtract(1, 'month').startOf('month').valueOf(),
|
|
2008
|
-
until: date.subtract(1, 'month').endOf('month').valueOf(),
|
|
2009
|
-
};
|
|
2010
|
-
}
|
|
2011
|
-
function getLast12Months(date) {
|
|
2012
|
-
return {
|
|
2013
|
-
since: date.subtract(12, 'month').startOf('month').valueOf(),
|
|
2014
|
-
until: date.subtract(1, 'month').endOf('month').valueOf(),
|
|
2015
|
-
};
|
|
2016
|
-
}
|
|
2017
|
-
function getLastYear(date) {
|
|
2018
|
-
return {
|
|
2019
|
-
since: date.subtract(1, 'year').startOf('year').valueOf(),
|
|
2020
|
-
until: date.subtract(1, 'year').endOf('year').valueOf(),
|
|
2021
|
-
};
|
|
2022
|
-
}
|
|
2023
|
-
const getMonthAndYearByDateFilter = (month, year, date) => {
|
|
2024
|
-
const endDate = dayjs(date);
|
|
2025
|
-
const endMonthFilter = endDate.month();
|
|
2026
|
-
const endYearFilter = endDate.year();
|
|
2027
|
-
if (endYearFilter !== year || endMonthFilter !== month) {
|
|
2028
|
-
const prev = endDate.subtract(1, 'month');
|
|
2029
|
-
return {
|
|
2030
|
-
month: prev.month(),
|
|
2031
|
-
year: prev.year(),
|
|
2032
|
-
};
|
|
2033
|
-
}
|
|
2034
|
-
return { month, year };
|
|
2035
|
-
};
|
|
2036
|
-
|
|
2037
|
-
var CompareDateTimePickerAlias;
|
|
2038
|
-
(function (CompareDateTimePickerAlias) {
|
|
2039
|
-
CompareDateTimePickerAlias["NO_COMPARISON"] = "noComparison";
|
|
2040
|
-
CompareDateTimePickerAlias["PREVIOUS_PERIOD"] = "previousPeriod";
|
|
2041
|
-
CompareDateTimePickerAlias["PREVIOUS_WEEK"] = "previousWeek";
|
|
2042
|
-
CompareDateTimePickerAlias["PREVIOUS_MONTH"] = "previousMonth";
|
|
2043
|
-
CompareDateTimePickerAlias["PREVIOUS_QUARTER"] = "previousQuarter";
|
|
2044
|
-
CompareDateTimePickerAlias["PREVIOUS_YEAR"] = "previousYear";
|
|
2045
|
-
})(CompareDateTimePickerAlias || (CompareDateTimePickerAlias = {}));
|
|
2046
|
-
const PREVIOUS_PERIOD_FILTER = {
|
|
2047
|
-
title: 'Previous period',
|
|
2048
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_PERIOD,
|
|
2049
|
-
since: 0,
|
|
2050
|
-
until: 0,
|
|
2051
|
-
};
|
|
2052
|
-
const DATE_TIME_COMPARISON_FILTERS = [
|
|
2053
|
-
{
|
|
2054
|
-
title: 'No comparison',
|
|
2055
|
-
alias: CompareDateTimePickerAlias.NO_COMPARISON,
|
|
2056
|
-
since: 0,
|
|
2057
|
-
until: 0,
|
|
2058
|
-
},
|
|
2059
|
-
PREVIOUS_PERIOD_FILTER,
|
|
2060
|
-
{
|
|
2061
|
-
title: 'Previous week',
|
|
2062
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_WEEK,
|
|
2063
|
-
since: 0,
|
|
2064
|
-
until: 0,
|
|
2065
|
-
},
|
|
2066
|
-
{
|
|
2067
|
-
title: 'Previous quarter',
|
|
2068
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_QUARTER,
|
|
2069
|
-
since: 0,
|
|
2070
|
-
until: 0,
|
|
2071
|
-
},
|
|
2072
|
-
{
|
|
2073
|
-
title: 'Previous month',
|
|
2074
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_MONTH,
|
|
2075
|
-
since: 0,
|
|
2076
|
-
until: 0,
|
|
2077
|
-
},
|
|
2078
|
-
{
|
|
2079
|
-
title: 'Previous year',
|
|
2080
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_YEAR,
|
|
2081
|
-
since: 0,
|
|
2082
|
-
until: 0,
|
|
2083
|
-
},
|
|
2084
|
-
];
|
|
2085
|
-
const COMPARE_DATE_TIME_FILTERS_MAP = {
|
|
2086
|
-
[CompareDateTimePickerAlias.NO_COMPARISON]: getNoComparison,
|
|
2087
|
-
[CompareDateTimePickerAlias.PREVIOUS_PERIOD]: getPreviousPeriod,
|
|
2088
|
-
[CompareDateTimePickerAlias.PREVIOUS_WEEK]: getPreviousWeek,
|
|
2089
|
-
[CompareDateTimePickerAlias.PREVIOUS_QUARTER]: getPreviousQuarter,
|
|
2090
|
-
[CompareDateTimePickerAlias.PREVIOUS_MONTH]: getPreviousMonth,
|
|
2091
|
-
[CompareDateTimePickerAlias.PREVIOUS_YEAR]: getPreviousYear,
|
|
2092
|
-
};
|
|
2093
|
-
|
|
2094
|
-
const useDateTimeFilter = () => {
|
|
2095
|
-
const currentDate = dayjsTzToLocalTZ().startOf('day');
|
|
2096
|
-
const mappings = getDateTimeFilterMapping();
|
|
2097
|
-
const TODAY_CONFIG = mappings[MainDateTimePickerAlias.TODAY];
|
|
2098
|
-
const TODAY_DATE_RANGE = {
|
|
2099
|
-
...TODAY_CONFIG,
|
|
2100
|
-
...TODAY_CONFIG.getDateRange(currentDate),
|
|
2101
|
-
};
|
|
2102
|
-
const YESTERDAY_CONFIG = mappings[MainDateTimePickerAlias.YESTERDAY];
|
|
2103
|
-
const YESTERDAY_DATE_RANGE = {
|
|
2104
|
-
...YESTERDAY_CONFIG,
|
|
2105
|
-
...YESTERDAY_CONFIG.getDateRange(currentDate),
|
|
2106
|
-
};
|
|
2107
|
-
const LAST_7_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_7_DAYS];
|
|
2108
|
-
const LAST_7_DAYS_DATE_RANGE = {
|
|
2109
|
-
...LAST_7_DAYS_CONFIG,
|
|
2110
|
-
...LAST_7_DAYS_CONFIG.getDateRange(currentDate),
|
|
2111
|
-
};
|
|
2112
|
-
const LAST_30_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_30_DAYS];
|
|
2113
|
-
const LAST_30_DAYS_DATE_RANGE = {
|
|
2114
|
-
...LAST_30_DAYS_CONFIG,
|
|
2115
|
-
...LAST_30_DAYS_CONFIG.getDateRange(currentDate),
|
|
2116
|
-
};
|
|
2117
|
-
const LAST_90_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_90_DAYS];
|
|
2118
|
-
const LAST_90_DAYS_DATE_RANGE = {
|
|
2119
|
-
...LAST_90_DAYS_CONFIG,
|
|
2120
|
-
...LAST_90_DAYS_CONFIG.getDateRange(currentDate),
|
|
2121
|
-
};
|
|
2122
|
-
const LAST_365_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_365_DAYS];
|
|
2123
|
-
const LAST_365_DAYS_DATE_RANGE = {
|
|
2124
|
-
...LAST_365_DAYS_CONFIG,
|
|
2125
|
-
...LAST_365_DAYS_CONFIG.getDateRange(currentDate),
|
|
2126
|
-
};
|
|
2127
|
-
const LAST_MONTH_CONFIG = mappings[MainDateTimePickerAlias.LAST_MONTH];
|
|
2128
|
-
const LAST_MONTH_DATE_RANGE = {
|
|
2129
|
-
...LAST_MONTH_CONFIG,
|
|
2130
|
-
...LAST_MONTH_CONFIG.getDateRange(currentDate),
|
|
2131
|
-
};
|
|
2132
|
-
const LAST_12_MONTHS_CONFIG = mappings[MainDateTimePickerAlias.LAST_12_MONTHS];
|
|
2133
|
-
const LAST_12_MONTHS_DATE_RANGE = {
|
|
2134
|
-
...LAST_12_MONTHS_CONFIG,
|
|
2135
|
-
...LAST_12_MONTHS_CONFIG.getDateRange(currentDate),
|
|
2136
|
-
};
|
|
2137
|
-
const LAST_YEAR_CONFIG = mappings[MainDateTimePickerAlias.LAST_YEAR];
|
|
2138
|
-
const LAST_YEAR_DATE_RANGE = {
|
|
2139
|
-
...LAST_YEAR_CONFIG,
|
|
2140
|
-
...LAST_YEAR_CONFIG.getDateRange(currentDate),
|
|
2141
|
-
};
|
|
2142
|
-
const DATE_TIME_FILTERS = [
|
|
2143
|
-
TODAY_DATE_RANGE,
|
|
2144
|
-
YESTERDAY_DATE_RANGE,
|
|
2145
|
-
LAST_7_DAYS_DATE_RANGE,
|
|
2146
|
-
LAST_30_DAYS_DATE_RANGE,
|
|
2147
|
-
LAST_90_DAYS_DATE_RANGE,
|
|
2148
|
-
LAST_365_DAYS_DATE_RANGE,
|
|
2149
|
-
LAST_MONTH_DATE_RANGE,
|
|
2150
|
-
LAST_12_MONTHS_DATE_RANGE,
|
|
2151
|
-
LAST_YEAR_DATE_RANGE,
|
|
2152
|
-
];
|
|
2153
|
-
return {
|
|
2154
|
-
DATE_TIME_FILTERS,
|
|
2155
|
-
LAST_7_DAYS_DATE_RANGE,
|
|
2156
|
-
LAST_30_DAYS_DATE_RANGE,
|
|
2157
|
-
};
|
|
2158
|
-
};
|
|
2159
|
-
|
|
2160
|
-
const DateTimePickerContext = createContext({
|
|
2161
|
-
dateTimePicked: {
|
|
2162
|
-
since: dayjsTz().valueOf(),
|
|
2163
|
-
until: dayjsTz().valueOf(),
|
|
2164
|
-
title: 'Today',
|
|
2165
|
-
alias: 'today',
|
|
2166
|
-
},
|
|
2167
|
-
compareDateTimePicked: PREVIOUS_PERIOD_FILTER,
|
|
2168
|
-
setDateTimePicked: () => { },
|
|
2169
|
-
setCompareDateTimePicked: () => { },
|
|
2170
|
-
resetDateVersion: () => { },
|
|
2171
|
-
});
|
|
2172
|
-
const DateTimePickerProvider = ({ children, initDate, initDateCompare, }) => {
|
|
2173
|
-
const [dateTimePicked, setDateTimePicked] = useState(initDate || {
|
|
2174
|
-
since: dayjsTz().set('hour', 0).valueOf(),
|
|
2175
|
-
until: dayjsTz().set('hour', 0).valueOf(),
|
|
2176
|
-
title: 'Today',
|
|
2177
|
-
alias: 'today',
|
|
2178
|
-
});
|
|
2179
|
-
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2180
|
-
const getCompareDateTimePicked = useCallback((alias, source = dateTimePicked) => {
|
|
2181
|
-
return {
|
|
2182
|
-
...PREVIOUS_PERIOD_FILTER,
|
|
2183
|
-
...COMPARE_DATE_TIME_FILTERS_MAP[alias]({
|
|
2184
|
-
since: source.since,
|
|
2185
|
-
until: source.until,
|
|
2186
|
-
alias: source.alias,
|
|
2187
|
-
}),
|
|
2188
|
-
};
|
|
2189
|
-
}, [dateTimePicked]);
|
|
2190
|
-
const [compareDateTimePicked, setCompareDateTimePicked] = useState(initDateCompare || getCompareDateTimePicked(CompareDateTimePickerAlias.PREVIOUS_PERIOD));
|
|
2191
|
-
const updateCompareDateTimePicked = useCallback((source) => {
|
|
2192
|
-
if (compareDateTimePicked.alias === 'custom' ||
|
|
2193
|
-
compareDateTimePicked.alias === CompareDateTimePickerAlias.NO_COMPARISON)
|
|
2194
|
-
return;
|
|
2195
|
-
setCompareDateTimePicked(getCompareDateTimePicked(compareDateTimePicked.alias, source));
|
|
2196
|
-
}, [compareDateTimePicked, getCompareDateTimePicked]);
|
|
2197
|
-
const resetDateVersion = () => {
|
|
2198
|
-
const since = dayjs(dateTimePicked.since).startOf('day').valueOf();
|
|
2199
|
-
const until = dayjs(dateTimePicked.until).startOf('day').valueOf();
|
|
2200
|
-
const dateFilter = DATE_TIME_FILTERS.find((filter) => filter.since === since && filter.until === until);
|
|
2201
|
-
setDateTimePicked({
|
|
2202
|
-
...dateTimePicked,
|
|
2203
|
-
isVersion: false,
|
|
2204
|
-
versionId: undefined,
|
|
2205
|
-
isCurrentVersion: false,
|
|
2206
|
-
description: '',
|
|
2207
|
-
title: dateFilter?.title || dateTimePicked.title,
|
|
2208
|
-
alias: dateFilter?.alias || 'custom',
|
|
2209
|
-
});
|
|
2210
|
-
};
|
|
2211
|
-
const onSetDateTimePicked = useCallback((value) => {
|
|
2212
|
-
setDateTimePicked(value);
|
|
2213
|
-
updateCompareDateTimePicked(value);
|
|
2214
|
-
}, [updateCompareDateTimePicked]);
|
|
2215
|
-
return (jsx(DateTimePickerContext.Provider, { value: {
|
|
2216
|
-
dateTimePicked,
|
|
2217
|
-
setDateTimePicked: onSetDateTimePicked,
|
|
2218
|
-
compareDateTimePicked,
|
|
2219
|
-
setCompareDateTimePicked,
|
|
2220
|
-
resetDateVersion,
|
|
2221
|
-
}, children: children }));
|
|
2222
|
-
};
|
|
2223
|
-
const useDateTimePickerContext = () => {
|
|
2224
|
-
const context = useContext(DateTimePickerContext);
|
|
2225
|
-
if (!context) {
|
|
2226
|
-
throw new Error('useDateTimePickerContext must be used within a DateTimePickerProvider');
|
|
2227
|
-
}
|
|
2228
|
-
return context;
|
|
2229
|
-
};
|
|
2230
|
-
|
|
2231
|
-
const useDateTimePicker = ({ ranges, initialPicked, onApply }) => {
|
|
2232
|
-
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2233
|
-
const allRanges = ranges || DATE_TIME_FILTERS;
|
|
2234
|
-
const { dateTimePicked, setDateTimePicked } = useDateTimePickerContext();
|
|
2235
|
-
const [dateRange, setDateRange] = useState(dateTimePicked);
|
|
2236
|
-
const [{ month, year }, setDate] = useState({
|
|
2237
|
-
month: dayjs(dateTimePicked.since).month(),
|
|
2238
|
-
year: dayjs(dateTimePicked.since).year(),
|
|
2239
|
-
});
|
|
2240
|
-
useEffect(() => {
|
|
2241
|
-
if (dateTimePicked) {
|
|
2242
|
-
const untilDate = new Date(dateTimePicked.until);
|
|
2243
|
-
const monthDiff = (referenceDate, newDate) => {
|
|
2244
|
-
return newDate.month - referenceDate.month + 12 * (referenceDate.year - newDate.year);
|
|
2245
|
-
};
|
|
2246
|
-
monthDiff({ year, month }, {
|
|
2247
|
-
year: untilDate.getFullYear(),
|
|
2248
|
-
month: untilDate.getMonth(),
|
|
2249
|
-
});
|
|
2250
|
-
// if (monthDifference > 1 || monthDifference < 0) {
|
|
2251
|
-
// setDate({
|
|
2252
|
-
// month: untilDate.getMonth(),
|
|
2253
|
-
// year: untilDate.getFullYear(),
|
|
2254
|
-
// });
|
|
2255
|
-
// }
|
|
2256
|
-
}
|
|
2257
|
-
}, [dateTimePicked, month, year]);
|
|
2258
|
-
const onMonthChange = (month, year) => {
|
|
2259
|
-
setDate({ month, year });
|
|
2260
|
-
};
|
|
2261
|
-
const onCalendarChange = (value) => {
|
|
2262
|
-
const { start, end, alias } = value;
|
|
2263
|
-
const customDateRange = {
|
|
2264
|
-
alias: 'custom',
|
|
2265
|
-
title: 'Custom',
|
|
2266
|
-
since: start.getTime(),
|
|
2267
|
-
until: end.getTime(),
|
|
2268
|
-
};
|
|
2269
|
-
const newDateRange = allRanges.find((range) => {
|
|
2270
|
-
const isSameAlias = range.alias === alias;
|
|
2271
|
-
const isSameUntil = range.until === end.getTime();
|
|
2272
|
-
const isSameSince = range.since === start.getTime();
|
|
2273
|
-
// const isSameVersionId = !!range.versionId && !!versionId && range.versionId === versionId;
|
|
2274
|
-
const isSameTime = isSameSince && isSameUntil;
|
|
2275
|
-
return isSameAlias || isSameTime;
|
|
2276
|
-
});
|
|
2277
|
-
const finalDateRange = newDateRange || initialPicked || customDateRange;
|
|
2278
|
-
setDateRange(finalDateRange);
|
|
2279
|
-
};
|
|
2280
|
-
const onChange = ({ end }) => {
|
|
2281
|
-
setDate(getMonthAndYearByDateFilter(month, year, end));
|
|
2282
|
-
};
|
|
2283
|
-
const apply = () => {
|
|
2284
|
-
setDateTimePicked(dateRange);
|
|
2285
|
-
onApply?.(dateRange);
|
|
2286
|
-
};
|
|
2287
|
-
const cancel = () => {
|
|
2288
|
-
setDateRange(dateTimePicked);
|
|
2289
|
-
};
|
|
2290
|
-
useEffect(() => {
|
|
2291
|
-
if (dateTimePicked) {
|
|
2292
|
-
setDateRange(dateTimePicked);
|
|
2293
|
-
setDate({
|
|
2294
|
-
month: dayjs(dateTimePicked.since).month(),
|
|
2295
|
-
year: dayjs(dateTimePicked.since).year(),
|
|
2296
|
-
});
|
|
2297
|
-
}
|
|
2298
|
-
}, [dateTimePicked]);
|
|
2299
|
-
return {
|
|
2300
|
-
month,
|
|
2301
|
-
year,
|
|
2302
|
-
setDate,
|
|
2303
|
-
dateRange,
|
|
2304
|
-
apply,
|
|
2305
|
-
cancel,
|
|
2306
|
-
dateTimePicked,
|
|
2307
|
-
onChange,
|
|
2308
|
-
onMonthChange,
|
|
2309
|
-
onCalendarChange,
|
|
2310
|
-
};
|
|
2311
|
-
};
|
|
2312
|
-
|
|
2313
|
-
const useVersionDateTimeFilters = (versions) => {
|
|
2314
|
-
const { t } = useTranslation();
|
|
2315
|
-
const rangers = useMemo(() => {
|
|
2316
|
-
if (!versions?.length)
|
|
2317
|
-
return [];
|
|
2318
|
-
return convertToDateTimeFilters(versions);
|
|
2319
|
-
}, [versions]);
|
|
2320
|
-
const rangeAddition = {
|
|
2321
|
-
title: t('Experiment periods'),
|
|
2322
|
-
rangers,
|
|
2323
|
-
};
|
|
2324
|
-
return { rangeAddition };
|
|
2325
|
-
};
|
|
2326
|
-
|
|
2327
|
-
function DateTimeFilterInputs({ onBlur, dateRange, setDateTimePicked }) {
|
|
2328
|
-
const [isFocus, setIsFocus] = useState(false);
|
|
2329
|
-
const [inputValues, setInputValues] = useState({});
|
|
2330
|
-
const formatDisplayDate = useCallback((timestamp, isEnd = false) => {
|
|
2331
|
-
if (!dateRange.isVersion || (isEnd && dateRange.isCurrentVersion))
|
|
2332
|
-
return formatDate(timestamp, 'FULL');
|
|
2333
|
-
return formatDate(timestamp, 'FULL_WITH_TIME');
|
|
2334
|
-
}, [dateRange.isVersion, dateRange.isCurrentVersion]);
|
|
2335
|
-
useEffect(() => {
|
|
2336
|
-
if (isFocus)
|
|
2337
|
-
return;
|
|
2338
|
-
setInputValues({
|
|
2339
|
-
since: formatDisplayDate(dateRange.since),
|
|
2340
|
-
until: formatDisplayDate(dateRange.until, true),
|
|
2341
|
-
});
|
|
2342
|
-
}, [dateRange, formatDisplayDate]);
|
|
2343
|
-
function handleStartInputValueChange(value) {
|
|
2344
|
-
setInputValues((prevState) => {
|
|
2345
|
-
return { ...prevState, since: value };
|
|
2346
|
-
});
|
|
2347
|
-
if (isValidDate(value)) {
|
|
2348
|
-
const newSinceDate = convertDateToTz(value).startOf('day');
|
|
2349
|
-
const untilDate = convertDateToTz(dateRange.until).endOf('day');
|
|
2350
|
-
const endDate = newSinceDate.isAfter(untilDate) ? newSinceDate.endOf('day') : untilDate;
|
|
2351
|
-
setDateTimePicked({
|
|
2352
|
-
start: dayjsTzToLocalTZ(newSinceDate).toDate(),
|
|
2353
|
-
end: dayjsTzToLocalTZ(endDate).toDate(),
|
|
2354
|
-
});
|
|
2355
|
-
}
|
|
2356
|
-
}
|
|
2357
|
-
function handleEndInputValueChange(value) {
|
|
2358
|
-
setInputValues((prevState) => ({ ...prevState, until: value }));
|
|
2359
|
-
if (isValidDate(value)) {
|
|
2360
|
-
const nowEndOfDay = dayjsTz().endOf('day');
|
|
2361
|
-
const newUntilDate = convertDateToTz(value).endOf('day');
|
|
2362
|
-
const clampedUntil = newUntilDate.isAfter(nowEndOfDay) ? nowEndOfDay : newUntilDate;
|
|
2363
|
-
const sinceDate = convertDateToTz(dateRange.since).startOf('day');
|
|
2364
|
-
const startDate = clampedUntil.isBefore(sinceDate) ? clampedUntil.startOf('day') : sinceDate;
|
|
2365
|
-
setDateTimePicked({
|
|
2366
|
-
start: dayjsTzToLocalTZ(startDate).toDate(),
|
|
2367
|
-
end: dayjsTzToLocalTZ(clampedUntil).toDate(),
|
|
2368
|
-
});
|
|
2369
|
-
}
|
|
2370
|
-
}
|
|
2371
|
-
function handleInputBlur() {
|
|
2372
|
-
setIsFocus(false);
|
|
2373
|
-
setInputValues({
|
|
2374
|
-
since: formatDisplayDate(dateRange.since),
|
|
2375
|
-
until: formatDisplayDate(dateRange.until, true),
|
|
2376
|
-
});
|
|
2377
|
-
onBlur && onBlur();
|
|
2378
|
-
}
|
|
2379
|
-
function handleFocusStartInput() {
|
|
2380
|
-
setIsFocus(true);
|
|
2381
|
-
setInputValues({
|
|
2382
|
-
...inputValues,
|
|
2383
|
-
since: formatDate(dateRange.since, 'YMD'),
|
|
2384
|
-
});
|
|
2385
|
-
}
|
|
2386
|
-
function handleFocusEndInput() {
|
|
2387
|
-
setIsFocus(true);
|
|
2388
|
-
setInputValues({
|
|
2389
|
-
...inputValues,
|
|
2390
|
-
until: formatDate(dateRange.until, 'YMD'),
|
|
2391
|
-
});
|
|
2392
|
-
}
|
|
2393
|
-
return (jsxs(InlineGrid, { gap: "200", columns: "1fr auto 1fr", children: [jsx(TextField, { role: "combobox", label: 'Since', labelHidden: true,
|
|
2394
|
-
// prefix={<Icon source={CalendarIcon} />}
|
|
2395
|
-
value: dateRange.since ? inputValues.since : 'MMMM D, YYYY', onChange: handleStartInputValueChange, onBlur: () => handleInputBlur(), onFocus: () => handleFocusStartInput(), autoComplete: "off" }), jsx(InlineStack, { children: jsx(Icon, { source: SvgArrowRightIcon, tone: "subdued" }) }), jsx(TextField, { role: "combobox", label: 'Until', labelHidden: true,
|
|
2396
|
-
// prefix={<Icon source={CalendarIcon} />}
|
|
2397
|
-
value: dateRange.until ? inputValues.until : 'MMMM D, YYYY', onChange: handleEndInputValueChange, onBlur: () => handleInputBlur(), onFocus: () => handleFocusEndInput(), autoComplete: "off" })] }));
|
|
2398
|
-
}
|
|
2399
|
-
|
|
2400
|
-
function DateTimeFilterAddition(props) {
|
|
2401
|
-
const { setDateTimePicked, dateTimePicked, rangeAddition, allRanges } = props;
|
|
2402
|
-
const { value: isExpanded, toggle: toggleExpanded } = useToggle(true);
|
|
2403
|
-
const rangesAdditions = rangeAddition?.rangers || [];
|
|
2404
|
-
const handleChangeFilterByOption = (value) => {
|
|
2405
|
-
const alias = value[0];
|
|
2406
|
-
const result = allRanges.find((range) => range.alias === alias) || allRanges[0];
|
|
2407
|
-
setDateTimePicked({
|
|
2408
|
-
start: dayjsTz(result?.since).toDate(),
|
|
2409
|
-
end: dayjsTz(result?.until).toDate(),
|
|
2410
|
-
alias: result?.alias,
|
|
2411
|
-
});
|
|
2412
|
-
};
|
|
2413
|
-
const options = rangesAdditions.map((range) => {
|
|
2414
|
-
const selected = dateTimePicked.alias === range.alias;
|
|
2415
|
-
return {
|
|
2416
|
-
value: range.alias,
|
|
2417
|
-
label: (jsxs(Text, { as: "span", truncate: true, children: [jsx(Text, { as: "span", variant: 'bodyMd', fontWeight: selected ? 'semibold' : 'regular', children: range.title }), range.description && (jsxs(Fragment, { children: [' ', jsx(Text, { as: "span", variant: 'bodyXs', fontWeight: 'regular', tone: "subdued", children: `(${range.description})` })] }))] })),
|
|
2418
|
-
};
|
|
2419
|
-
});
|
|
2420
|
-
if (!rangeAddition || rangesAdditions.length === 0)
|
|
2421
|
-
return;
|
|
2422
|
-
return (jsxs(Box, { borderBlockEndWidth: '025', borderColor: 'border', paddingBlock: '200', children: [jsx("div", { className: "px-1.5", children: jsx(GDiv, { onClick: toggleExpanded, "aria-expanded": isExpanded, className: cls('hover:bg-surface-hover cursor-pointer rounded-lg p-1.5'), children: jsxs(InlineStack, { align: "space-between", blockAlign: "center", children: [jsx(Text, { as: "span", variant: "bodyMd", children: rangeAddition.title }), jsx(Box, { children: jsx(Icon, { source: isExpanded ? SvgChevronUpIcon : SvgChevronDownIcon }) })] }) }) }), jsx(Collapsible, { open: isExpanded, id: "date-time-filter-periods-collapsible", transition: { duration: '200ms', timingFunction: 'ease-in-out' }, children: jsx(GOptionList, { options: options, selected: dateTimePicked ? [dateTimePicked.alias] : [], onChange: handleChangeFilterByOption }) })] }));
|
|
2423
|
-
}
|
|
2424
|
-
|
|
2425
|
-
function DateTimeFilters(props) {
|
|
2426
|
-
const { setDateTimePicked, dateTimePicked, allRanges, isCompare } = props;
|
|
2427
|
-
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2428
|
-
const { mdDown } = useBreakpoints();
|
|
2429
|
-
const rangesDefault = isCompare ? [...DATE_TIME_COMPARISON_FILTERS] : [...DATE_TIME_FILTERS];
|
|
2430
|
-
const handleChangeFilterBySelect = (value) => {
|
|
2431
|
-
const result = allRanges.find(({ title, alias }) => title === value || alias === value) || allRanges[0];
|
|
2432
|
-
setDateTimePicked({
|
|
2433
|
-
start: dayjsTz(result?.since).toDate(),
|
|
2434
|
-
end: dayjsTz(result?.until).toDate(),
|
|
2435
|
-
alias: result?.alias,
|
|
2436
|
-
});
|
|
2437
|
-
};
|
|
2438
|
-
const handleChangeFilterByOption = (value) => {
|
|
2439
|
-
const result = allRanges.find((range) => range.alias === value[0]) || allRanges[0];
|
|
2440
|
-
setDateTimePicked({
|
|
2441
|
-
start: dayjsTz(result?.since).toDate(),
|
|
2442
|
-
end: dayjsTz(result?.until).toDate(),
|
|
2443
|
-
alias: result?.alias,
|
|
2444
|
-
});
|
|
2445
|
-
};
|
|
2446
|
-
return (jsx(Box, { maxWidth: mdDown ? '516px' : '250px', width: mdDown ? '100%' : '250px', padding: { xs: '500', md: '0' }, paddingBlockEnd: { xs: '100', md: '0' }, children: mdDown ? (jsx(Select, { label: "dateRangeLabel", labelHidden: true, onChange: (value) => handleChangeFilterBySelect(value), value: dateTimePicked?.title || dateTimePicked?.alias || '', options: allRanges.map(({ alias, title }) => title || alias) })) : (jsx(Scrollable, { style: { maxHeight: '356px' }, children: jsx(Box, { children: jsxs(BlockStack, { children: [jsx(DateTimeFilterAddition, { ...props }), jsx(OptionList, { options: rangesDefault.map((range) => ({
|
|
2447
|
-
value: range.alias,
|
|
2448
|
-
label: range.title,
|
|
2449
|
-
})), selected: dateTimePicked ? [dateTimePicked.alias] : [], onChange: (value) => handleChangeFilterByOption(value) })] }) }) })) }));
|
|
2450
|
-
}
|
|
2451
|
-
|
|
2452
|
-
const useCompareDateTimePicker = ({ ranges, onApply }) => {
|
|
2453
|
-
const allRanges = ranges || DATE_TIME_COMPARISON_FILTERS;
|
|
2454
|
-
const { compareDateTimePicked, setCompareDateTimePicked } = useDateTimePickerContext();
|
|
2455
|
-
const { dateTimePicked: mainDateRange } = useDateTimePickerContext();
|
|
2456
|
-
const [dateRange, setDateRange] = useState(compareDateTimePicked);
|
|
2457
|
-
const [{ month, year }, setDate] = useState({
|
|
2458
|
-
month: dayjsTz(compareDateTimePicked.since).month(),
|
|
2459
|
-
year: dayjsTz(compareDateTimePicked.since).year(),
|
|
2460
|
-
});
|
|
2461
|
-
const onMonthChange = (month, year) => {
|
|
2462
|
-
setDate({ month, year });
|
|
2463
|
-
};
|
|
2464
|
-
const onCalendarChange = ({ start, end, alias }) => {
|
|
2465
|
-
const newDateRange = allRanges.find((range) => {
|
|
2466
|
-
return range.alias === alias;
|
|
2467
|
-
});
|
|
2468
|
-
// If the alias is not found, set the custom date range
|
|
2469
|
-
if (!newDateRange) {
|
|
2470
|
-
setDateRange({
|
|
2471
|
-
alias: 'custom',
|
|
2472
|
-
title: 'Custom',
|
|
2473
|
-
since: start.getTime(),
|
|
2474
|
-
until: end.getTime(),
|
|
2475
|
-
});
|
|
2476
|
-
return;
|
|
2477
|
-
}
|
|
2478
|
-
setDateRange({
|
|
2479
|
-
...newDateRange,
|
|
2480
|
-
...COMPARE_DATE_TIME_FILTERS_MAP[alias]({
|
|
2481
|
-
since: mainDateRange.since,
|
|
2482
|
-
until: mainDateRange.until,
|
|
2483
|
-
}),
|
|
2484
|
-
});
|
|
2485
|
-
};
|
|
2486
|
-
const apply = () => {
|
|
2487
|
-
setCompareDateTimePicked(dateRange);
|
|
2488
|
-
onApply?.(dateRange);
|
|
2489
|
-
};
|
|
2490
|
-
const cancel = () => {
|
|
2491
|
-
setDateRange(compareDateTimePicked);
|
|
2492
|
-
};
|
|
2493
|
-
const onChange = ({ end }) => {
|
|
2494
|
-
setDate(getMonthAndYearByDateFilter(month, year, end));
|
|
2495
|
-
};
|
|
2496
|
-
return {
|
|
2497
|
-
month,
|
|
2498
|
-
year,
|
|
2499
|
-
setDate,
|
|
2500
|
-
dateRange,
|
|
2501
|
-
apply,
|
|
2502
|
-
cancel,
|
|
2503
|
-
compareDateTimePicked,
|
|
2504
|
-
onChange,
|
|
2505
|
-
onMonthChange,
|
|
2506
|
-
onCalendarChange,
|
|
2507
|
-
};
|
|
2508
|
-
};
|
|
2509
|
-
|
|
2510
|
-
const BaseTimePicker = (props) => {
|
|
2511
|
-
const { dateTimeFilters, rangeAddition, popoverProps, activatorProps, actionProps, isCompare, buttonValue, activator, } = props;
|
|
2512
|
-
const initialPicked = rangeAddition?.initialPicked;
|
|
2513
|
-
const ranges = [...(dateTimeFilters || []), ...(rangeAddition?.rangers || [])];
|
|
2514
|
-
const useHookDateTimePicker = isCompare ? useCompareDateTimePicker : useDateTimePicker;
|
|
2515
|
-
const { month, year, dateRange, apply, cancel, onMonthChange, onCalendarChange, onChange } = useHookDateTimePicker({
|
|
2516
|
-
ranges,
|
|
2517
|
-
initialPicked,
|
|
2518
|
-
onApply: props.onApply,
|
|
2519
|
-
});
|
|
2520
|
-
const { t } = useTranslation();
|
|
2521
|
-
const { mdDown, lgUp } = useBreakpoints();
|
|
2522
|
-
const shouldShowMultiMonth = lgUp;
|
|
2523
|
-
const rawTooltipContent = useMemo(() => {
|
|
2524
|
-
// Only show tooltip when selecting Period (isVersion)
|
|
2525
|
-
if (!dateRange.isVersion || !dateRange.since || !dateRange.until)
|
|
2526
|
-
return;
|
|
2527
|
-
return formatDateTimeRange({
|
|
2528
|
-
since: dateRange.since,
|
|
2529
|
-
until: dateRange.until,
|
|
2530
|
-
isShowNow: dateRange.isCurrentVersion,
|
|
2531
|
-
});
|
|
2532
|
-
}, [dateRange.since, dateRange.until, dateRange.isVersion, dateRange.isCurrentVersion]);
|
|
2533
|
-
const [popoverActive, setPopoverActive] = useState(false);
|
|
2534
|
-
// Freeze tooltip content while popover is open to prevent button remount (focus/CSS loss)
|
|
2535
|
-
const datePickerRef = useRef(null);
|
|
2536
|
-
const tooltipContentRef = useRef(rawTooltipContent);
|
|
2537
|
-
if (!popoverActive)
|
|
2538
|
-
tooltipContentRef.current = rawTooltipContent;
|
|
2539
|
-
const tooltipContent = tooltipContentRef.current;
|
|
2540
|
-
//@ts-ignore
|
|
2541
|
-
function nodeContainsDescendant(rootNode, descendant) {
|
|
2542
|
-
if (rootNode === descendant) {
|
|
2543
|
-
return true;
|
|
2544
|
-
}
|
|
2545
|
-
let parent = descendant.parentNode;
|
|
2546
|
-
while (parent != null) {
|
|
2547
|
-
if (parent === rootNode) {
|
|
2548
|
-
return true;
|
|
2549
|
-
}
|
|
2550
|
-
parent = parent.parentNode;
|
|
2551
|
-
}
|
|
2552
|
-
return false;
|
|
2553
|
-
}
|
|
2554
|
-
//@ts-ignore
|
|
2555
|
-
function isNodeWithinPopover(node) {
|
|
2556
|
-
return datePickerRef?.current ? nodeContainsDescendant(datePickerRef.current, node) : false;
|
|
2557
|
-
}
|
|
2558
|
-
//@ts-ignore
|
|
2559
|
-
function handleInputBlur({ relatedTarget }) {
|
|
2560
|
-
const isRelatedTargetWithinPopover = relatedTarget != null && isNodeWithinPopover(relatedTarget);
|
|
2561
|
-
// If focus moves from the TextField to the Popover
|
|
2562
|
-
// we don't want to close the popover
|
|
2563
|
-
if (isRelatedTargetWithinPopover) {
|
|
2564
|
-
return;
|
|
2565
|
-
}
|
|
2566
|
-
setPopoverActive(false);
|
|
2567
|
-
}
|
|
2568
|
-
function applyFunc() {
|
|
2569
|
-
apply();
|
|
2570
|
-
setPopoverActive(false);
|
|
2571
|
-
}
|
|
2572
|
-
function cancelFunc() {
|
|
2573
|
-
cancel();
|
|
2574
|
-
setPopoverActive(false);
|
|
2575
|
-
}
|
|
2576
|
-
const handleTogglePopover = () => {
|
|
2577
|
-
if (isCompare) {
|
|
2578
|
-
return;
|
|
2579
|
-
}
|
|
2580
|
-
setPopoverActive(!popoverActive);
|
|
2581
|
-
};
|
|
2582
|
-
const onChangeDateTimeFilter = (data) => {
|
|
2583
|
-
onCalendarChange(data);
|
|
2584
|
-
onChange(data);
|
|
2585
|
-
};
|
|
2586
|
-
return (jsx(Popover, { active: popoverActive, autofocusTarget: "none", preferredAlignment: "right", preferredPosition: "below", fluidContent: true, sectioned: false, fullHeight: true, activator: jsx(GBlockCenter, { height: "100%", minHeight: "28px", align: "center", children: jsx(GTooltip, { content: tooltipContent, maxWidth: activator ? 'large' : 'extra-large', children: jsx(Box, { children: activator ? (activator({ onClick: handleTogglePopover, value: buttonValue })) : (jsx(Button, { size: "slim", icon: !isCompare ? SvgCalendarIcon : undefined, onClick: handleTogglePopover, ...activatorProps, children: buttonValue })) }) }) }), onClose: cancelFunc, ...popoverProps, children: jsxs(Scrollable, { vertical: true, scrollbarWidth: "thin", className: "max-w-[100%]", children: [jsx(Popover.Pane, { fixed: true, children: jsx("div", { ref: datePickerRef, children: jsxs(InlineGrid, { columns: {
|
|
2587
|
-
xs: '1fr',
|
|
2588
|
-
md: 'max-content max-content',
|
|
2589
|
-
}, gap: "0", children: [jsx(DateTimeFilters, { setDateTimePicked: onChangeDateTimeFilter, dateTimePicked: dateRange, rangeAddition: rangeAddition, allRanges: ranges, isCompare: isCompare }), jsx(Box, { padding: "400", maxWidth: mdDown ? '320px' : '516px', borderInlineStartWidth: "025", borderColor: "border-secondary", children: jsxs(BlockStack, { gap: "400", children: [jsx(DateTimeFilterInputs, { setDateTimePicked: onCalendarChange, dateRange: dateRange, onBlur: () => handleInputBlur }), jsx("div", { children: jsx(DatePicker, { month: month, year: year, selected: !dateRange.since && !dateRange.until
|
|
2590
|
-
? undefined
|
|
2591
|
-
: {
|
|
2592
|
-
start: dayjs(dateRange.since).toDate(),
|
|
2593
|
-
end: dayjs(dateRange.until).toDate(),
|
|
2594
|
-
}, onMonthChange: onMonthChange, onChange: onCalendarChange, multiMonth: shouldShowMultiMonth, allowRange: true, disableDatesAfter: dayjsTzToDate() }) }), actionProps && (jsx(GButton, { ...actionProps, onClick: () => {
|
|
2595
|
-
setPopoverActive(false);
|
|
2596
|
-
actionProps.onClick?.();
|
|
2597
|
-
} }))] }) })] }) }) }), jsx(Popover.Pane, { fixed: true, children: jsx(Box, { padding: "400", borderBlockStartWidth: "025", borderColor: "border-secondary", children: jsx(InlineStack, { align: "end", gap: "200", children: jsxs(ButtonGroup, { children: [jsx(Button, { onClick: cancelFunc, children: t('Cancel') }), jsx(Button, { variant: "primary", onClick: applyFunc, children: t('Apply') })] }) }) }) })] }) }));
|
|
2598
|
-
};
|
|
2599
|
-
|
|
2600
|
-
const CompareTimePicker = (props) => {
|
|
2601
|
-
const { rangeAddition, popoverProps } = props;
|
|
2602
|
-
const initialPicked = rangeAddition?.initialPicked;
|
|
2603
|
-
const dateTimeFilters = DATE_TIME_COMPARISON_FILTERS;
|
|
2604
|
-
const ranges = [...dateTimeFilters, ...(rangeAddition?.rangers || [])];
|
|
2605
|
-
const { t } = useTranslation();
|
|
2606
|
-
const { compareDateTimePicked } = useCompareDateTimePicker({ ranges, initialPicked });
|
|
2607
|
-
const buttonValue = useMemo(() => {
|
|
2608
|
-
if (compareDateTimePicked.alias === CompareDateTimePickerAlias.NO_COMPARISON) {
|
|
2609
|
-
return t('No comparison');
|
|
2610
|
-
}
|
|
2611
|
-
return t('Compare to: {{value}}', {
|
|
2612
|
-
value: getDateRangeTitle(compareDateTimePicked.since, compareDateTimePicked.until),
|
|
2613
|
-
});
|
|
2614
|
-
}, [compareDateTimePicked, t]);
|
|
2615
|
-
return (jsx(BaseTimePicker, { dateTimeFilters: dateTimeFilters, rangeAddition: rangeAddition, popoverProps: popoverProps, isCompare: true, buttonValue: buttonValue }));
|
|
2616
|
-
};
|
|
2617
|
-
|
|
2618
|
-
const MainTimePicker = (props) => {
|
|
2619
|
-
const { rangeAddition, popoverProps, activator, onApply, activatorProps, actionProps } = props;
|
|
2620
|
-
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2621
|
-
const dateTimeFilters = DATE_TIME_FILTERS;
|
|
2622
|
-
const additionalRanges = rangeAddition?.rangers || [];
|
|
2623
|
-
const initialPicked = rangeAddition?.initialPicked;
|
|
2624
|
-
const ranges = [...dateTimeFilters, ...additionalRanges];
|
|
2625
|
-
const { dateTimePicked } = useDateTimePicker({ ranges, initialPicked });
|
|
2626
|
-
const getButtonValue = () => {
|
|
2627
|
-
if (dateTimePicked.isVersion && additionalRanges.length > 0) {
|
|
2628
|
-
const time = dateTimePicked.description ? `at ${dateTimePicked.description}` : '';
|
|
2629
|
-
return `Period: ${dateTimePicked.title} ${time}`;
|
|
2630
|
-
}
|
|
2631
|
-
if (dateTimePicked.alias === 'custom') {
|
|
2632
|
-
return getDateRangeTitle(dateTimePicked.since, dateTimePicked.until);
|
|
2633
|
-
}
|
|
2634
|
-
return dateTimePicked.title;
|
|
2635
|
-
};
|
|
2636
|
-
return (jsx(BaseTimePicker, { activatorProps: activatorProps, dateTimeFilters: dateTimeFilters, rangeAddition: rangeAddition, popoverProps: popoverProps, actionProps: actionProps, buttonValue: getButtonValue(), activator: activator, onApply: onApply }));
|
|
2637
|
-
};
|
|
2638
|
-
|
|
2639
|
-
const GTimePicker = (props) => {
|
|
2640
|
-
const { isCompare, ...timePickerProps } = props;
|
|
2641
|
-
return (jsxs(InlineStack, { gap: "200", children: [jsx(MainTimePicker, { ...timePickerProps }), isCompare && (jsx(CompareTimePicker, { rangeAddition: timePickerProps.rangeAddition, popoverProps: timePickerProps.popoverProps }))] }));
|
|
2642
|
-
};
|
|
2643
|
-
|
|
2644
|
-
function isBrowser() {
|
|
2645
|
-
return typeof window !== 'undefined';
|
|
2646
|
-
}
|
|
2647
|
-
const useIsStickyById = ({ id, stickyTop, threshold = 0, enabled = true }) => {
|
|
2648
|
-
const [isSticky, setIsSticky] = useState(false);
|
|
2649
|
-
useEffect(() => {
|
|
2650
|
-
if (!enabled || !isBrowser())
|
|
2651
|
-
return;
|
|
2652
|
-
const el = document.getElementById(id);
|
|
2653
|
-
if (!el)
|
|
2654
|
-
return;
|
|
2655
|
-
const checkSticky = () => {
|
|
2656
|
-
const rect = el.getBoundingClientRect();
|
|
2657
|
-
setIsSticky(rect.top <= stickyTop + threshold);
|
|
2658
|
-
};
|
|
2659
|
-
checkSticky();
|
|
2660
|
-
window.addEventListener('scroll', checkSticky, { passive: true });
|
|
2661
|
-
window.addEventListener('resize', checkSticky);
|
|
2662
|
-
return () => {
|
|
2663
|
-
window.removeEventListener('scroll', checkSticky);
|
|
2664
|
-
window.removeEventListener('resize', checkSticky);
|
|
2665
|
-
};
|
|
2666
|
-
}, [id, stickyTop, threshold, enabled]);
|
|
2667
|
-
return isSticky;
|
|
2668
|
-
};
|
|
2669
|
-
|
|
2670
|
-
// Border is deferred until the row is actually stuck so it doesn't flash on initial render.
|
|
2671
|
-
const useStickyFilterBoxProps = ({ id }) => {
|
|
2672
|
-
const { isMobileView } = useWindowSize();
|
|
2673
|
-
const enabled = isMobileView && Boolean(id);
|
|
2674
|
-
const isStuck = useIsStickyById({ id, stickyTop: 0, enabled });
|
|
2675
|
-
if (!enabled)
|
|
2676
|
-
return {};
|
|
2677
|
-
return {
|
|
2678
|
-
position: 'sticky',
|
|
2679
|
-
insetBlockStart: '0',
|
|
2680
|
-
zIndex: '10',
|
|
2681
|
-
background: 'bg',
|
|
2682
|
-
paddingBlock: '200',
|
|
2683
|
-
...(isStuck && { borderBlockEndWidth: '025', borderColor: 'border' }),
|
|
2684
|
-
};
|
|
2685
|
-
};
|
|
2686
|
-
|
|
2687
|
-
export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, ConvertMoneyProvider, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricChartProvider, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE, convertDateToTz, convertToDateTimeFilters, createLastDaysRange, dayjsTz, dayjsTzToDate, dayjsTzToLocalTZ, formatDate, formatDateTimeRange, formatDayjs, formatMs, formatTime, formatTimeRange, getDateRangeTitle, getDateTimeFilterBase, getDateTimeFilterByAlias, getDateTimeFilterMapping, getEndOfDayBy, getInitialTimezone, getLast12Months, getLast30Days, getLast365Days, getLast7Days, getLast90Days, getLastMonth, getLastYear, getMonthAndYearByDateFilter, getNoComparison, getPreviousMonth, getPreviousPeriod, getPreviousQuarter, getPreviousWeek, getPreviousYear, getToday, getVersionDateDescription, getVersionDateRangeTitle, getYesterday, isDate, isMidnight, isSameDayTimestamp, isValidDate, isValidYearMonthDayDateString, parseYearMonthDayDateString, setTz, useConvertMoneyContext, useCurrencyRatesStore, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useIsStickyById, useStickyFilterBoxProps, useVersionDateTimeFilters };
|
|
1021
|
+
export { ANALYTICS_METRIC_TOOLTIP, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, EAnalyticColumnKey, EDeviceType, EMetricKey, ETrafficSourceType, EVisitorType, GSelectableMetricChartCard, MetricDonutChartCard, PLACEHOLDER_VALUE, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE };
|