@levi-gemcommerce/analytics 1.0.0-dev.11 → 1.0.0-dev.13
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/GTimePicker/GTimePicker.d.ts +17 -0
- package/dist/esm/components/GTimePicker/components/BaseTimePicker.d.ts +10 -0
- package/dist/esm/components/GTimePicker/components/CompareTimePicker.d.ts +5 -0
- package/dist/esm/components/GTimePicker/components/DateTimeFilterAddition.d.ts +2 -0
- package/dist/esm/components/GTimePicker/components/DateTimeFilterInputs.d.ts +9 -0
- package/dist/esm/components/GTimePicker/components/DateTimeFilters.d.ts +15 -0
- package/dist/esm/components/GTimePicker/components/MainTimePicker.d.ts +3 -0
- package/dist/esm/components/GTimePicker/components/index.d.ts +2 -0
- package/dist/esm/components/GTimePicker/constants/compareDateTimePicker.d.ts +12 -0
- package/dist/esm/components/GTimePicker/constants/datePicker.d.ts +14 -0
- package/dist/esm/components/GTimePicker/constants/index.d.ts +2 -0
- package/dist/esm/components/GTimePicker/constants/mainDataTimePicker.d.ts +14 -0
- package/dist/esm/components/GTimePicker/contexts/DateTimePickerProvider.d.ts +15 -0
- package/dist/esm/components/GTimePicker/contexts/index.d.ts +1 -0
- package/dist/esm/components/GTimePicker/helpers/date-range-info.d.ts +16 -0
- package/dist/esm/components/GTimePicker/helpers/index.d.ts +4 -0
- package/dist/esm/components/GTimePicker/helpers/parse-date.d.ts +24 -0
- package/dist/esm/components/GTimePicker/helpers/time-picker.d.ts +76 -0
- package/dist/esm/components/GTimePicker/helpers/version.d.ts +2 -0
- package/dist/esm/components/GTimePicker/hooks/index.d.ts +3 -0
- package/dist/esm/components/GTimePicker/hooks/useCompareDateTimePicker.d.ts +25 -0
- package/dist/esm/components/GTimePicker/hooks/useDateTimeFilter.d.ts +18 -0
- package/dist/esm/components/GTimePicker/hooks/useDateTimePicker.d.ts +30 -0
- package/dist/esm/components/GTimePicker/hooks/useVersionDateTimeFilters.d.ts +9 -0
- package/dist/esm/components/GTimePicker/index.d.ts +7 -0
- package/dist/esm/components/GTimePicker/types/index.d.ts +38 -0
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/core/gemxql/helpers/getTimeDimension.d.ts +1 -1
- package/dist/esm/core/gemxql/index.d.ts +0 -2
- package/dist/esm/core/gemxql/types/date-filter.d.ts +1 -1
- package/dist/esm/gemxql.js +38 -48
- package/dist/esm/gemxql.mjs +38 -48
- package/dist/esm/index.d.ts +1 -4
- package/dist/esm/index.js +1377 -1414
- package/dist/esm/index.mjs +1377 -1414
- package/dist/esm/shared/charts/components/GPolarisViz/utilities/getFontSize.d.ts +1 -1
- package/dist/esm/shared/components/GTimePicker/GTimePicker.d.ts +1 -1
- package/dist/esm/shared/components/GTimePicker/helpers/parse-date.d.ts +2 -2
- package/dist/esm/shared/components/GTimePicker/hooks/useCompareDateTimePicker.d.ts +1 -2
- package/dist/esm/shared/components/GTimePicker/types/index.d.ts +1 -1
- package/dist/esm/shared/components/index.d.ts +0 -1
- package/dist/esm/utils/dayjs.d.ts +10 -0
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/umd/esm/components/GTimePicker/GTimePicker.d.ts +17 -0
- package/dist/umd/esm/components/GTimePicker/components/BaseTimePicker.d.ts +10 -0
- package/dist/umd/esm/components/GTimePicker/components/CompareTimePicker.d.ts +5 -0
- package/dist/umd/esm/components/GTimePicker/components/DateTimeFilterAddition.d.ts +2 -0
- package/dist/umd/esm/components/GTimePicker/components/DateTimeFilterInputs.d.ts +9 -0
- package/dist/umd/esm/components/GTimePicker/components/DateTimeFilters.d.ts +15 -0
- package/dist/umd/esm/components/GTimePicker/components/MainTimePicker.d.ts +3 -0
- package/dist/umd/esm/components/GTimePicker/components/index.d.ts +2 -0
- package/dist/umd/esm/components/GTimePicker/constants/compareDateTimePicker.d.ts +12 -0
- package/dist/umd/esm/components/GTimePicker/constants/datePicker.d.ts +14 -0
- package/dist/umd/esm/components/GTimePicker/constants/index.d.ts +2 -0
- package/dist/umd/esm/components/GTimePicker/constants/mainDataTimePicker.d.ts +14 -0
- package/dist/umd/esm/components/GTimePicker/contexts/DateTimePickerProvider.d.ts +15 -0
- package/dist/umd/esm/components/GTimePicker/contexts/index.d.ts +1 -0
- package/dist/umd/esm/components/GTimePicker/helpers/date-range-info.d.ts +16 -0
- package/dist/umd/esm/components/GTimePicker/helpers/index.d.ts +4 -0
- package/dist/umd/esm/components/GTimePicker/helpers/parse-date.d.ts +24 -0
- package/dist/umd/esm/components/GTimePicker/helpers/time-picker.d.ts +76 -0
- package/dist/umd/esm/components/GTimePicker/helpers/version.d.ts +2 -0
- package/dist/umd/esm/components/GTimePicker/hooks/index.d.ts +3 -0
- package/dist/umd/esm/components/GTimePicker/hooks/useCompareDateTimePicker.d.ts +25 -0
- package/dist/umd/esm/components/GTimePicker/hooks/useDateTimeFilter.d.ts +18 -0
- package/dist/umd/esm/components/GTimePicker/hooks/useDateTimePicker.d.ts +30 -0
- package/dist/umd/esm/components/GTimePicker/hooks/useVersionDateTimeFilters.d.ts +9 -0
- package/dist/umd/esm/components/GTimePicker/index.d.ts +7 -0
- package/dist/umd/esm/components/GTimePicker/types/index.d.ts +38 -0
- package/dist/umd/esm/components/index.d.ts +1 -0
- package/dist/umd/esm/core/gemxql/helpers/getTimeDimension.d.ts +1 -1
- package/dist/umd/esm/core/gemxql/index.d.ts +0 -2
- package/dist/umd/esm/core/gemxql/types/date-filter.d.ts +1 -1
- package/dist/umd/esm/index.d.ts +1 -4
- package/dist/umd/esm/shared/charts/components/GPolarisViz/utilities/getFontSize.d.ts +1 -1
- package/dist/umd/esm/shared/components/GTimePicker/GTimePicker.d.ts +1 -1
- package/dist/umd/esm/shared/components/GTimePicker/helpers/parse-date.d.ts +2 -2
- package/dist/umd/esm/shared/components/GTimePicker/hooks/useCompareDateTimePicker.d.ts +1 -2
- package/dist/umd/esm/shared/components/GTimePicker/types/index.d.ts +1 -1
- package/dist/umd/esm/shared/components/index.d.ts +0 -1
- package/dist/umd/esm/utils/dayjs.d.ts +10 -0
- package/dist/umd/esm/utils/index.d.ts +1 -0
- package/dist/umd/gemxql.js +1 -1
- package/dist/umd/index.js +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
import '@tanstack/react-query';
|
|
4
4
|
import dayjs from 'dayjs';
|
|
5
|
+
export { default as dayjs } from 'dayjs';
|
|
5
6
|
import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
|
|
6
7
|
import timezone from 'dayjs/plugin/timezone.js';
|
|
7
8
|
import utc from 'dayjs/plugin/utc.js';
|
|
8
9
|
import React, { useMemo, useCallback, useState, useEffect, forwardRef, Fragment as Fragment$1, useRef, useImperativeHandle, createContext, useContext } from 'react';
|
|
9
|
-
import { Text, Box, InlineStack, Icon, InlineGrid, Tooltip, Button, BlockStack, Checkbox, RadioButton, Popover, ActionList, Link, SkeletonDisplayText, List, TextField, Collapsible, useBreakpoints, Select, Scrollable, OptionList, DatePicker, ButtonGroup
|
|
10
|
+
import { Text, Box, InlineStack, Icon, InlineGrid, Tooltip, Button, BlockStack, Checkbox, RadioButton, Popover, ActionList, Link, SkeletonDisplayText, List, Card, SkeletonBodyText, TextField, Collapsible, useBreakpoints, Select, Scrollable, OptionList, DatePicker, ButtonGroup } from '@shopify/polaris';
|
|
10
11
|
import { useTranslation } from 'react-i18next';
|
|
11
12
|
import { PolarisVizProvider, LineChart, DonutChart } from '@shopify/polaris-viz';
|
|
12
13
|
|
|
@@ -348,30 +349,6 @@ EGroupOperator.OR;
|
|
|
348
349
|
},
|
|
349
350
|
];
|
|
350
351
|
|
|
351
|
-
dayjs.extend(utc);
|
|
352
|
-
dayjs.extend(timezone);
|
|
353
|
-
dayjs.extend(quarterOfYear);
|
|
354
|
-
let tz = 'UTC';
|
|
355
|
-
const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
|
356
|
-
const dayjsTz = (date) => {
|
|
357
|
-
if (!date)
|
|
358
|
-
return dayjs().tz(tz);
|
|
359
|
-
return dayjs(date).tz(tz);
|
|
360
|
-
};
|
|
361
|
-
const convertDateToTz = (date) => {
|
|
362
|
-
if (!date)
|
|
363
|
-
return dayjs.tz(dayjs().format(DEFAULT_DATE_FORMAT), tz);
|
|
364
|
-
return dayjs.tz(dayjs(date).format(DEFAULT_DATE_FORMAT), tz);
|
|
365
|
-
};
|
|
366
|
-
const dayjsTzToLocalTZ = (date) => {
|
|
367
|
-
if (!date)
|
|
368
|
-
return dayjs(dayjsTz().format(DEFAULT_DATE_FORMAT));
|
|
369
|
-
return dayjs(dayjsTz(date).format(DEFAULT_DATE_FORMAT));
|
|
370
|
-
};
|
|
371
|
-
const dayjsTzToDate = (date) => {
|
|
372
|
-
return dayjsTzToLocalTZ(date).toDate();
|
|
373
|
-
};
|
|
374
|
-
|
|
375
352
|
const TRIM_DECIMAL_ZEROS_REGEX = /\.0+$/;
|
|
376
353
|
const DEFAULT_DECIMALS = 2;
|
|
377
354
|
const trimDecimalZeros = (number) => {
|
|
@@ -419,6 +396,118 @@ const formatPercentage = (percentage, decimals = DEFAULT_DECIMALS) => {
|
|
|
419
396
|
return `${cleanDecimal(percentage, decimals)}%`;
|
|
420
397
|
};
|
|
421
398
|
|
|
399
|
+
function toVal(mix) {
|
|
400
|
+
if (typeof mix === 'string') {
|
|
401
|
+
return mix;
|
|
402
|
+
}
|
|
403
|
+
else if (typeof mix === 'object' && mix !== null) {
|
|
404
|
+
return Object.keys(mix)
|
|
405
|
+
.filter((key) => mix[key])
|
|
406
|
+
.join(' ');
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function cls(...classes) {
|
|
413
|
+
return classes.map(toVal).filter(Boolean).join(' ');
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function compareValues(a, b, order = 'asc') {
|
|
417
|
+
if (a === b)
|
|
418
|
+
return 0;
|
|
419
|
+
if (a === undefined || b === undefined) {
|
|
420
|
+
if (a === undefined && b !== undefined)
|
|
421
|
+
return order === 'asc' ? -1 : 1;
|
|
422
|
+
if (b === undefined && a !== undefined)
|
|
423
|
+
return order === 'asc' ? 1 : -1;
|
|
424
|
+
return 0;
|
|
425
|
+
}
|
|
426
|
+
const isDate = (val) => typeof val !== 'boolean' && !isNaN(Date.parse(val));
|
|
427
|
+
const isString = (val) => typeof val === 'string';
|
|
428
|
+
let comparison = 0;
|
|
429
|
+
if (isDate(a) && isDate(b)) {
|
|
430
|
+
const dateA = a instanceof Date ? a : new Date(a);
|
|
431
|
+
const dateB = b instanceof Date ? b : new Date(b);
|
|
432
|
+
comparison = dateA > dateB ? 1 : -1;
|
|
433
|
+
}
|
|
434
|
+
else if (isString(a) && isString(b)) {
|
|
435
|
+
comparison = a > b ? 1 : -1;
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
comparison = a > b ? 1 : -1;
|
|
439
|
+
}
|
|
440
|
+
return order === 'asc' ? -comparison : comparison;
|
|
441
|
+
}
|
|
442
|
+
function getNestedValue(obj, path) {
|
|
443
|
+
if (typeof path === 'string') {
|
|
444
|
+
return path
|
|
445
|
+
.replace(/\[(\d+)\]/g, '.$1')
|
|
446
|
+
.split('.')
|
|
447
|
+
.reduce((acc, key) => acc?.[key], obj);
|
|
448
|
+
}
|
|
449
|
+
return obj[path];
|
|
450
|
+
}
|
|
451
|
+
function sortByCondition(array, options) {
|
|
452
|
+
const { attr, order = 'asc', preferredValue, backupAttr, orderArrayAttr, orderArray } = options;
|
|
453
|
+
return array.slice().sort((a, b) => {
|
|
454
|
+
const valueA = getNestedValue(a, attr);
|
|
455
|
+
const valueB = getNestedValue(b, attr);
|
|
456
|
+
if (preferredValue !== undefined) {
|
|
457
|
+
if (valueA === preferredValue && valueB !== preferredValue)
|
|
458
|
+
return -1;
|
|
459
|
+
if (valueB === preferredValue && valueA !== preferredValue)
|
|
460
|
+
return 1;
|
|
461
|
+
}
|
|
462
|
+
if (orderArrayAttr === attr && orderArray) {
|
|
463
|
+
const orderArrayValue = orderArray[order];
|
|
464
|
+
return orderArrayValue.indexOf(valueA) - orderArrayValue.indexOf(valueB);
|
|
465
|
+
}
|
|
466
|
+
const primaryComparison = compareValues(valueA, valueB, order);
|
|
467
|
+
if (primaryComparison !== 0)
|
|
468
|
+
return primaryComparison;
|
|
469
|
+
if (backupAttr)
|
|
470
|
+
return compareValues(a[backupAttr], b[backupAttr], order);
|
|
471
|
+
return 0;
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
function sortByConditions(array, optionsArray) {
|
|
475
|
+
return optionsArray.reduce((sortedArray, options) => {
|
|
476
|
+
return sortByCondition(sortedArray, options);
|
|
477
|
+
}, array.slice());
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
dayjs.extend(utc);
|
|
481
|
+
dayjs.extend(timezone);
|
|
482
|
+
dayjs.extend(quarterOfYear);
|
|
483
|
+
let tz = 'UTC';
|
|
484
|
+
const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD HH:mm:ss';
|
|
485
|
+
function getInitialTimezone() {
|
|
486
|
+
return tz;
|
|
487
|
+
}
|
|
488
|
+
function setTz(value) {
|
|
489
|
+
tz = value;
|
|
490
|
+
dayjs.tz.setDefault(value);
|
|
491
|
+
}
|
|
492
|
+
const dayjsTz = (date) => {
|
|
493
|
+
if (!date)
|
|
494
|
+
return dayjs().tz(tz);
|
|
495
|
+
return dayjs(date).tz(tz);
|
|
496
|
+
};
|
|
497
|
+
const convertDateToTz = (date) => {
|
|
498
|
+
if (!date)
|
|
499
|
+
return dayjs.tz(dayjs().format(DEFAULT_DATE_FORMAT), tz);
|
|
500
|
+
return dayjs.tz(dayjs(date).format(DEFAULT_DATE_FORMAT), tz);
|
|
501
|
+
};
|
|
502
|
+
const dayjsTzToLocalTZ = (date) => {
|
|
503
|
+
if (!date)
|
|
504
|
+
return dayjs(dayjsTz().format(DEFAULT_DATE_FORMAT));
|
|
505
|
+
return dayjs(dayjsTz(date).format(DEFAULT_DATE_FORMAT));
|
|
506
|
+
};
|
|
507
|
+
const dayjsTzToDate = (date) => {
|
|
508
|
+
return dayjsTzToLocalTZ(date).toDate();
|
|
509
|
+
};
|
|
510
|
+
|
|
422
511
|
var AnalyticInterval;
|
|
423
512
|
(function (AnalyticInterval) {
|
|
424
513
|
AnalyticInterval["DAY"] = "DAY";
|
|
@@ -622,16 +711,16 @@ var GPaginationDirection;
|
|
|
622
711
|
GPaginationDirection["PREV"] = "PREV";
|
|
623
712
|
})(GPaginationDirection || (GPaginationDirection = {}));
|
|
624
713
|
|
|
625
|
-
|
|
714
|
+
[
|
|
626
715
|
{ value: EVisitorType.NEW, label: 'New' },
|
|
627
716
|
{ value: EVisitorType.RETURNING, label: 'Returning' },
|
|
628
717
|
];
|
|
629
|
-
|
|
718
|
+
[
|
|
630
719
|
{ value: EDeviceType.DESKTOP, label: 'Desktop' },
|
|
631
720
|
{ value: EDeviceType.TABLET, label: 'Tablet' },
|
|
632
721
|
{ value: EDeviceType.MOBILE, label: 'Mobile' },
|
|
633
722
|
];
|
|
634
|
-
|
|
723
|
+
[
|
|
635
724
|
{ value: ETrafficSourceType.DIRECT, label: 'Direct' },
|
|
636
725
|
{ value: ETrafficSourceType.EMAIL, label: 'Email' },
|
|
637
726
|
{ value: ETrafficSourceType.REFERRAL, label: 'Referral' },
|
|
@@ -642,11 +731,6 @@ const TARGET_CHANNEL = [
|
|
|
642
731
|
{ value: ETrafficSourceType.SMS, label: 'SMS' },
|
|
643
732
|
];
|
|
644
733
|
|
|
645
|
-
const CAMPAIGN_BACKGROUND_MAIN = {
|
|
646
|
-
ORIGIN: '#2C7DFF',
|
|
647
|
-
VARIANT: '#F34A70',
|
|
648
|
-
};
|
|
649
|
-
|
|
650
734
|
const DEFAULT_CURRENT_PERIOD_LABEL = 'Current';
|
|
651
735
|
const DEFAULT_PREVIOUS_PERIOD_LABEL = 'Previous';
|
|
652
736
|
const CHART_MIN_HEIGHT = 228;
|
|
@@ -725,87 +809,6 @@ var SvgChevronUpIcon = function SvgChevronUpIcon(props) {
|
|
|
725
809
|
};
|
|
726
810
|
SvgChevronUpIcon.displayName = "ChevronUpIcon";
|
|
727
811
|
|
|
728
|
-
function toVal(mix) {
|
|
729
|
-
if (typeof mix === 'string') {
|
|
730
|
-
return mix;
|
|
731
|
-
}
|
|
732
|
-
else if (typeof mix === 'object' && mix !== null) {
|
|
733
|
-
return Object.keys(mix)
|
|
734
|
-
.filter((key) => mix[key])
|
|
735
|
-
.join(' ');
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
return false;
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
function cls(...classes) {
|
|
742
|
-
return classes.map(toVal).filter(Boolean).join(' ');
|
|
743
|
-
}
|
|
744
|
-
|
|
745
|
-
function compareValues(a, b, order = 'asc') {
|
|
746
|
-
if (a === b)
|
|
747
|
-
return 0;
|
|
748
|
-
if (a === undefined || b === undefined) {
|
|
749
|
-
if (a === undefined && b !== undefined)
|
|
750
|
-
return order === 'asc' ? -1 : 1;
|
|
751
|
-
if (b === undefined && a !== undefined)
|
|
752
|
-
return order === 'asc' ? 1 : -1;
|
|
753
|
-
return 0;
|
|
754
|
-
}
|
|
755
|
-
const isDate = (val) => typeof val !== 'boolean' && !isNaN(Date.parse(val));
|
|
756
|
-
const isString = (val) => typeof val === 'string';
|
|
757
|
-
let comparison = 0;
|
|
758
|
-
if (isDate(a) && isDate(b)) {
|
|
759
|
-
const dateA = a instanceof Date ? a : new Date(a);
|
|
760
|
-
const dateB = b instanceof Date ? b : new Date(b);
|
|
761
|
-
comparison = dateA > dateB ? 1 : -1;
|
|
762
|
-
}
|
|
763
|
-
else if (isString(a) && isString(b)) {
|
|
764
|
-
comparison = a > b ? 1 : -1;
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
comparison = a > b ? 1 : -1;
|
|
768
|
-
}
|
|
769
|
-
return order === 'asc' ? -comparison : comparison;
|
|
770
|
-
}
|
|
771
|
-
function getNestedValue(obj, path) {
|
|
772
|
-
if (typeof path === 'string') {
|
|
773
|
-
return path
|
|
774
|
-
.replace(/\[(\d+)\]/g, '.$1')
|
|
775
|
-
.split('.')
|
|
776
|
-
.reduce((acc, key) => acc?.[key], obj);
|
|
777
|
-
}
|
|
778
|
-
return obj[path];
|
|
779
|
-
}
|
|
780
|
-
function sortByCondition(array, options) {
|
|
781
|
-
const { attr, order = 'asc', preferredValue, backupAttr, orderArrayAttr, orderArray } = options;
|
|
782
|
-
return array.slice().sort((a, b) => {
|
|
783
|
-
const valueA = getNestedValue(a, attr);
|
|
784
|
-
const valueB = getNestedValue(b, attr);
|
|
785
|
-
if (preferredValue !== undefined) {
|
|
786
|
-
if (valueA === preferredValue && valueB !== preferredValue)
|
|
787
|
-
return -1;
|
|
788
|
-
if (valueB === preferredValue && valueA !== preferredValue)
|
|
789
|
-
return 1;
|
|
790
|
-
}
|
|
791
|
-
if (orderArrayAttr === attr && orderArray) {
|
|
792
|
-
const orderArrayValue = orderArray[order];
|
|
793
|
-
return orderArrayValue.indexOf(valueA) - orderArrayValue.indexOf(valueB);
|
|
794
|
-
}
|
|
795
|
-
const primaryComparison = compareValues(valueA, valueB, order);
|
|
796
|
-
if (primaryComparison !== 0)
|
|
797
|
-
return primaryComparison;
|
|
798
|
-
if (backupAttr)
|
|
799
|
-
return compareValues(a[backupAttr], b[backupAttr], order);
|
|
800
|
-
return 0;
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
function sortByConditions(array, optionsArray) {
|
|
804
|
-
return optionsArray.reduce((sortedArray, options) => {
|
|
805
|
-
return sortByCondition(sortedArray, options);
|
|
806
|
-
}, array.slice());
|
|
807
|
-
}
|
|
808
|
-
|
|
809
812
|
const GClickable = ({ children, fullWidth = false, cursor = 'pointer', onClick, onMouseEnter, onMouseLeave, }) => {
|
|
810
813
|
return (jsx("div", { role: "button", tabIndex: 0, className: cls({
|
|
811
814
|
'w-full': fullWidth,
|
|
@@ -1158,1410 +1161,1370 @@ const GTooltipCard = forwardRef((props, ref) => {
|
|
|
1158
1161
|
});
|
|
1159
1162
|
GTooltipCard.displayName = 'GTooltipCard';
|
|
1160
1163
|
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
getDateRange: getToday,
|
|
1179
|
-
},
|
|
1180
|
-
[MainDateTimePickerAlias.YESTERDAY]: {
|
|
1181
|
-
title: 'Yesterday',
|
|
1182
|
-
alias: MainDateTimePickerAlias.YESTERDAY,
|
|
1183
|
-
getDateRange: getYesterday,
|
|
1184
|
-
},
|
|
1185
|
-
[MainDateTimePickerAlias.LAST_7_DAYS]: {
|
|
1186
|
-
title: 'Last 7 days',
|
|
1187
|
-
alias: MainDateTimePickerAlias.LAST_7_DAYS,
|
|
1188
|
-
getDateRange: getLast7Days,
|
|
1189
|
-
},
|
|
1190
|
-
[MainDateTimePickerAlias.LAST_30_DAYS]: {
|
|
1191
|
-
title: 'Last 30 days',
|
|
1192
|
-
alias: MainDateTimePickerAlias.LAST_30_DAYS,
|
|
1193
|
-
getDateRange: getLast30Days,
|
|
1194
|
-
},
|
|
1195
|
-
[MainDateTimePickerAlias.LAST_90_DAYS]: {
|
|
1196
|
-
title: 'Last 90 days',
|
|
1197
|
-
alias: MainDateTimePickerAlias.LAST_90_DAYS,
|
|
1198
|
-
getDateRange: getLast90Days,
|
|
1199
|
-
},
|
|
1200
|
-
[MainDateTimePickerAlias.LAST_365_DAYS]: {
|
|
1201
|
-
title: 'Last 365 days',
|
|
1202
|
-
alias: MainDateTimePickerAlias.LAST_365_DAYS,
|
|
1203
|
-
getDateRange: getLast365Days,
|
|
1204
|
-
},
|
|
1205
|
-
[MainDateTimePickerAlias.LAST_MONTH]: {
|
|
1206
|
-
title: 'Last month',
|
|
1207
|
-
alias: MainDateTimePickerAlias.LAST_MONTH,
|
|
1208
|
-
getDateRange: getLastMonth,
|
|
1209
|
-
},
|
|
1210
|
-
[MainDateTimePickerAlias.LAST_12_MONTHS]: {
|
|
1211
|
-
title: 'Last 12 months',
|
|
1212
|
-
alias: MainDateTimePickerAlias.LAST_12_MONTHS,
|
|
1213
|
-
getDateRange: getLast12Months,
|
|
1214
|
-
},
|
|
1215
|
-
[MainDateTimePickerAlias.LAST_YEAR]: {
|
|
1216
|
-
title: 'Last year',
|
|
1217
|
-
alias: MainDateTimePickerAlias.LAST_YEAR,
|
|
1218
|
-
getDateRange: getLastYear,
|
|
1219
|
-
},
|
|
1164
|
+
const GViewBySelector = ({ activatorText, selected, options, minWidth, maxWidth, preferredAlignment = 'right', onSelect, }) => {
|
|
1165
|
+
const [popoverActive, setPopoverActive] = useState(false);
|
|
1166
|
+
const [itemHover, setItemHover] = useState(null);
|
|
1167
|
+
const togglePopoverActive = () => setPopoverActive((prev) => !prev);
|
|
1168
|
+
const selectedOption = useMemo(() => {
|
|
1169
|
+
return options.find((item) => item.id === selected);
|
|
1170
|
+
}, [options, selected]);
|
|
1171
|
+
const activatorContent = useMemo(() => {
|
|
1172
|
+
if (selectedOption) {
|
|
1173
|
+
const content = selectedOption.title ?? selectedOption.content;
|
|
1174
|
+
return activatorText ? `${activatorText}: ${content}` : content;
|
|
1175
|
+
}
|
|
1176
|
+
return activatorText;
|
|
1177
|
+
}, [selectedOption, activatorText]);
|
|
1178
|
+
const handleSelect = (value) => {
|
|
1179
|
+
onSelect(value);
|
|
1180
|
+
setPopoverActive(false);
|
|
1220
1181
|
};
|
|
1221
|
-
return
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
const DATE_FORMAT = {
|
|
1229
|
-
YMD: 'YYYY-MM-DD', // 2025-01-01
|
|
1230
|
-
MONTH_YEAR: 'MMM YYYY', // Jan 2025
|
|
1231
|
-
FULL: 'MMMM D, YYYY', // January 1, 2025
|
|
1232
|
-
FULL_WITH_TIME: 'MMMM D, YYYY [at] h:mm A', // January 1, 2025 at 12:00 AM
|
|
1233
|
-
SHORT: 'MMM DD, YYYY', // Jan 01, 2025
|
|
1234
|
-
SHORT_NO_PAD: 'MMM D, YYYY', // Jan 1, 2025
|
|
1235
|
-
SHORT_WITH_TIME: 'MMM D, YYYY [at] h:mm A', // Jan 1, 2025 at 12:00 AM
|
|
1236
|
-
MONTH_DAY: 'MMM D', // Jan 1
|
|
1237
|
-
DAY_YEAR: 'D, YYYY', // 1, 2025
|
|
1238
|
-
TIME: 'h:mm A', // 12:00 AM
|
|
1239
|
-
MONTH_DAY_WITH_TIME: 'MMM D [at] h:mm A', // Jan 1 at 12:00 AM
|
|
1240
|
-
YEAR: 'YYYY', // 2025
|
|
1182
|
+
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) => {
|
|
1183
|
+
const isSelected = option.id === selected;
|
|
1184
|
+
const isHover = itemHover === option.id;
|
|
1185
|
+
const borderColor = isSelected ? 'input-border' : isHover ? 'border-hover' : 'transparent';
|
|
1186
|
+
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));
|
|
1187
|
+
}) }) }) }));
|
|
1241
1188
|
};
|
|
1242
1189
|
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
return !isNaN(new Date(date).getDate());
|
|
1253
|
-
}
|
|
1254
|
-
function isValidYearMonthDayDateString(date) {
|
|
1255
|
-
return VALID_YYYY_MM_DD_DATE_REGEX.test(date) && isDate(date);
|
|
1256
|
-
}
|
|
1257
|
-
function isValidDate(date) {
|
|
1258
|
-
return date.length === 10 && isValidYearMonthDayDateString(date);
|
|
1259
|
-
}
|
|
1260
|
-
function formatDate(timestamp, type) {
|
|
1261
|
-
const date = convertDateToTz(timestamp);
|
|
1262
|
-
if (type === 'YMD') {
|
|
1263
|
-
return date.format(DATE_FORMAT.YMD);
|
|
1264
|
-
}
|
|
1265
|
-
if (type === 'MY') {
|
|
1266
|
-
return date.format(DATE_FORMAT.MONTH_YEAR);
|
|
1267
|
-
}
|
|
1268
|
-
if (type === 'FULL') {
|
|
1269
|
-
return date.format(DATE_FORMAT.FULL);
|
|
1270
|
-
}
|
|
1271
|
-
if (type === 'FULL_WITH_TIME') {
|
|
1272
|
-
return date.format(DATE_FORMAT.FULL_WITH_TIME);
|
|
1273
|
-
}
|
|
1274
|
-
return date.format(DATE_FORMAT.SHORT);
|
|
1275
|
-
}
|
|
1276
|
-
function formatTime(timestamp) {
|
|
1277
|
-
const date = convertDateToTz(timestamp);
|
|
1278
|
-
return date.format(DATE_FORMAT.TIME);
|
|
1279
|
-
}
|
|
1280
|
-
function isSameDayTimestamp(since, until) {
|
|
1281
|
-
const sinceDate = convertDateToTz(since);
|
|
1282
|
-
const untilDate = convertDateToTz(until);
|
|
1283
|
-
return sinceDate.isSame(untilDate, 'day');
|
|
1284
|
-
}
|
|
1285
|
-
function formatTimeRange(data) {
|
|
1286
|
-
const { since, until, format = DATE_FORMAT.TIME, showNow = false } = data;
|
|
1287
|
-
const sinceDate = convertDateToTz(since);
|
|
1288
|
-
const untilDate = convertDateToTz(until);
|
|
1289
|
-
return `${sinceDate.format(format)} - ${showNow ? 'Now' : untilDate.format(format)}`;
|
|
1290
|
-
}
|
|
1291
|
-
function formatDateTimeRange(data) {
|
|
1292
|
-
const { since, until, isShowNow } = data;
|
|
1293
|
-
const sinceDate = convertDateToTz(since);
|
|
1294
|
-
const untilDate = convertDateToTz(until);
|
|
1295
|
-
const isToday = sinceDate.isSame(dayjsTz(), 'day');
|
|
1296
|
-
const startTime = sinceDate.format(DATE_FORMAT.TIME);
|
|
1297
|
-
const endTime = untilDate.format(DATE_FORMAT.TIME);
|
|
1298
|
-
if (isToday) {
|
|
1299
|
-
const formatEndTime = isShowNow ? 'Now' : endTime;
|
|
1300
|
-
return `Today at ${startTime} - ${formatEndTime}`;
|
|
1301
|
-
}
|
|
1302
|
-
if (isShowNow) {
|
|
1303
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - Now`;
|
|
1304
|
-
}
|
|
1305
|
-
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1306
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - ${endTime}`;
|
|
1307
|
-
}
|
|
1308
|
-
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1309
|
-
const time = formatTimeRange({ since, until });
|
|
1310
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT)} (${time})`;
|
|
1311
|
-
}
|
|
1312
|
-
if (sinceDate.isSame(untilDate, 'year')) {
|
|
1313
|
-
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY_WITH_TIME)} - ${untilDate.format(DATE_FORMAT.MONTH_DAY_WITH_TIME)}, ${untilDate.format(DATE_FORMAT.YEAR)}`;
|
|
1314
|
-
}
|
|
1315
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - ${untilDate.format(DATE_FORMAT.SHORT_WITH_TIME)}`;
|
|
1316
|
-
}
|
|
1317
|
-
const formatDayjs = (date, isEndDay = false, formatTemplate) => {
|
|
1318
|
-
// const isUTC = date.isUTC?.() ?? false;
|
|
1319
|
-
// if (isUTC) return date.format();
|
|
1320
|
-
if (isEndDay && isMidnight(date)) {
|
|
1321
|
-
return date.endOf('day').format(formatTemplate);
|
|
1322
|
-
}
|
|
1323
|
-
return date.format(formatTemplate);
|
|
1190
|
+
const ChoiceHelpText = ({ item }) => {
|
|
1191
|
+
return (jsxs(Text, { as: "p", variant: "bodyMd", children: [item.description, item.inlineAction && (jsx(Link, { monochrome: true, onClick: () => {
|
|
1192
|
+
if (item.inlineAction?.onAction) {
|
|
1193
|
+
item.inlineAction?.onAction();
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
window.open(item.inlineAction?.url, item.inlineAction?.target ?? '_blank');
|
|
1197
|
+
}
|
|
1198
|
+
}, children: item.inlineAction?.content }))] }));
|
|
1324
1199
|
};
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
}
|
|
1329
|
-
return formatDayjs(dayjsTz(value).endOf('day'), false, formatTemplate);
|
|
1200
|
+
|
|
1201
|
+
const GChartSkeleton = () => {
|
|
1202
|
+
return jsx(GSkeletonDisplayText, { height: "188px" });
|
|
1330
1203
|
};
|
|
1331
|
-
|
|
1332
|
-
|
|
1204
|
+
|
|
1205
|
+
const LINE_SERIES_COLORS = {
|
|
1206
|
+
comparison: SERIES_COLORS.comparison,
|
|
1207
|
+
single: SERIES_COLORS.current,
|
|
1208
|
+
all: [...SERIES_COLORS.all],
|
|
1333
1209
|
};
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1210
|
+
const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesColors = LINE_SERIES_COLORS, }) => {
|
|
1211
|
+
return (jsx(PolarisVizProvider, { themes: {
|
|
1212
|
+
Light: {
|
|
1213
|
+
chartContainer: {
|
|
1214
|
+
minHeight,
|
|
1215
|
+
},
|
|
1216
|
+
grid: {
|
|
1217
|
+
horizontalOverflow: true,
|
|
1218
|
+
verticalOverflow: true,
|
|
1219
|
+
horizontalMargin: 0,
|
|
1220
|
+
},
|
|
1221
|
+
seriesColors,
|
|
1222
|
+
},
|
|
1223
|
+
}, children: children }));
|
|
1340
1224
|
};
|
|
1341
1225
|
|
|
1342
|
-
function getDateRangeTitle(since, until) {
|
|
1343
|
-
const sinceDate = convertDateToTz(since);
|
|
1344
|
-
const untilDate = convertDateToTz(until);
|
|
1345
|
-
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1346
|
-
return sinceDate.format(DATE_FORMAT.SHORT);
|
|
1347
|
-
}
|
|
1348
|
-
if (sinceDate.isSame(untilDate, 'month') && sinceDate.isSame(untilDate, 'year')) {
|
|
1349
|
-
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY)} - ${untilDate.format(DATE_FORMAT.DAY_YEAR)}`;
|
|
1350
|
-
}
|
|
1351
|
-
if (sinceDate.isSame(untilDate, 'year')) {
|
|
1352
|
-
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY)} - ${untilDate.format(DATE_FORMAT.SHORT_NO_PAD)}`;
|
|
1353
|
-
}
|
|
1354
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_NO_PAD)} - ${untilDate.format(DATE_FORMAT.SHORT_NO_PAD)}`;
|
|
1355
|
-
}
|
|
1356
1226
|
/**
|
|
1357
|
-
*
|
|
1358
|
-
*
|
|
1359
|
-
* a formatted custom range with alias "custom".
|
|
1227
|
+
* Returns a stateful value, and a set of memoized functions to toggle it,
|
|
1228
|
+
* set it to true and set it to false
|
|
1360
1229
|
*/
|
|
1361
|
-
function
|
|
1362
|
-
const
|
|
1363
|
-
const sinceDate = convertDateToTz(since);
|
|
1364
|
-
const untilDate = convertDateToTz(until);
|
|
1365
|
-
const mappings = getDateTimeFilterMapping();
|
|
1366
|
-
for (const mapping of Object.values(mappings)) {
|
|
1367
|
-
const range = mapping.getDateRange(now);
|
|
1368
|
-
const expectedSince = convertDateToTz(range.since);
|
|
1369
|
-
const expectedUntil = convertDateToTz(range.until);
|
|
1370
|
-
const isSameSince = sinceDate.isSame(expectedSince, 'day');
|
|
1371
|
-
const isSameUntil = untilDate.isSame(expectedUntil, 'day');
|
|
1372
|
-
if (isSameSince && isSameUntil) {
|
|
1373
|
-
return { title: mapping.title, alias: mapping.alias };
|
|
1374
|
-
}
|
|
1375
|
-
}
|
|
1230
|
+
function useToggle(initialState) {
|
|
1231
|
+
const [value, setState] = useState(initialState);
|
|
1376
1232
|
return {
|
|
1377
|
-
|
|
1378
|
-
|
|
1233
|
+
value,
|
|
1234
|
+
toggle: useCallback(() => setState((state) => !state), []),
|
|
1235
|
+
setTrue: useCallback(() => setState(true), []),
|
|
1236
|
+
setFalse: useCallback(() => setState(false), []),
|
|
1379
1237
|
};
|
|
1380
1238
|
}
|
|
1381
|
-
function getVersionDateRangeTitle(data) {
|
|
1382
|
-
const { since, until, isShowNow } = data;
|
|
1383
|
-
const sinceDate = convertDateToTz(since);
|
|
1384
|
-
const isToday = sinceDate.isSame(dayjsTz(), 'day');
|
|
1385
|
-
if (isToday)
|
|
1386
|
-
return getDateTimeFilterByAlias(MainDateTimePickerAlias.TODAY).title;
|
|
1387
|
-
if (isShowNow)
|
|
1388
|
-
return `${sinceDate.format(DATE_FORMAT.SHORT_NO_PAD)} - Now`;
|
|
1389
|
-
return getDateRangeTitle(since, until);
|
|
1390
|
-
}
|
|
1391
|
-
const getVersionDateDescription = ({ since, until, isShowNow }) => {
|
|
1392
|
-
const isSameDay = isSameDayTimestamp(since, until);
|
|
1393
|
-
if (!isSameDay)
|
|
1394
|
-
return undefined;
|
|
1395
|
-
return formatTimeRange({ since, until, showNow: isShowNow });
|
|
1396
|
-
};
|
|
1397
1239
|
|
|
1398
|
-
const
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1240
|
+
const useFormatLineChartData = ({ metricKey, columnTypes }) => {
|
|
1241
|
+
const { formatData } = useAnalyticData();
|
|
1242
|
+
const formatter = metricKey ? columnTypes?.[metricKey] : undefined;
|
|
1243
|
+
const formatValue = (value) => {
|
|
1244
|
+
return String(formatData({ value, formatter }));
|
|
1245
|
+
};
|
|
1246
|
+
const yAxisOptions = {
|
|
1247
|
+
labelFormatter: (value) => {
|
|
1248
|
+
return formatValue(Number(value) || 0);
|
|
1249
|
+
},
|
|
1250
|
+
};
|
|
1251
|
+
return { formatValue, yAxisOptions };
|
|
1252
|
+
};
|
|
1253
|
+
|
|
1254
|
+
const useWindowSize = () => {
|
|
1255
|
+
const [windowSize, setWindowSize] = useState(() => ({
|
|
1256
|
+
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
1257
|
+
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
1258
|
+
}));
|
|
1259
|
+
const windowWidth = useMemo(() => {
|
|
1411
1260
|
return {
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
description,
|
|
1419
|
-
versionId: item.id,
|
|
1261
|
+
xs: windowSize.width <= 768,
|
|
1262
|
+
md: 768 < windowSize.width && windowSize.width <= 1024,
|
|
1263
|
+
lg: windowSize.width > 1024,
|
|
1264
|
+
xsDown: windowSize.width < 768,
|
|
1265
|
+
'1200Down': windowSize.width < 1200,
|
|
1266
|
+
'1040Down': windowSize.width < 1040,
|
|
1420
1267
|
};
|
|
1421
|
-
})
|
|
1422
|
-
|
|
1268
|
+
}, [windowSize.width]);
|
|
1269
|
+
const isMobileTabletView = !windowWidth.lg;
|
|
1270
|
+
const isMobileView = windowWidth.xs;
|
|
1271
|
+
useEffect(() => {
|
|
1272
|
+
const windowSizeHandler = () => {
|
|
1273
|
+
setWindowSize({ width: window.innerWidth, height: window.innerHeight });
|
|
1274
|
+
};
|
|
1275
|
+
window.addEventListener('resize', windowSizeHandler);
|
|
1276
|
+
return () => {
|
|
1277
|
+
window.removeEventListener('resize', windowSizeHandler);
|
|
1278
|
+
};
|
|
1279
|
+
}, []);
|
|
1280
|
+
return { windowSize, windowWidth, isMobileTabletView, isMobileView };
|
|
1423
1281
|
};
|
|
1424
1282
|
|
|
1425
|
-
const
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
};
|
|
1430
|
-
};
|
|
1431
|
-
const getPreviousPeriod = (value) => {
|
|
1432
|
-
const { since, until, alias } = value;
|
|
1433
|
-
const sinceDate = dayjs(since);
|
|
1434
|
-
const untilDate = dayjs(until);
|
|
1435
|
-
if (alias === MainDateTimePickerAlias.LAST_MONTH) {
|
|
1436
|
-
return getLastMonth(sinceDate);
|
|
1283
|
+
const MetricChart = ({ lineChartData, isLoading, isEmptyMetricData, columnTypes, metricKey, }) => {
|
|
1284
|
+
const { formatValue, yAxisOptions } = useFormatLineChartData({ metricKey, columnTypes: columnTypes || {} });
|
|
1285
|
+
if (!metricKey) {
|
|
1286
|
+
return jsx(Fragment, {});
|
|
1437
1287
|
}
|
|
1438
|
-
if (
|
|
1439
|
-
return
|
|
1288
|
+
if (isLoading) {
|
|
1289
|
+
return jsx(GChartSkeleton, {});
|
|
1440
1290
|
}
|
|
1441
|
-
if (
|
|
1442
|
-
return
|
|
1291
|
+
if (isEmptyMetricData) {
|
|
1292
|
+
return jsx(MetricChartEmpty, { title: "No data yet", description: "Data needs time to gather" });
|
|
1443
1293
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
}
|
|
1452
|
-
|
|
1453
|
-
const { since, until } = value;
|
|
1454
|
-
const sinceDate = dayjs(since);
|
|
1455
|
-
const untilDate = dayjs(until);
|
|
1456
|
-
const duration = untilDate.diff(sinceDate, 'day');
|
|
1457
|
-
const previousSince = sinceDate.subtract(subtractAmount, subtractUnit);
|
|
1458
|
-
const previousUntil = previousSince.add(duration, 'day');
|
|
1459
|
-
return {
|
|
1460
|
-
since: previousSince.valueOf(),
|
|
1461
|
-
until: previousUntil.valueOf(),
|
|
1462
|
-
};
|
|
1294
|
+
return (jsx(MetricChartProvider, { children: jsx(LineChart, { data: lineChartData, yAxisOptions: yAxisOptions, theme: "Light", tooltipOptions: {
|
|
1295
|
+
titleFormatter: () => `${ANALYTICS_METRIC_TOOLTIP[metricKey]?.title ?? ''}`,
|
|
1296
|
+
keyFormatter: (value) => {
|
|
1297
|
+
return value;
|
|
1298
|
+
},
|
|
1299
|
+
renderTooltipContent(data) {
|
|
1300
|
+
return jsx(MetricChartTooltip, { data: data, formatValue: formatValue });
|
|
1301
|
+
},
|
|
1302
|
+
}, showLegend: true }) }));
|
|
1463
1303
|
};
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
const
|
|
1468
|
-
|
|
1469
|
-
return {
|
|
1470
|
-
since: date.subtract(subtractAmount, 'day').valueOf(),
|
|
1471
|
-
until: date.valueOf(),
|
|
1472
|
-
};
|
|
1304
|
+
|
|
1305
|
+
var IMAGE_ANALYTIC_EMPTY = "data:image/png;base64,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";
|
|
1306
|
+
|
|
1307
|
+
const MetricChartEmpty = ({ boxProps, minHeight, description, title }) => {
|
|
1308
|
+
return (jsx(Box, { minWidth: "100%", ...boxProps, children: jsx(GBlockCenter, { minHeight: minHeight, children: jsx(Box, { padding: '400', children: jsxs(BlockStack, { gap: "400", align: "center", inlineAlign: "center", children: [jsx("div", { className: "h-[80px] w-[80px]", children: jsx(GThumbnail, { source: IMAGE_ANALYTIC_EMPTY, width: "80px", height: "80px", alt: title, classRemoved: true }) }), jsxs(BlockStack, { gap: "200", align: "center", inlineAlign: "center", children: [jsx(Text, { as: "h4", variant: "headingSm", fontWeight: "semibold", children: title }), jsx(Text, { as: "h4", variant: "bodyMd", tone: "subdued", children: description })] })] }) }) }) }));
|
|
1473
1309
|
};
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
until: currentDate.valueOf(),
|
|
1478
|
-
};
|
|
1310
|
+
|
|
1311
|
+
const DownIcon8px = () => {
|
|
1312
|
+
return (jsxs("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("g", { clipPath: "url(#clip0_18114_1160)", children: jsx("path", { d: "M1 1L6.5 6.5M6.5 6.5V1.5M6.5 6.5H1.5", stroke: "#8A8A8A", strokeWidth: "1.5" }) }), jsx("defs", { children: jsx("clipPath", { id: "clip0_18114_1160", children: jsx("rect", { width: "8", height: "8", fill: "white" }) }) })] }));
|
|
1479
1313
|
};
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
until: date.subtract(1, 'day').valueOf(),
|
|
1484
|
-
};
|
|
1314
|
+
|
|
1315
|
+
const UpIcon8px = () => {
|
|
1316
|
+
return (jsxs("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("g", { clipPath: "url(#clip0_18114_1146)", children: jsx("path", { d: "M1 7L6.5 1.5M6.5 1.5H1.5M6.5 1.5V6.5", stroke: "#29845A", strokeWidth: "1.5" }) }), jsx("defs", { children: jsx("clipPath", { id: "clip0_18114_1146", children: jsx("rect", { width: "8", height: "8", fill: "white", transform: "matrix(0 -1 1 0 0 8)" }) }) })] }));
|
|
1485
1317
|
};
|
|
1486
|
-
|
|
1487
|
-
const
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
function getLastMonth(date) {
|
|
1491
|
-
return {
|
|
1492
|
-
since: date.subtract(1, 'month').startOf('month').valueOf(),
|
|
1493
|
-
until: date.subtract(1, 'month').endOf('month').valueOf(),
|
|
1494
|
-
};
|
|
1495
|
-
}
|
|
1496
|
-
function getLast12Months(date) {
|
|
1497
|
-
return {
|
|
1498
|
-
since: date.subtract(12, 'month').startOf('month').valueOf(),
|
|
1499
|
-
until: date.subtract(1, 'month').endOf('month').valueOf(),
|
|
1500
|
-
};
|
|
1501
|
-
}
|
|
1502
|
-
function getLastYear(date) {
|
|
1503
|
-
return {
|
|
1504
|
-
since: date.subtract(1, 'year').startOf('year').valueOf(),
|
|
1505
|
-
until: date.subtract(1, 'year').endOf('year').valueOf(),
|
|
1506
|
-
};
|
|
1507
|
-
}
|
|
1508
|
-
const getMonthAndYearByDateFilter = (month, year, date) => {
|
|
1509
|
-
const endDate = dayjs(date);
|
|
1510
|
-
const endMonthFilter = endDate.month();
|
|
1511
|
-
const endYearFilter = endDate.year();
|
|
1512
|
-
if (endYearFilter !== year || endMonthFilter !== month) {
|
|
1513
|
-
const prev = endDate.subtract(1, 'month');
|
|
1514
|
-
return {
|
|
1515
|
-
month: prev.month(),
|
|
1516
|
-
year: prev.year(),
|
|
1517
|
-
};
|
|
1318
|
+
|
|
1319
|
+
const MetricPercentage = ({ change }) => {
|
|
1320
|
+
if (typeof change !== 'number') {
|
|
1321
|
+
return jsx("div", { style: { height: '2px', width: '11px', backgroundColor: '#8A8A8A' } });
|
|
1518
1322
|
}
|
|
1519
|
-
return {
|
|
1323
|
+
return (jsxs("div", { style: {
|
|
1324
|
+
display: 'flex',
|
|
1325
|
+
maxHeight: '20px',
|
|
1326
|
+
width: 'fit-content',
|
|
1327
|
+
alignItems: 'center',
|
|
1328
|
+
gap: '4px',
|
|
1329
|
+
borderRadius: '8px',
|
|
1330
|
+
fontSize: '12px',
|
|
1331
|
+
color: change > 0 ? TREND_TONE.POSITIVE : TREND_TONE.NEUTRAL,
|
|
1332
|
+
}, children: [change < 0 && (jsx(InlineStack, { align: "center", children: jsx(DownIcon8px, {}) })), change > 0 && (jsx(InlineStack, { align: "center", children: jsx(UpIcon8px, {}) })), jsx(Text, { as: "span", variant: "bodyXs", fontWeight: "semibold", children: formatPercentage(Math.abs(change || 0)) })] }));
|
|
1520
1333
|
};
|
|
1521
1334
|
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1335
|
+
const MetricChartTooltip = ({ data, formatValue }) => {
|
|
1336
|
+
const { activeIndex } = data;
|
|
1337
|
+
const currentData = data?.dataSeries[0]?.data[activeIndex];
|
|
1338
|
+
const previousData = data?.dataSeries[1]?.data[activeIndex];
|
|
1339
|
+
const formatPercent = () => {
|
|
1340
|
+
const value = currentData.trend?.value;
|
|
1341
|
+
if (!value)
|
|
1342
|
+
return PLACEHOLDER_VALUE;
|
|
1343
|
+
const valueNumber = Number(value.replace(/[%~]/g, ''));
|
|
1344
|
+
if (currentData.trend?.trend === 'negative') {
|
|
1345
|
+
return valueNumber * -1;
|
|
1346
|
+
}
|
|
1347
|
+
return valueNumber;
|
|
1348
|
+
};
|
|
1349
|
+
return (jsx("div", { className: "w-fit min-w-[175px]", children: jsx(Card, { padding: '200', children: jsxs(BlockStack, { gap: '100', children: [jsx(Text, { as: "p", variant: "bodySm", fontWeight: "semibold", children: data.formatters?.titleFormatter?.(data.title || '') || data.title }), jsxs(BlockStack, { gap: '100', children: [jsxs(InlineStack, { gap: '400', align: "space-between", blockAlign: "center", children: [jsxs(InlineStack, { gap: '100', blockAlign: "center", children: [jsx("div", { className: "h-[2px] w-[12px] rounded-[10px] bg-[#4FA9EA]" }), jsx(Text, { as: "p", variant: "bodySm", fontWeight: "medium", tone: "subdued", children: currentData.tooltipKey })] }), jsxs(InlineStack, { blockAlign: "center", gap: "100", children: [jsx(Text, { as: "span", variant: "bodySm", fontWeight: "semibold", children: formatValue(currentData.value) }), jsx(MetricPercentage, { change: formatPercent() })] })] }), jsxs(InlineStack, { gap: '400', align: "space-between", blockAlign: "center", children: [jsxs(InlineStack, { gap: '100', blockAlign: "center", children: [jsx("div", { className: "w-[12px] border border-dashed border-[#A1CAE7]" }), jsx(Text, { as: "p", variant: "bodySm", tone: "subdued", fontWeight: "medium", children: previousData.tooltipKey })] }), jsxs(InlineStack, { blockAlign: "center", gap: "100", children: [jsx(Text, { as: "span", variant: "bodySm", fontWeight: "semibold", children: formatValue(previousData.value) }), jsx("div", { className: "opacity-0", children: jsx(MetricPercentage, { change: formatPercent() }) })] })] })] })] }) }) }));
|
|
1536
1350
|
};
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
},
|
|
1544
|
-
PREVIOUS_PERIOD_FILTER,
|
|
1545
|
-
{
|
|
1546
|
-
title: 'Previous week',
|
|
1547
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_WEEK,
|
|
1548
|
-
since: 0,
|
|
1549
|
-
until: 0,
|
|
1550
|
-
},
|
|
1551
|
-
{
|
|
1552
|
-
title: 'Previous quarter',
|
|
1553
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_QUARTER,
|
|
1554
|
-
since: 0,
|
|
1555
|
-
until: 0,
|
|
1556
|
-
},
|
|
1557
|
-
{
|
|
1558
|
-
title: 'Previous month',
|
|
1559
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_MONTH,
|
|
1560
|
-
since: 0,
|
|
1561
|
-
until: 0,
|
|
1562
|
-
},
|
|
1563
|
-
{
|
|
1564
|
-
title: 'Previous year',
|
|
1565
|
-
alias: CompareDateTimePickerAlias.PREVIOUS_YEAR,
|
|
1566
|
-
since: 0,
|
|
1567
|
-
until: 0,
|
|
1568
|
-
},
|
|
1569
|
-
];
|
|
1570
|
-
const COMPARE_DATE_TIME_FILTERS_MAP = {
|
|
1571
|
-
[CompareDateTimePickerAlias.NO_COMPARISON]: getNoComparison,
|
|
1572
|
-
[CompareDateTimePickerAlias.PREVIOUS_PERIOD]: getPreviousPeriod,
|
|
1573
|
-
[CompareDateTimePickerAlias.PREVIOUS_WEEK]: getPreviousWeek,
|
|
1574
|
-
[CompareDateTimePickerAlias.PREVIOUS_QUARTER]: getPreviousQuarter,
|
|
1575
|
-
[CompareDateTimePickerAlias.PREVIOUS_MONTH]: getPreviousMonth,
|
|
1576
|
-
[CompareDateTimePickerAlias.PREVIOUS_YEAR]: getPreviousYear,
|
|
1351
|
+
|
|
1352
|
+
const MetricInfoSkeleton = ({ isShowOneLine }) => {
|
|
1353
|
+
if (isShowOneLine) {
|
|
1354
|
+
return (jsx(Box, { width: "40%", children: jsx(SkeletonBodyText, { lines: 1 }) }));
|
|
1355
|
+
}
|
|
1356
|
+
return (jsxs(BlockStack, { gap: "200", children: [jsx(Box, { width: "60%", children: jsx(SkeletonBodyText, { lines: 1 }) }), jsx(Box, { width: "40%", children: jsx(SkeletonBodyText, { lines: 1 }) })] }));
|
|
1577
1357
|
};
|
|
1578
1358
|
|
|
1579
|
-
const
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
};
|
|
1587
|
-
const
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
const
|
|
1598
|
-
const
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
const
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1359
|
+
const MetricDonutChartSkeleton = () => {
|
|
1360
|
+
return (jsx(Card, { children: jsxs(BlockStack, { gap: "400", children: [jsx(MetricInfoSkeleton, { isShowOneLine: true }), jsx(GChartSkeleton, {})] }) }));
|
|
1361
|
+
};
|
|
1362
|
+
|
|
1363
|
+
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 })] }) }));
|
|
1364
|
+
|
|
1365
|
+
const MetricInfoBlock = ({ item, isHovered, isLoading, hideComparison, titleVariant = 'headingMd', titleFontWeight, onClickTitle, }) => {
|
|
1366
|
+
const { key, title, totalValue } = item;
|
|
1367
|
+
const tooltip = ANALYTICS_METRIC_TOOLTIP[key];
|
|
1368
|
+
if (isLoading)
|
|
1369
|
+
return jsx(MetricInfoSkeleton, {});
|
|
1370
|
+
return (jsxs(BlockStack, { gap: "200", children: [jsx("div", { className: "hover:cursor-pointer hover:text-[--p-color-text-link-hover]", onClick: (e) => {
|
|
1371
|
+
e?.stopPropagation();
|
|
1372
|
+
onClickTitle?.(key);
|
|
1373
|
+
}, 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 })] }));
|
|
1374
|
+
};
|
|
1375
|
+
|
|
1376
|
+
const MetricChartTab = ({ item, isActive, isLoading, hideComparison, onSelect, onClickTitle, }) => {
|
|
1377
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
1378
|
+
const isHighlighted = isActive || isHovered;
|
|
1379
|
+
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 }) }) }));
|
|
1380
|
+
};
|
|
1381
|
+
|
|
1382
|
+
const GSelectableMetricChartCard = ({ metricInfo, dataChart, defaultActiveTab, isLoading, isEmptyMetricData, hideComparison, currentPeriodLabel = DEFAULT_CURRENT_PERIOD_LABEL, previousPeriodLabel = DEFAULT_PREVIOUS_PERIOD_LABEL, columnTypes, }) => {
|
|
1383
|
+
const [activeTab, setActiveTab] = useState(defaultActiveTab);
|
|
1384
|
+
const lineChartData = useMemo(() => {
|
|
1385
|
+
const chartData = activeTab ? dataChart[activeTab] : undefined;
|
|
1386
|
+
if (!chartData)
|
|
1387
|
+
return [];
|
|
1388
|
+
const currentSeries = { name: currentPeriodLabel, data: chartData.current };
|
|
1389
|
+
if (hideComparison)
|
|
1390
|
+
return [currentSeries];
|
|
1391
|
+
return [currentSeries, { name: previousPeriodLabel, data: chartData.previous, isComparison: true }];
|
|
1392
|
+
}, [activeTab, dataChart, hideComparison, currentPeriodLabel, previousPeriodLabel]);
|
|
1393
|
+
return (jsxs(Card, { children: [jsx("div", { style: {
|
|
1394
|
+
display: 'grid',
|
|
1395
|
+
gridTemplateColumns: `repeat(${metricInfo.length}, 1fr)`,
|
|
1396
|
+
gap: '16px',
|
|
1397
|
+
marginBottom: '16px',
|
|
1398
|
+
}, 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 })] }));
|
|
1399
|
+
};
|
|
1400
|
+
|
|
1401
|
+
const calculatePercentageChange = (current, previous) => {
|
|
1402
|
+
if (current === 0 && previous === 0) {
|
|
1403
|
+
return undefined;
|
|
1404
|
+
}
|
|
1405
|
+
if (previous === 0) {
|
|
1406
|
+
return current > 0 ? '100%' : '0%';
|
|
1407
|
+
}
|
|
1408
|
+
const change = ((current - previous) / previous) * 100;
|
|
1409
|
+
return `${Math.abs(change).toFixed(0)}%`;
|
|
1410
|
+
};
|
|
1411
|
+
const computeDonutData = ({ name, currentValue, prevValue, hasPreviousData, }) => ({
|
|
1412
|
+
name,
|
|
1413
|
+
data: [{ key: 'value', value: currentValue }],
|
|
1414
|
+
metadata: {
|
|
1415
|
+
trend: {
|
|
1416
|
+
value: hasPreviousData ? calculatePercentageChange(currentValue, prevValue) : undefined,
|
|
1417
|
+
direction: currentValue >= prevValue ? 'upward' : 'downward',
|
|
1418
|
+
trend: currentValue >= prevValue ? 'positive' : 'negative',
|
|
1419
|
+
},
|
|
1420
|
+
},
|
|
1421
|
+
});
|
|
1422
|
+
const getTotalCountByType = (stats, type) => {
|
|
1423
|
+
const item = stats?.find((stat) => stat?.type?.toLowerCase() === type.toLowerCase());
|
|
1424
|
+
return item?.total ?? 0;
|
|
1425
|
+
};
|
|
1426
|
+
const buildBreakdownDonutData = ({ targets, metricKey, totalsRow, comparisonTotalsRow, sort, }) => {
|
|
1427
|
+
const items = parseBreakdownItems(totalsRow?.[metricKey]);
|
|
1428
|
+
const comparisonItems = parseBreakdownItems(comparisonTotalsRow?.[metricKey]);
|
|
1429
|
+
const hasPreviousData = !!comparisonTotalsRow?.[metricKey];
|
|
1430
|
+
const result = targets.map(({ value, label }) => computeDonutData({
|
|
1431
|
+
name: label,
|
|
1432
|
+
currentValue: getTotalCountByType(items, value),
|
|
1433
|
+
prevValue: getTotalCountByType(comparisonItems, value),
|
|
1434
|
+
hasPreviousData,
|
|
1435
|
+
}));
|
|
1436
|
+
const getValue = (item) => item.data[0]?.value ?? 0;
|
|
1437
|
+
return sort ? [...result].sort((a, b) => getValue(b) - getValue(a)) : result;
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
const DONUT_CHART_MIN_HEIGHT = 294;
|
|
1441
|
+
const COMPACT_MAX_WIDTH = 1500;
|
|
1442
|
+
const MetricDonutChartCard = ({ label, metricKey, targets, totalsRow, comparisonTotalsRow, sort, isLoading, isEmptyMetricData, minHeight = DONUT_CHART_MIN_HEIGHT, onClick, }) => {
|
|
1443
|
+
const tooltip = ANALYTICS_METRIC_TOOLTIP[metricKey];
|
|
1444
|
+
const { windowWidth, windowSize } = useWindowSize();
|
|
1445
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
1446
|
+
const data = useMemo(() => buildBreakdownDonutData({ targets, metricKey, totalsRow, comparisonTotalsRow, sort }), [targets, metricKey, totalsRow, comparisonTotalsRow, sort]);
|
|
1447
|
+
if (isLoading) {
|
|
1448
|
+
return jsx(MetricDonutChartSkeleton, {});
|
|
1449
|
+
}
|
|
1450
|
+
const formatValue = (value) => {
|
|
1451
|
+
return numberWithCommas(`${value}`);
|
|
1611
1452
|
};
|
|
1612
|
-
const
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
...LAST_MONTH_CONFIG.getDateRange(currentDate),
|
|
1453
|
+
const handleClickTitle = (event) => {
|
|
1454
|
+
event.stopPropagation();
|
|
1455
|
+
onClick();
|
|
1616
1456
|
};
|
|
1617
|
-
const
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1457
|
+
const isCompactView = windowWidth.lg && windowSize.width < COMPACT_MAX_WIDTH;
|
|
1458
|
+
return (jsx("div", { onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: jsx(Card, { children: jsxs(BlockStack, { gap: "200", children: [jsx(InlineStack, { children: jsx("div", { className: "hover:cursor-pointer hover:text-[--p-color-text-link-hover]", onClick: handleClickTitle, children: jsxs(InlineStack, { children: [jsx(GTooltipCard, { tooltip: tooltip, children: jsx(Text, { as: "h3", variant: "headingMd", children: label }) }), isHovered && jsx(Icon, { source: SvgChevronRightIcon, tone: "inherit" })] }) }) }), jsx("div", { className: cls('flex items-center justify-center', {
|
|
1459
|
+
'max-h-[250px] overflow-hidden': isCompactView,
|
|
1460
|
+
}), children: isEmptyMetricData ? (jsx(MetricChartEmpty, { title: "No data yet", description: "Data needs time to gather" })) : (jsx(MetricChartProvider, { minHeight: minHeight, seriesColors: {}, children: jsx(DonutChart, { data: data, legendPosition: "left", showLegendValues: true, showLegend: true, theme: "Light", tooltipOptions: {
|
|
1461
|
+
valueFormatter: formatValue,
|
|
1462
|
+
}, labelFormatter: formatValue }) })) })] }) }) }));
|
|
1463
|
+
};
|
|
1464
|
+
|
|
1465
|
+
const SingleMetricChartCard = ({ metricInfo, lineChartData, isLoading, hideComparison, columnTypes, isEmptyMetricData, onClickTitle, }) => {
|
|
1466
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
1467
|
+
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 })] }) }) }));
|
|
1468
|
+
};
|
|
1469
|
+
|
|
1470
|
+
var IMAGE_FIRST_SESSION = "data:image/png;base64,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";
|
|
1471
|
+
|
|
1472
|
+
var IMAGE_ALL_SESSION = "data:image/png;base64,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";
|
|
1473
|
+
|
|
1474
|
+
var EAnalyticMode;
|
|
1475
|
+
(function (EAnalyticMode) {
|
|
1476
|
+
EAnalyticMode["ALL_SESSION"] = "ALL_SESSION";
|
|
1477
|
+
EAnalyticMode["FIRST_SESSION"] = "FIRST_SESSION";
|
|
1478
|
+
EAnalyticMode["PAGE_ONLY"] = "PAGE_ONLY";
|
|
1479
|
+
})(EAnalyticMode || (EAnalyticMode = {}));
|
|
1480
|
+
|
|
1481
|
+
const VIEW_BY_OPTIONS = [
|
|
1482
|
+
{
|
|
1483
|
+
id: EAnalyticMode.ALL_SESSION,
|
|
1484
|
+
content: 'All sessions',
|
|
1485
|
+
helpText: 'Count metrics for all sessions where this page shows up anywhere in the journey: before, during, or after other pages.',
|
|
1486
|
+
icon: IMAGE_ALL_SESSION,
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
id: EAnalyticMode.FIRST_SESSION,
|
|
1490
|
+
content: 'Entry session only',
|
|
1491
|
+
helpText: 'Count metrics for sessions only where this page was the very first page visited, then track how they moved through the funnel.',
|
|
1492
|
+
icon: IMAGE_FIRST_SESSION,
|
|
1493
|
+
},
|
|
1494
|
+
];
|
|
1495
|
+
const AnalyticModeSelector = ({ activatorText = 'View by', value, onChange }) => {
|
|
1496
|
+
const options = useMemo(() => {
|
|
1497
|
+
return VIEW_BY_OPTIONS.map((option) => ({
|
|
1498
|
+
...option,
|
|
1499
|
+
}));
|
|
1500
|
+
}, []);
|
|
1501
|
+
const onSelectMode = (value) => {
|
|
1502
|
+
onChange(value);
|
|
1621
1503
|
};
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1504
|
+
return (jsx(GViewBySelector, { activatorText: activatorText, options: options, selected: value, onSelect: onSelectMode, maxWidth: "650px" }));
|
|
1505
|
+
};
|
|
1506
|
+
|
|
1507
|
+
const EXCHANGE_RATE_HELP_URL = 'https://help.shopify.com/en/manual/international/pricing/exchange-rates#auto-convert';
|
|
1508
|
+
const CurrencySelector = ({ currencies, selected, preferredAlignment = 'left', activatorText, onSelect, }) => {
|
|
1509
|
+
const { t } = useTranslation();
|
|
1510
|
+
const onSelectRef = useRef(onSelect);
|
|
1511
|
+
const handleSelection = useCallback((value) => {
|
|
1512
|
+
onSelectRef.current?.(value);
|
|
1513
|
+
}, []);
|
|
1514
|
+
const actionItems = useMemo(() => {
|
|
1515
|
+
if (!currencies)
|
|
1516
|
+
return [];
|
|
1517
|
+
const formattedCurrencies = currencies.map((currency) => ({
|
|
1518
|
+
content: currency,
|
|
1519
|
+
id: currency,
|
|
1520
|
+
}));
|
|
1521
|
+
const hasCurrencyDefault = formattedCurrencies.some((item) => item.id === DEFAULT_CURRENCY_ANALYTIC);
|
|
1522
|
+
if (!hasCurrencyDefault) {
|
|
1523
|
+
formattedCurrencies.push({
|
|
1524
|
+
content: DEFAULT_CURRENCY_ANALYTIC,
|
|
1525
|
+
id: DEFAULT_CURRENCY_ANALYTIC,
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
return sortByConditions(formattedCurrencies, [
|
|
1529
|
+
{ attr: 'content', order: 'asc', preferredValue: DEFAULT_CURRENCY_ANALYTIC },
|
|
1530
|
+
]);
|
|
1531
|
+
}, [currencies]);
|
|
1532
|
+
const actionListItems = useMemo(() => {
|
|
1533
|
+
return actionItems.map((option) => ({
|
|
1534
|
+
id: option.id,
|
|
1535
|
+
content: option.content,
|
|
1536
|
+
onAction: () => handleSelection(option.id),
|
|
1537
|
+
active: option.id === selected,
|
|
1538
|
+
suffix: option.id === selected && jsx(Icon, { source: SvgCheckIcon, tone: "success" }),
|
|
1539
|
+
helpText: option.id === DEFAULT_CURRENCY_ANALYTIC && (jsx(Text, { as: "p", fontWeight: "semibold", children: t('Default') })),
|
|
1540
|
+
}));
|
|
1541
|
+
}, [actionItems, selected, handleSelection, t]);
|
|
1542
|
+
const isHidden = useMemo(() => {
|
|
1543
|
+
if (!actionItems?.length)
|
|
1544
|
+
return true;
|
|
1545
|
+
return actionItems.length === 1 && actionItems[0]?.id === DEFAULT_CURRENCY_ANALYTIC;
|
|
1546
|
+
}, [actionItems]);
|
|
1547
|
+
useEffect(() => {
|
|
1548
|
+
onSelectRef.current = onSelect;
|
|
1549
|
+
});
|
|
1550
|
+
if (isHidden)
|
|
1551
|
+
return null;
|
|
1552
|
+
return (jsx(GSelector, { options: actionListItems, selected: selected, variant: "action-list",
|
|
1553
|
+
// value originates from our CurrencyCode option ids, so the widen-to-string round trip is safe
|
|
1554
|
+
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: {
|
|
1555
|
+
1: (text) => (jsx(GTextLink, { linkAction: {
|
|
1556
|
+
url: EXCHANGE_RATE_HELP_URL,
|
|
1557
|
+
target: '_blank',
|
|
1558
|
+
}, children: text }, text + 'text-link')),
|
|
1559
|
+
}, children: t("This will follow Shopify's current exchange rate. [1]Read more[]") }) }) }));
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1562
|
+
var MainDateTimePickerAlias;
|
|
1563
|
+
(function (MainDateTimePickerAlias) {
|
|
1564
|
+
MainDateTimePickerAlias["TODAY"] = "today";
|
|
1565
|
+
MainDateTimePickerAlias["YESTERDAY"] = "yesterday";
|
|
1566
|
+
MainDateTimePickerAlias["LAST_7_DAYS"] = "last7days";
|
|
1567
|
+
MainDateTimePickerAlias["LAST_30_DAYS"] = "last30days";
|
|
1568
|
+
MainDateTimePickerAlias["LAST_90_DAYS"] = "last90days";
|
|
1569
|
+
MainDateTimePickerAlias["LAST_365_DAYS"] = "last365days";
|
|
1570
|
+
MainDateTimePickerAlias["LAST_MONTH"] = "lastMonth";
|
|
1571
|
+
MainDateTimePickerAlias["LAST_12_MONTHS"] = "last12Months";
|
|
1572
|
+
MainDateTimePickerAlias["LAST_YEAR"] = "lastYear";
|
|
1573
|
+
})(MainDateTimePickerAlias || (MainDateTimePickerAlias = {}));
|
|
1574
|
+
function getDateTimeFilterMapping() {
|
|
1575
|
+
const mappings = {
|
|
1576
|
+
[MainDateTimePickerAlias.TODAY]: {
|
|
1577
|
+
title: 'Today',
|
|
1578
|
+
alias: MainDateTimePickerAlias.TODAY,
|
|
1579
|
+
getDateRange: getToday,
|
|
1580
|
+
},
|
|
1581
|
+
[MainDateTimePickerAlias.YESTERDAY]: {
|
|
1582
|
+
title: 'Yesterday',
|
|
1583
|
+
alias: MainDateTimePickerAlias.YESTERDAY,
|
|
1584
|
+
getDateRange: getYesterday,
|
|
1585
|
+
},
|
|
1586
|
+
[MainDateTimePickerAlias.LAST_7_DAYS]: {
|
|
1587
|
+
title: 'Last 7 days',
|
|
1588
|
+
alias: MainDateTimePickerAlias.LAST_7_DAYS,
|
|
1589
|
+
getDateRange: getLast7Days,
|
|
1590
|
+
},
|
|
1591
|
+
[MainDateTimePickerAlias.LAST_30_DAYS]: {
|
|
1592
|
+
title: 'Last 30 days',
|
|
1593
|
+
alias: MainDateTimePickerAlias.LAST_30_DAYS,
|
|
1594
|
+
getDateRange: getLast30Days,
|
|
1595
|
+
},
|
|
1596
|
+
[MainDateTimePickerAlias.LAST_90_DAYS]: {
|
|
1597
|
+
title: 'Last 90 days',
|
|
1598
|
+
alias: MainDateTimePickerAlias.LAST_90_DAYS,
|
|
1599
|
+
getDateRange: getLast90Days,
|
|
1600
|
+
},
|
|
1601
|
+
[MainDateTimePickerAlias.LAST_365_DAYS]: {
|
|
1602
|
+
title: 'Last 365 days',
|
|
1603
|
+
alias: MainDateTimePickerAlias.LAST_365_DAYS,
|
|
1604
|
+
getDateRange: getLast365Days,
|
|
1605
|
+
},
|
|
1606
|
+
[MainDateTimePickerAlias.LAST_MONTH]: {
|
|
1607
|
+
title: 'Last month',
|
|
1608
|
+
alias: MainDateTimePickerAlias.LAST_MONTH,
|
|
1609
|
+
getDateRange: getLastMonth,
|
|
1610
|
+
},
|
|
1611
|
+
[MainDateTimePickerAlias.LAST_12_MONTHS]: {
|
|
1612
|
+
title: 'Last 12 months',
|
|
1613
|
+
alias: MainDateTimePickerAlias.LAST_12_MONTHS,
|
|
1614
|
+
getDateRange: getLast12Months,
|
|
1615
|
+
},
|
|
1616
|
+
[MainDateTimePickerAlias.LAST_YEAR]: {
|
|
1617
|
+
title: 'Last year',
|
|
1618
|
+
alias: MainDateTimePickerAlias.LAST_YEAR,
|
|
1619
|
+
getDateRange: getLastYear,
|
|
1620
|
+
},
|
|
1626
1621
|
};
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1622
|
+
return mappings;
|
|
1623
|
+
}
|
|
1624
|
+
function getDateTimeFilterByAlias(alias) {
|
|
1625
|
+
const mappings = getDateTimeFilterMapping();
|
|
1626
|
+
return mappings[alias];
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
const DATE_FORMAT = {
|
|
1630
|
+
YMD: 'YYYY-MM-DD', // 2025-01-01
|
|
1631
|
+
MONTH_YEAR: 'MMM YYYY', // Jan 2025
|
|
1632
|
+
FULL: 'MMMM D, YYYY', // January 1, 2025
|
|
1633
|
+
FULL_WITH_TIME: 'MMMM D, YYYY [at] h:mm A', // January 1, 2025 at 12:00 AM
|
|
1634
|
+
SHORT: 'MMM DD, YYYY', // Jan 01, 2025
|
|
1635
|
+
SHORT_NO_PAD: 'MMM D, YYYY', // Jan 1, 2025
|
|
1636
|
+
SHORT_WITH_TIME: 'MMM D, YYYY [at] h:mm A', // Jan 1, 2025 at 12:00 AM
|
|
1637
|
+
MONTH_DAY: 'MMM D', // Jan 1
|
|
1638
|
+
DAY_YEAR: 'D, YYYY', // 1, 2025
|
|
1639
|
+
TIME: 'h:mm A', // 12:00 AM
|
|
1640
|
+
MONTH_DAY_WITH_TIME: 'MMM D [at] h:mm A', // Jan 1 at 12:00 AM
|
|
1641
|
+
YEAR: 'YYYY', // 2025
|
|
1642
|
+
};
|
|
1643
|
+
|
|
1644
|
+
function parseYearMonthDayDateString(input) {
|
|
1645
|
+
// Date-only strings (e.g. "1970-01-01") are treated as UTC, not local time
|
|
1646
|
+
// when using new Date()
|
|
1647
|
+
// We need to split year, month, day to pass into new Date() separately
|
|
1648
|
+
// to get a localized Date
|
|
1649
|
+
return dayjs(input).valueOf();
|
|
1650
|
+
}
|
|
1651
|
+
const VALID_YYYY_MM_DD_DATE_REGEX = /^\d{4}-\d{1,2}-\d{1,2}/;
|
|
1652
|
+
function isDate(date) {
|
|
1653
|
+
return !isNaN(new Date(date).getDate());
|
|
1654
|
+
}
|
|
1655
|
+
function isValidYearMonthDayDateString(date) {
|
|
1656
|
+
return VALID_YYYY_MM_DD_DATE_REGEX.test(date) && isDate(date);
|
|
1657
|
+
}
|
|
1658
|
+
function isValidDate(date) {
|
|
1659
|
+
return date.length === 10 && isValidYearMonthDayDateString(date);
|
|
1660
|
+
}
|
|
1661
|
+
function formatDate(timestamp, type) {
|
|
1662
|
+
const date = convertDateToTz(timestamp);
|
|
1663
|
+
if (type === 'YMD') {
|
|
1664
|
+
return date.format(DATE_FORMAT.YMD);
|
|
1665
|
+
}
|
|
1666
|
+
if (type === 'MY') {
|
|
1667
|
+
return date.format(DATE_FORMAT.MONTH_YEAR);
|
|
1668
|
+
}
|
|
1669
|
+
if (type === 'FULL') {
|
|
1670
|
+
return date.format(DATE_FORMAT.FULL);
|
|
1671
|
+
}
|
|
1672
|
+
if (type === 'FULL_WITH_TIME') {
|
|
1673
|
+
return date.format(DATE_FORMAT.FULL_WITH_TIME);
|
|
1674
|
+
}
|
|
1675
|
+
return date.format(DATE_FORMAT.SHORT);
|
|
1676
|
+
}
|
|
1677
|
+
function formatTime(timestamp) {
|
|
1678
|
+
const date = convertDateToTz(timestamp);
|
|
1679
|
+
return date.format(DATE_FORMAT.TIME);
|
|
1680
|
+
}
|
|
1681
|
+
function isSameDayTimestamp(since, until) {
|
|
1682
|
+
const sinceDate = convertDateToTz(since);
|
|
1683
|
+
const untilDate = convertDateToTz(until);
|
|
1684
|
+
return sinceDate.isSame(untilDate, 'day');
|
|
1685
|
+
}
|
|
1686
|
+
function formatTimeRange(data) {
|
|
1687
|
+
const { since, until, format = DATE_FORMAT.TIME, showNow = false } = data;
|
|
1688
|
+
const sinceDate = convertDateToTz(since);
|
|
1689
|
+
const untilDate = convertDateToTz(until);
|
|
1690
|
+
return `${sinceDate.format(format)} - ${showNow ? 'Now' : untilDate.format(format)}`;
|
|
1691
|
+
}
|
|
1692
|
+
function formatDateTimeRange(data) {
|
|
1693
|
+
const { since, until, isShowNow } = data;
|
|
1694
|
+
const sinceDate = convertDateToTz(since);
|
|
1695
|
+
const untilDate = convertDateToTz(until);
|
|
1696
|
+
const isToday = sinceDate.isSame(dayjsTz(), 'day');
|
|
1697
|
+
const startTime = sinceDate.format(DATE_FORMAT.TIME);
|
|
1698
|
+
const endTime = untilDate.format(DATE_FORMAT.TIME);
|
|
1699
|
+
if (isToday) {
|
|
1700
|
+
const formatEndTime = isShowNow ? 'Now' : endTime;
|
|
1701
|
+
return `Today at ${startTime} - ${formatEndTime}`;
|
|
1702
|
+
}
|
|
1703
|
+
if (isShowNow) {
|
|
1704
|
+
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - Now`;
|
|
1705
|
+
}
|
|
1706
|
+
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1707
|
+
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - ${endTime}`;
|
|
1708
|
+
}
|
|
1709
|
+
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1710
|
+
const time = formatTimeRange({ since, until });
|
|
1711
|
+
return `${sinceDate.format(DATE_FORMAT.SHORT)} (${time})`;
|
|
1712
|
+
}
|
|
1713
|
+
if (sinceDate.isSame(untilDate, 'year')) {
|
|
1714
|
+
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY_WITH_TIME)} - ${untilDate.format(DATE_FORMAT.MONTH_DAY_WITH_TIME)}, ${untilDate.format(DATE_FORMAT.YEAR)}`;
|
|
1715
|
+
}
|
|
1716
|
+
return `${sinceDate.format(DATE_FORMAT.SHORT_WITH_TIME)} - ${untilDate.format(DATE_FORMAT.SHORT_WITH_TIME)}`;
|
|
1717
|
+
}
|
|
1718
|
+
const formatDayjs = (date, isEndDay = false, formatTemplate) => {
|
|
1719
|
+
// const isUTC = date.isUTC?.() ?? false;
|
|
1720
|
+
// if (isUTC) return date.format();
|
|
1721
|
+
if (isEndDay && isMidnight(date)) {
|
|
1722
|
+
return date.endOf('day').format(formatTemplate);
|
|
1723
|
+
}
|
|
1724
|
+
return date.format(formatTemplate);
|
|
1725
|
+
};
|
|
1726
|
+
const getEndOfDayBy = (value, formatTemplate) => {
|
|
1727
|
+
if (!value) {
|
|
1728
|
+
return formatDayjs(dayjsTz().endOf('day'), false, formatTemplate);
|
|
1729
|
+
}
|
|
1730
|
+
return formatDayjs(dayjsTz(value).endOf('day'), false, formatTemplate);
|
|
1731
|
+
};
|
|
1732
|
+
const isMidnight = (date) => {
|
|
1733
|
+
return date.hour() === 0 && date.minute() === 0;
|
|
1734
|
+
};
|
|
1735
|
+
const formatMs = (ms) => {
|
|
1736
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
1737
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
1738
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
1739
|
+
const seconds = totalSeconds % 60;
|
|
1740
|
+
return [hours, minutes, seconds].map((v) => String(v).padStart(2, '0')).join(':');
|
|
1741
|
+
};
|
|
1742
|
+
|
|
1743
|
+
function getDateRangeTitle(since, until) {
|
|
1744
|
+
const sinceDate = convertDateToTz(since);
|
|
1745
|
+
const untilDate = convertDateToTz(until);
|
|
1746
|
+
if (sinceDate.isSame(untilDate, 'day')) {
|
|
1747
|
+
return sinceDate.format(DATE_FORMAT.SHORT);
|
|
1748
|
+
}
|
|
1749
|
+
if (sinceDate.isSame(untilDate, 'month') && sinceDate.isSame(untilDate, 'year')) {
|
|
1750
|
+
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY)} - ${untilDate.format(DATE_FORMAT.DAY_YEAR)}`;
|
|
1751
|
+
}
|
|
1752
|
+
if (sinceDate.isSame(untilDate, 'year')) {
|
|
1753
|
+
return `${sinceDate.format(DATE_FORMAT.MONTH_DAY)} - ${untilDate.format(DATE_FORMAT.SHORT_NO_PAD)}`;
|
|
1754
|
+
}
|
|
1755
|
+
return `${sinceDate.format(DATE_FORMAT.SHORT_NO_PAD)} - ${untilDate.format(DATE_FORMAT.SHORT_NO_PAD)}`;
|
|
1756
|
+
}
|
|
1757
|
+
/**
|
|
1758
|
+
* Resolves a { title, alias } pair from a since/until date range.
|
|
1759
|
+
* Matches against known presets (today, last 7 days, …); falls back to
|
|
1760
|
+
* a formatted custom range with alias "custom".
|
|
1761
|
+
*/
|
|
1762
|
+
function getDateTimeFilterBase(since, until) {
|
|
1763
|
+
const now = dayjsTz();
|
|
1764
|
+
const sinceDate = convertDateToTz(since);
|
|
1765
|
+
const untilDate = convertDateToTz(until);
|
|
1766
|
+
const mappings = getDateTimeFilterMapping();
|
|
1767
|
+
for (const mapping of Object.values(mappings)) {
|
|
1768
|
+
const range = mapping.getDateRange(now);
|
|
1769
|
+
const expectedSince = convertDateToTz(range.since);
|
|
1770
|
+
const expectedUntil = convertDateToTz(range.until);
|
|
1771
|
+
const isSameSince = sinceDate.isSame(expectedSince, 'day');
|
|
1772
|
+
const isSameUntil = untilDate.isSame(expectedUntil, 'day');
|
|
1773
|
+
if (isSameSince && isSameUntil) {
|
|
1774
|
+
return { title: mapping.title, alias: mapping.alias };
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1638
1777
|
return {
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
LAST_30_DAYS_DATE_RANGE,
|
|
1778
|
+
title: getDateRangeTitle(since, until),
|
|
1779
|
+
alias: 'custom',
|
|
1642
1780
|
};
|
|
1781
|
+
}
|
|
1782
|
+
function getVersionDateRangeTitle(data) {
|
|
1783
|
+
const { since, until, isShowNow } = data;
|
|
1784
|
+
const sinceDate = convertDateToTz(since);
|
|
1785
|
+
const isToday = sinceDate.isSame(dayjsTz(), 'day');
|
|
1786
|
+
if (isToday)
|
|
1787
|
+
return getDateTimeFilterByAlias(MainDateTimePickerAlias.TODAY).title;
|
|
1788
|
+
if (isShowNow)
|
|
1789
|
+
return `${sinceDate.format(DATE_FORMAT.SHORT_NO_PAD)} - Now`;
|
|
1790
|
+
return getDateRangeTitle(since, until);
|
|
1791
|
+
}
|
|
1792
|
+
const getVersionDateDescription = ({ since, until, isShowNow }) => {
|
|
1793
|
+
const isSameDay = isSameDayTimestamp(since, until);
|
|
1794
|
+
if (!isSameDay)
|
|
1795
|
+
return undefined;
|
|
1796
|
+
return formatTimeRange({ since, until, showNow: isShowNow });
|
|
1643
1797
|
};
|
|
1644
1798
|
|
|
1645
|
-
const
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
});
|
|
1657
|
-
const
|
|
1658
|
-
const [dateTimePicked, setDateTimePicked] = useState(initDate || {
|
|
1659
|
-
since: dayjsTz().set('hour', 0).valueOf(),
|
|
1660
|
-
until: dayjsTz().set('hour', 0).valueOf(),
|
|
1661
|
-
title: 'Today',
|
|
1662
|
-
alias: 'today',
|
|
1663
|
-
});
|
|
1664
|
-
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
1665
|
-
const getCompareDateTimePicked = useCallback((alias, source = dateTimePicked) => {
|
|
1799
|
+
const convertToDateTimeFilters = (versions) => {
|
|
1800
|
+
const dataVersions = [...versions].sort((a, b) => semverToNum(b.version) - semverToNum(a.version));
|
|
1801
|
+
return dataVersions
|
|
1802
|
+
.map((item) => {
|
|
1803
|
+
if (!item.startedAt)
|
|
1804
|
+
return false;
|
|
1805
|
+
const isCurrentVersion = !item.completedAt;
|
|
1806
|
+
const since = dayjsTzToLocalTZ(item.startedAt).valueOf();
|
|
1807
|
+
const until = isCurrentVersion
|
|
1808
|
+
? dayjsTzToLocalTZ(getEndOfDayBy()).valueOf()
|
|
1809
|
+
: dayjsTzToLocalTZ(item.completedAt).valueOf();
|
|
1810
|
+
const title = getVersionDateRangeTitle({ since, until, isShowNow: isCurrentVersion });
|
|
1811
|
+
const description = getVersionDateDescription({ since, until, isShowNow: isCurrentVersion });
|
|
1666
1812
|
return {
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1813
|
+
title,
|
|
1814
|
+
alias: `${item.version}`,
|
|
1815
|
+
since,
|
|
1816
|
+
until,
|
|
1817
|
+
isVersion: true,
|
|
1818
|
+
isCurrentVersion,
|
|
1819
|
+
description,
|
|
1820
|
+
versionId: item.id,
|
|
1673
1821
|
};
|
|
1674
|
-
}
|
|
1675
|
-
|
|
1676
|
-
const updateCompareDateTimePicked = useCallback((source) => {
|
|
1677
|
-
if (compareDateTimePicked.alias === 'custom' ||
|
|
1678
|
-
compareDateTimePicked.alias === CompareDateTimePickerAlias.NO_COMPARISON)
|
|
1679
|
-
return;
|
|
1680
|
-
setCompareDateTimePicked(getCompareDateTimePicked(compareDateTimePicked.alias, source));
|
|
1681
|
-
}, [compareDateTimePicked, getCompareDateTimePicked]);
|
|
1682
|
-
const resetDateVersion = () => {
|
|
1683
|
-
const since = dayjs(dateTimePicked.since).startOf('day').valueOf();
|
|
1684
|
-
const until = dayjs(dateTimePicked.until).startOf('day').valueOf();
|
|
1685
|
-
const dateFilter = DATE_TIME_FILTERS.find((filter) => filter.since === since && filter.until === until);
|
|
1686
|
-
setDateTimePicked({
|
|
1687
|
-
...dateTimePicked,
|
|
1688
|
-
isVersion: false,
|
|
1689
|
-
versionId: undefined,
|
|
1690
|
-
isCurrentVersion: false,
|
|
1691
|
-
description: '',
|
|
1692
|
-
title: dateFilter?.title || dateTimePicked.title,
|
|
1693
|
-
alias: dateFilter?.alias || 'custom',
|
|
1694
|
-
});
|
|
1695
|
-
};
|
|
1696
|
-
const onSetDateTimePicked = useCallback((value) => {
|
|
1697
|
-
setDateTimePicked(value);
|
|
1698
|
-
updateCompareDateTimePicked(value);
|
|
1699
|
-
}, [updateCompareDateTimePicked]);
|
|
1700
|
-
return (jsx(DateTimePickerContext.Provider, { value: {
|
|
1701
|
-
dateTimePicked,
|
|
1702
|
-
setDateTimePicked: onSetDateTimePicked,
|
|
1703
|
-
compareDateTimePicked,
|
|
1704
|
-
setCompareDateTimePicked,
|
|
1705
|
-
resetDateVersion,
|
|
1706
|
-
}, children: children }));
|
|
1707
|
-
};
|
|
1708
|
-
const useDateTimePickerContext = () => {
|
|
1709
|
-
const context = useContext(DateTimePickerContext);
|
|
1710
|
-
if (!context) {
|
|
1711
|
-
throw new Error('useDateTimePickerContext must be used within a DateTimePickerProvider');
|
|
1712
|
-
}
|
|
1713
|
-
return context;
|
|
1822
|
+
})
|
|
1823
|
+
.filter(Boolean);
|
|
1714
1824
|
};
|
|
1715
1825
|
|
|
1716
|
-
const
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
const [dateRange, setDateRange] = useState(dateTimePicked);
|
|
1721
|
-
const [{ month, year }, setDate] = useState({
|
|
1722
|
-
month: dayjs(dateTimePicked.since).month(),
|
|
1723
|
-
year: dayjs(dateTimePicked.since).year(),
|
|
1724
|
-
});
|
|
1725
|
-
useEffect(() => {
|
|
1726
|
-
if (dateTimePicked) {
|
|
1727
|
-
const untilDate = new Date(dateTimePicked.until);
|
|
1728
|
-
const monthDiff = (referenceDate, newDate) => {
|
|
1729
|
-
return newDate.month - referenceDate.month + 12 * (referenceDate.year - newDate.year);
|
|
1730
|
-
};
|
|
1731
|
-
monthDiff({ year, month }, {
|
|
1732
|
-
year: untilDate.getFullYear(),
|
|
1733
|
-
month: untilDate.getMonth(),
|
|
1734
|
-
});
|
|
1735
|
-
// if (monthDifference > 1 || monthDifference < 0) {
|
|
1736
|
-
// setDate({
|
|
1737
|
-
// month: untilDate.getMonth(),
|
|
1738
|
-
// year: untilDate.getFullYear(),
|
|
1739
|
-
// });
|
|
1740
|
-
// }
|
|
1741
|
-
}
|
|
1742
|
-
}, [dateTimePicked, month, year]);
|
|
1743
|
-
const onMonthChange = (month, year) => {
|
|
1744
|
-
setDate({ month, year });
|
|
1745
|
-
};
|
|
1746
|
-
const onCalendarChange = (value) => {
|
|
1747
|
-
const { start, end, alias } = value;
|
|
1748
|
-
const customDateRange = {
|
|
1749
|
-
alias: 'custom',
|
|
1750
|
-
title: 'Custom',
|
|
1751
|
-
since: start.getTime(),
|
|
1752
|
-
until: end.getTime(),
|
|
1753
|
-
};
|
|
1754
|
-
const newDateRange = allRanges.find((range) => {
|
|
1755
|
-
const isSameAlias = range.alias === alias;
|
|
1756
|
-
const isSameUntil = range.until === end.getTime();
|
|
1757
|
-
const isSameSince = range.since === start.getTime();
|
|
1758
|
-
// const isSameVersionId = !!range.versionId && !!versionId && range.versionId === versionId;
|
|
1759
|
-
const isSameTime = isSameSince && isSameUntil;
|
|
1760
|
-
return isSameAlias || isSameTime;
|
|
1761
|
-
});
|
|
1762
|
-
const finalDateRange = newDateRange || initialPicked || customDateRange;
|
|
1763
|
-
setDateRange(finalDateRange);
|
|
1764
|
-
};
|
|
1765
|
-
const onChange = ({ end }) => {
|
|
1766
|
-
setDate(getMonthAndYearByDateFilter(month, year, end));
|
|
1826
|
+
const getNoComparison = () => {
|
|
1827
|
+
return {
|
|
1828
|
+
since: 0,
|
|
1829
|
+
until: 0,
|
|
1767
1830
|
};
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1831
|
+
};
|
|
1832
|
+
const getPreviousPeriod = (value) => {
|
|
1833
|
+
const { since, until, alias } = value;
|
|
1834
|
+
const sinceDate = dayjs(since);
|
|
1835
|
+
const untilDate = dayjs(until);
|
|
1836
|
+
if (alias === MainDateTimePickerAlias.LAST_MONTH) {
|
|
1837
|
+
return getLastMonth(sinceDate);
|
|
1838
|
+
}
|
|
1839
|
+
if (alias === MainDateTimePickerAlias.LAST_12_MONTHS) {
|
|
1840
|
+
return getLast12Months(sinceDate);
|
|
1841
|
+
}
|
|
1842
|
+
if (alias === MainDateTimePickerAlias.LAST_YEAR) {
|
|
1843
|
+
return getLastYear(sinceDate);
|
|
1844
|
+
}
|
|
1845
|
+
const duration = untilDate.diff(sinceDate, 'day') + 1;
|
|
1846
|
+
const previousSince = sinceDate.subtract(duration, 'day');
|
|
1847
|
+
const previousUntil = untilDate.subtract(duration, 'day');
|
|
1848
|
+
return {
|
|
1849
|
+
since: previousSince.valueOf(),
|
|
1850
|
+
until: previousUntil.valueOf(),
|
|
1771
1851
|
};
|
|
1772
|
-
|
|
1773
|
-
|
|
1852
|
+
};
|
|
1853
|
+
const createPreviousRange = (subtractAmount, subtractUnit) => (value) => {
|
|
1854
|
+
const { since, until } = value;
|
|
1855
|
+
const sinceDate = dayjs(since);
|
|
1856
|
+
const untilDate = dayjs(until);
|
|
1857
|
+
const duration = untilDate.diff(sinceDate, 'day');
|
|
1858
|
+
const previousSince = sinceDate.subtract(subtractAmount, subtractUnit);
|
|
1859
|
+
const previousUntil = previousSince.add(duration, 'day');
|
|
1860
|
+
return {
|
|
1861
|
+
since: previousSince.valueOf(),
|
|
1862
|
+
until: previousUntil.valueOf(),
|
|
1774
1863
|
};
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
});
|
|
1782
|
-
}
|
|
1783
|
-
}, [dateTimePicked]);
|
|
1864
|
+
};
|
|
1865
|
+
const getPreviousWeek = createPreviousRange(7, 'day');
|
|
1866
|
+
const getPreviousQuarter = createPreviousRange(3, 'month');
|
|
1867
|
+
const getPreviousMonth = createPreviousRange(1, 'month');
|
|
1868
|
+
const getPreviousYear = createPreviousRange(1, 'year');
|
|
1869
|
+
const createLastDaysRange = (subtractAmount) => (date) => {
|
|
1784
1870
|
return {
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
onMonthChange,
|
|
1794
|
-
onCalendarChange,
|
|
1871
|
+
since: date.subtract(subtractAmount, 'day').valueOf(),
|
|
1872
|
+
until: date.valueOf(),
|
|
1873
|
+
};
|
|
1874
|
+
};
|
|
1875
|
+
const getToday = (currentDate) => {
|
|
1876
|
+
return {
|
|
1877
|
+
since: currentDate.valueOf(),
|
|
1878
|
+
until: currentDate.valueOf(),
|
|
1795
1879
|
};
|
|
1796
1880
|
};
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
if (!versions?.length)
|
|
1802
|
-
return [];
|
|
1803
|
-
return convertToDateTimeFilters(versions);
|
|
1804
|
-
}, [versions]);
|
|
1805
|
-
const rangeAddition = {
|
|
1806
|
-
title: t('Experiment periods'),
|
|
1807
|
-
rangers,
|
|
1881
|
+
const getYesterday = (date) => {
|
|
1882
|
+
return {
|
|
1883
|
+
since: date.subtract(1, 'day').valueOf(),
|
|
1884
|
+
until: date.subtract(1, 'day').valueOf(),
|
|
1808
1885
|
};
|
|
1809
|
-
return { rangeAddition };
|
|
1810
1886
|
};
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
}
|
|
1820
|
-
useEffect(() => {
|
|
1821
|
-
if (isFocus)
|
|
1822
|
-
return;
|
|
1823
|
-
setInputValues({
|
|
1824
|
-
since: formatDisplayDate(dateRange.since),
|
|
1825
|
-
until: formatDisplayDate(dateRange.until, true),
|
|
1826
|
-
});
|
|
1827
|
-
}, [dateRange, formatDisplayDate]);
|
|
1828
|
-
function handleStartInputValueChange(value) {
|
|
1829
|
-
setInputValues((prevState) => {
|
|
1830
|
-
return { ...prevState, since: value };
|
|
1831
|
-
});
|
|
1832
|
-
if (isValidDate(value)) {
|
|
1833
|
-
const newSinceDate = convertDateToTz(value).startOf('day');
|
|
1834
|
-
const untilDate = convertDateToTz(dateRange.until).endOf('day');
|
|
1835
|
-
const endDate = newSinceDate.isAfter(untilDate) ? newSinceDate.endOf('day') : untilDate;
|
|
1836
|
-
setDateTimePicked({
|
|
1837
|
-
start: dayjsTzToLocalTZ(newSinceDate).toDate(),
|
|
1838
|
-
end: dayjsTzToLocalTZ(endDate).toDate(),
|
|
1839
|
-
});
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
function handleEndInputValueChange(value) {
|
|
1843
|
-
setInputValues((prevState) => ({ ...prevState, until: value }));
|
|
1844
|
-
if (isValidDate(value)) {
|
|
1845
|
-
const nowEndOfDay = dayjsTz().endOf('day');
|
|
1846
|
-
const newUntilDate = convertDateToTz(value).endOf('day');
|
|
1847
|
-
const clampedUntil = newUntilDate.isAfter(nowEndOfDay) ? nowEndOfDay : newUntilDate;
|
|
1848
|
-
const sinceDate = convertDateToTz(dateRange.since).startOf('day');
|
|
1849
|
-
const startDate = clampedUntil.isBefore(sinceDate) ? clampedUntil.startOf('day') : sinceDate;
|
|
1850
|
-
setDateTimePicked({
|
|
1851
|
-
start: dayjsTzToLocalTZ(startDate).toDate(),
|
|
1852
|
-
end: dayjsTzToLocalTZ(clampedUntil).toDate(),
|
|
1853
|
-
});
|
|
1854
|
-
}
|
|
1855
|
-
}
|
|
1856
|
-
function handleInputBlur() {
|
|
1857
|
-
setIsFocus(false);
|
|
1858
|
-
setInputValues({
|
|
1859
|
-
since: formatDisplayDate(dateRange.since),
|
|
1860
|
-
until: formatDisplayDate(dateRange.until, true),
|
|
1861
|
-
});
|
|
1862
|
-
onBlur && onBlur();
|
|
1863
|
-
}
|
|
1864
|
-
function handleFocusStartInput() {
|
|
1865
|
-
setIsFocus(true);
|
|
1866
|
-
setInputValues({
|
|
1867
|
-
...inputValues,
|
|
1868
|
-
since: formatDate(dateRange.since, 'YMD'),
|
|
1869
|
-
});
|
|
1870
|
-
}
|
|
1871
|
-
function handleFocusEndInput() {
|
|
1872
|
-
setIsFocus(true);
|
|
1873
|
-
setInputValues({
|
|
1874
|
-
...inputValues,
|
|
1875
|
-
until: formatDate(dateRange.until, 'YMD'),
|
|
1876
|
-
});
|
|
1877
|
-
}
|
|
1878
|
-
return (jsxs(InlineGrid, { gap: "200", columns: "1fr auto 1fr", children: [jsx(TextField, { role: "combobox", label: 'Since', labelHidden: true,
|
|
1879
|
-
// prefix={<Icon source={CalendarIcon} />}
|
|
1880
|
-
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,
|
|
1881
|
-
// prefix={<Icon source={CalendarIcon} />}
|
|
1882
|
-
value: dateRange.until ? inputValues.until : 'MMMM D, YYYY', onChange: handleEndInputValueChange, onBlur: () => handleInputBlur(), onFocus: () => handleFocusEndInput(), autoComplete: "off" })] }));
|
|
1887
|
+
const getLast7Days = createLastDaysRange(6);
|
|
1888
|
+
const getLast30Days = createLastDaysRange(29);
|
|
1889
|
+
const getLast90Days = createLastDaysRange(89);
|
|
1890
|
+
const getLast365Days = createLastDaysRange(364);
|
|
1891
|
+
function getLastMonth(date) {
|
|
1892
|
+
return {
|
|
1893
|
+
since: date.subtract(1, 'month').startOf('month').valueOf(),
|
|
1894
|
+
until: date.subtract(1, 'month').endOf('month').valueOf(),
|
|
1895
|
+
};
|
|
1883
1896
|
}
|
|
1884
|
-
|
|
1885
|
-
/**
|
|
1886
|
-
* Returns a stateful value, and a set of memoized functions to toggle it,
|
|
1887
|
-
* set it to true and set it to false
|
|
1888
|
-
*/
|
|
1889
|
-
function useToggle(initialState) {
|
|
1890
|
-
const [value, setState] = useState(initialState);
|
|
1897
|
+
function getLast12Months(date) {
|
|
1891
1898
|
return {
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
setTrue: useCallback(() => setState(true), []),
|
|
1895
|
-
setFalse: useCallback(() => setState(false), []),
|
|
1899
|
+
since: date.subtract(12, 'month').startOf('month').valueOf(),
|
|
1900
|
+
until: date.subtract(1, 'month').endOf('month').valueOf(),
|
|
1896
1901
|
};
|
|
1897
1902
|
}
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
const rangesAdditions = rangeAddition?.rangers || [];
|
|
1903
|
-
const handleChangeFilterByOption = (value) => {
|
|
1904
|
-
const alias = value[0];
|
|
1905
|
-
const result = allRanges.find((range) => range.alias === alias) || allRanges[0];
|
|
1906
|
-
setDateTimePicked({
|
|
1907
|
-
start: dayjsTz(result?.since).toDate(),
|
|
1908
|
-
end: dayjsTz(result?.until).toDate(),
|
|
1909
|
-
alias: result?.alias,
|
|
1910
|
-
});
|
|
1903
|
+
function getLastYear(date) {
|
|
1904
|
+
return {
|
|
1905
|
+
since: date.subtract(1, 'year').startOf('year').valueOf(),
|
|
1906
|
+
until: date.subtract(1, 'year').endOf('year').valueOf(),
|
|
1911
1907
|
};
|
|
1912
|
-
|
|
1913
|
-
|
|
1908
|
+
}
|
|
1909
|
+
const getMonthAndYearByDateFilter = (month, year, date) => {
|
|
1910
|
+
const endDate = dayjs(date);
|
|
1911
|
+
const endMonthFilter = endDate.month();
|
|
1912
|
+
const endYearFilter = endDate.year();
|
|
1913
|
+
if (endYearFilter !== year || endMonthFilter !== month) {
|
|
1914
|
+
const prev = endDate.subtract(1, 'month');
|
|
1914
1915
|
return {
|
|
1915
|
-
|
|
1916
|
-
|
|
1916
|
+
month: prev.month(),
|
|
1917
|
+
year: prev.year(),
|
|
1917
1918
|
};
|
|
1918
|
-
}
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
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 }) })] }));
|
|
1922
|
-
}
|
|
1919
|
+
}
|
|
1920
|
+
return { month, year };
|
|
1921
|
+
};
|
|
1923
1922
|
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1923
|
+
var CompareDateTimePickerAlias;
|
|
1924
|
+
(function (CompareDateTimePickerAlias) {
|
|
1925
|
+
CompareDateTimePickerAlias["NO_COMPARISON"] = "noComparison";
|
|
1926
|
+
CompareDateTimePickerAlias["PREVIOUS_PERIOD"] = "previousPeriod";
|
|
1927
|
+
CompareDateTimePickerAlias["PREVIOUS_WEEK"] = "previousWeek";
|
|
1928
|
+
CompareDateTimePickerAlias["PREVIOUS_MONTH"] = "previousMonth";
|
|
1929
|
+
CompareDateTimePickerAlias["PREVIOUS_QUARTER"] = "previousQuarter";
|
|
1930
|
+
CompareDateTimePickerAlias["PREVIOUS_YEAR"] = "previousYear";
|
|
1931
|
+
})(CompareDateTimePickerAlias || (CompareDateTimePickerAlias = {}));
|
|
1932
|
+
const PREVIOUS_PERIOD_FILTER = {
|
|
1933
|
+
title: 'Previous period',
|
|
1934
|
+
alias: CompareDateTimePickerAlias.PREVIOUS_PERIOD,
|
|
1935
|
+
since: 0,
|
|
1936
|
+
until: 0,
|
|
1937
|
+
};
|
|
1938
|
+
const DATE_TIME_COMPARISON_FILTERS = [
|
|
1939
|
+
{
|
|
1940
|
+
title: 'No comparison',
|
|
1941
|
+
alias: CompareDateTimePickerAlias.NO_COMPARISON,
|
|
1942
|
+
since: 0,
|
|
1943
|
+
until: 0,
|
|
1944
|
+
},
|
|
1945
|
+
PREVIOUS_PERIOD_FILTER,
|
|
1946
|
+
{
|
|
1947
|
+
title: 'Previous week',
|
|
1948
|
+
alias: CompareDateTimePickerAlias.PREVIOUS_WEEK,
|
|
1949
|
+
since: 0,
|
|
1950
|
+
until: 0,
|
|
1951
|
+
},
|
|
1952
|
+
{
|
|
1953
|
+
title: 'Previous quarter',
|
|
1954
|
+
alias: CompareDateTimePickerAlias.PREVIOUS_QUARTER,
|
|
1955
|
+
since: 0,
|
|
1956
|
+
until: 0,
|
|
1957
|
+
},
|
|
1958
|
+
{
|
|
1959
|
+
title: 'Previous month',
|
|
1960
|
+
alias: CompareDateTimePickerAlias.PREVIOUS_MONTH,
|
|
1961
|
+
since: 0,
|
|
1962
|
+
until: 0,
|
|
1963
|
+
},
|
|
1964
|
+
{
|
|
1965
|
+
title: 'Previous year',
|
|
1966
|
+
alias: CompareDateTimePickerAlias.PREVIOUS_YEAR,
|
|
1967
|
+
since: 0,
|
|
1968
|
+
until: 0,
|
|
1969
|
+
},
|
|
1970
|
+
];
|
|
1971
|
+
const COMPARE_DATE_TIME_FILTERS_MAP = {
|
|
1972
|
+
[CompareDateTimePickerAlias.NO_COMPARISON]: getNoComparison,
|
|
1973
|
+
[CompareDateTimePickerAlias.PREVIOUS_PERIOD]: getPreviousPeriod,
|
|
1974
|
+
[CompareDateTimePickerAlias.PREVIOUS_WEEK]: getPreviousWeek,
|
|
1975
|
+
[CompareDateTimePickerAlias.PREVIOUS_QUARTER]: getPreviousQuarter,
|
|
1976
|
+
[CompareDateTimePickerAlias.PREVIOUS_MONTH]: getPreviousMonth,
|
|
1977
|
+
[CompareDateTimePickerAlias.PREVIOUS_YEAR]: getPreviousYear,
|
|
1978
|
+
};
|
|
1979
|
+
|
|
1980
|
+
const useDateTimeFilter = () => {
|
|
1981
|
+
const currentDate = dayjsTzToLocalTZ().startOf('day');
|
|
1982
|
+
const mappings = getDateTimeFilterMapping();
|
|
1983
|
+
const TODAY_CONFIG = mappings[MainDateTimePickerAlias.TODAY];
|
|
1984
|
+
const TODAY_DATE_RANGE = {
|
|
1985
|
+
...TODAY_CONFIG,
|
|
1986
|
+
...TODAY_CONFIG.getDateRange(currentDate),
|
|
1936
1987
|
};
|
|
1937
|
-
const
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
end: dayjsTz(result?.until).toDate(),
|
|
1942
|
-
alias: result?.alias,
|
|
1943
|
-
});
|
|
1988
|
+
const YESTERDAY_CONFIG = mappings[MainDateTimePickerAlias.YESTERDAY];
|
|
1989
|
+
const YESTERDAY_DATE_RANGE = {
|
|
1990
|
+
...YESTERDAY_CONFIG,
|
|
1991
|
+
...YESTERDAY_CONFIG.getDateRange(currentDate),
|
|
1944
1992
|
};
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
}
|
|
1950
|
-
|
|
1951
|
-
const useCompareDateTimePicker = ({ ranges, onApply }) => {
|
|
1952
|
-
const allRanges = ranges || DATE_TIME_COMPARISON_FILTERS;
|
|
1953
|
-
const { compareDateTimePicked, setCompareDateTimePicked } = useDateTimePickerContext();
|
|
1954
|
-
const { dateTimePicked: mainDateRange } = useDateTimePickerContext();
|
|
1955
|
-
const [dateRange, setDateRange] = useState(compareDateTimePicked);
|
|
1956
|
-
const [{ month, year }, setDate] = useState({
|
|
1957
|
-
month: dayjsTz(compareDateTimePicked.since).month(),
|
|
1958
|
-
year: dayjsTz(compareDateTimePicked.since).year(),
|
|
1959
|
-
});
|
|
1960
|
-
const onMonthChange = (month, year) => {
|
|
1961
|
-
setDate({ month, year });
|
|
1993
|
+
const LAST_7_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_7_DAYS];
|
|
1994
|
+
const LAST_7_DAYS_DATE_RANGE = {
|
|
1995
|
+
...LAST_7_DAYS_CONFIG,
|
|
1996
|
+
...LAST_7_DAYS_CONFIG.getDateRange(currentDate),
|
|
1962
1997
|
};
|
|
1963
|
-
const
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
// If the alias is not found, set the custom date range
|
|
1968
|
-
if (!newDateRange) {
|
|
1969
|
-
setDateRange({
|
|
1970
|
-
alias: 'custom',
|
|
1971
|
-
title: 'Custom',
|
|
1972
|
-
since: start.getTime(),
|
|
1973
|
-
until: end.getTime(),
|
|
1974
|
-
});
|
|
1975
|
-
return;
|
|
1976
|
-
}
|
|
1977
|
-
setDateRange({
|
|
1978
|
-
...newDateRange,
|
|
1979
|
-
...COMPARE_DATE_TIME_FILTERS_MAP[alias]({
|
|
1980
|
-
since: mainDateRange.since,
|
|
1981
|
-
until: mainDateRange.until,
|
|
1982
|
-
}),
|
|
1983
|
-
});
|
|
1998
|
+
const LAST_30_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_30_DAYS];
|
|
1999
|
+
const LAST_30_DAYS_DATE_RANGE = {
|
|
2000
|
+
...LAST_30_DAYS_CONFIG,
|
|
2001
|
+
...LAST_30_DAYS_CONFIG.getDateRange(currentDate),
|
|
1984
2002
|
};
|
|
1985
|
-
const
|
|
1986
|
-
|
|
1987
|
-
|
|
2003
|
+
const LAST_90_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_90_DAYS];
|
|
2004
|
+
const LAST_90_DAYS_DATE_RANGE = {
|
|
2005
|
+
...LAST_90_DAYS_CONFIG,
|
|
2006
|
+
...LAST_90_DAYS_CONFIG.getDateRange(currentDate),
|
|
1988
2007
|
};
|
|
1989
|
-
const
|
|
1990
|
-
|
|
2008
|
+
const LAST_365_DAYS_CONFIG = mappings[MainDateTimePickerAlias.LAST_365_DAYS];
|
|
2009
|
+
const LAST_365_DAYS_DATE_RANGE = {
|
|
2010
|
+
...LAST_365_DAYS_CONFIG,
|
|
2011
|
+
...LAST_365_DAYS_CONFIG.getDateRange(currentDate),
|
|
1991
2012
|
};
|
|
1992
|
-
const
|
|
1993
|
-
|
|
2013
|
+
const LAST_MONTH_CONFIG = mappings[MainDateTimePickerAlias.LAST_MONTH];
|
|
2014
|
+
const LAST_MONTH_DATE_RANGE = {
|
|
2015
|
+
...LAST_MONTH_CONFIG,
|
|
2016
|
+
...LAST_MONTH_CONFIG.getDateRange(currentDate),
|
|
1994
2017
|
};
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
dateRange,
|
|
2000
|
-
apply,
|
|
2001
|
-
cancel,
|
|
2002
|
-
compareDateTimePicked,
|
|
2003
|
-
onChange,
|
|
2004
|
-
onMonthChange,
|
|
2005
|
-
onCalendarChange,
|
|
2018
|
+
const LAST_12_MONTHS_CONFIG = mappings[MainDateTimePickerAlias.LAST_12_MONTHS];
|
|
2019
|
+
const LAST_12_MONTHS_DATE_RANGE = {
|
|
2020
|
+
...LAST_12_MONTHS_CONFIG,
|
|
2021
|
+
...LAST_12_MONTHS_CONFIG.getDateRange(currentDate),
|
|
2006
2022
|
};
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
const initialPicked = rangeAddition?.initialPicked;
|
|
2012
|
-
const ranges = [...(dateTimeFilters || []), ...(rangeAddition?.rangers || [])];
|
|
2013
|
-
const useHookDateTimePicker = isCompare ? useCompareDateTimePicker : useDateTimePicker;
|
|
2014
|
-
const { month, year, dateRange, apply, cancel, onMonthChange, onCalendarChange, onChange } = useHookDateTimePicker({
|
|
2015
|
-
ranges,
|
|
2016
|
-
initialPicked,
|
|
2017
|
-
onApply: props.onApply,
|
|
2018
|
-
});
|
|
2019
|
-
const { t } = useTranslation();
|
|
2020
|
-
const { mdDown, lgUp } = useBreakpoints();
|
|
2021
|
-
const shouldShowMultiMonth = lgUp;
|
|
2022
|
-
const rawTooltipContent = useMemo(() => {
|
|
2023
|
-
// Only show tooltip when selecting Period (isVersion)
|
|
2024
|
-
if (!dateRange.isVersion || !dateRange.since || !dateRange.until)
|
|
2025
|
-
return;
|
|
2026
|
-
return formatDateTimeRange({
|
|
2027
|
-
since: dateRange.since,
|
|
2028
|
-
until: dateRange.until,
|
|
2029
|
-
isShowNow: dateRange.isCurrentVersion,
|
|
2030
|
-
});
|
|
2031
|
-
}, [dateRange.since, dateRange.until, dateRange.isVersion, dateRange.isCurrentVersion]);
|
|
2032
|
-
const [popoverActive, setPopoverActive] = useState(false);
|
|
2033
|
-
// Freeze tooltip content while popover is open to prevent button remount (focus/CSS loss)
|
|
2034
|
-
const datePickerRef = useRef(null);
|
|
2035
|
-
const tooltipContentRef = useRef(rawTooltipContent);
|
|
2036
|
-
if (!popoverActive)
|
|
2037
|
-
tooltipContentRef.current = rawTooltipContent;
|
|
2038
|
-
const tooltipContent = tooltipContentRef.current;
|
|
2039
|
-
//@ts-ignore
|
|
2040
|
-
function nodeContainsDescendant(rootNode, descendant) {
|
|
2041
|
-
if (rootNode === descendant) {
|
|
2042
|
-
return true;
|
|
2043
|
-
}
|
|
2044
|
-
let parent = descendant.parentNode;
|
|
2045
|
-
while (parent != null) {
|
|
2046
|
-
if (parent === rootNode) {
|
|
2047
|
-
return true;
|
|
2048
|
-
}
|
|
2049
|
-
parent = parent.parentNode;
|
|
2050
|
-
}
|
|
2051
|
-
return false;
|
|
2052
|
-
}
|
|
2053
|
-
//@ts-ignore
|
|
2054
|
-
function isNodeWithinPopover(node) {
|
|
2055
|
-
return datePickerRef?.current ? nodeContainsDescendant(datePickerRef.current, node) : false;
|
|
2056
|
-
}
|
|
2057
|
-
//@ts-ignore
|
|
2058
|
-
function handleInputBlur({ relatedTarget }) {
|
|
2059
|
-
const isRelatedTargetWithinPopover = relatedTarget != null && isNodeWithinPopover(relatedTarget);
|
|
2060
|
-
// If focus moves from the TextField to the Popover
|
|
2061
|
-
// we don't want to close the popover
|
|
2062
|
-
if (isRelatedTargetWithinPopover) {
|
|
2063
|
-
return;
|
|
2064
|
-
}
|
|
2065
|
-
setPopoverActive(false);
|
|
2066
|
-
}
|
|
2067
|
-
function applyFunc() {
|
|
2068
|
-
apply();
|
|
2069
|
-
setPopoverActive(false);
|
|
2070
|
-
}
|
|
2071
|
-
function cancelFunc() {
|
|
2072
|
-
cancel();
|
|
2073
|
-
setPopoverActive(false);
|
|
2074
|
-
}
|
|
2075
|
-
const handleTogglePopover = () => {
|
|
2076
|
-
if (isCompare) {
|
|
2077
|
-
return;
|
|
2078
|
-
}
|
|
2079
|
-
setPopoverActive(!popoverActive);
|
|
2023
|
+
const LAST_YEAR_CONFIG = mappings[MainDateTimePickerAlias.LAST_YEAR];
|
|
2024
|
+
const LAST_YEAR_DATE_RANGE = {
|
|
2025
|
+
...LAST_YEAR_CONFIG,
|
|
2026
|
+
...LAST_YEAR_CONFIG.getDateRange(currentDate),
|
|
2080
2027
|
};
|
|
2081
|
-
const
|
|
2082
|
-
|
|
2083
|
-
|
|
2028
|
+
const DATE_TIME_FILTERS = [
|
|
2029
|
+
TODAY_DATE_RANGE,
|
|
2030
|
+
YESTERDAY_DATE_RANGE,
|
|
2031
|
+
LAST_7_DAYS_DATE_RANGE,
|
|
2032
|
+
LAST_30_DAYS_DATE_RANGE,
|
|
2033
|
+
LAST_90_DAYS_DATE_RANGE,
|
|
2034
|
+
LAST_365_DAYS_DATE_RANGE,
|
|
2035
|
+
LAST_MONTH_DATE_RANGE,
|
|
2036
|
+
LAST_12_MONTHS_DATE_RANGE,
|
|
2037
|
+
LAST_YEAR_DATE_RANGE,
|
|
2038
|
+
];
|
|
2039
|
+
return {
|
|
2040
|
+
DATE_TIME_FILTERS,
|
|
2041
|
+
LAST_7_DAYS_DATE_RANGE,
|
|
2042
|
+
LAST_30_DAYS_DATE_RANGE,
|
|
2084
2043
|
};
|
|
2085
|
-
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: {
|
|
2086
|
-
xs: '1fr',
|
|
2087
|
-
md: 'max-content max-content',
|
|
2088
|
-
}, 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
|
|
2089
|
-
? undefined
|
|
2090
|
-
: {
|
|
2091
|
-
start: dayjs(dateRange.since).toDate(),
|
|
2092
|
-
end: dayjs(dateRange.until).toDate(),
|
|
2093
|
-
}, onMonthChange: onMonthChange, onChange: onCalendarChange, multiMonth: shouldShowMultiMonth, allowRange: true, disableDatesAfter: dayjsTzToDate() }) }), actionProps && (jsx(GButton, { ...actionProps, onClick: () => {
|
|
2094
|
-
setPopoverActive(false);
|
|
2095
|
-
actionProps.onClick?.();
|
|
2096
|
-
} }))] }) })] }) }) }), 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') })] }) }) }) })] }) }));
|
|
2097
|
-
};
|
|
2098
|
-
|
|
2099
|
-
const CompareTimePicker = (props) => {
|
|
2100
|
-
const { rangeAddition, popoverProps } = props;
|
|
2101
|
-
const initialPicked = rangeAddition?.initialPicked;
|
|
2102
|
-
const dateTimeFilters = DATE_TIME_COMPARISON_FILTERS;
|
|
2103
|
-
const ranges = [...dateTimeFilters, ...(rangeAddition?.rangers || [])];
|
|
2104
|
-
const { t } = useTranslation();
|
|
2105
|
-
const { compareDateTimePicked } = useCompareDateTimePicker({ ranges, initialPicked });
|
|
2106
|
-
const buttonValue = useMemo(() => {
|
|
2107
|
-
if (compareDateTimePicked.alias === CompareDateTimePickerAlias.NO_COMPARISON) {
|
|
2108
|
-
return t('No comparison');
|
|
2109
|
-
}
|
|
2110
|
-
return t('Compare to: {{value}}', {
|
|
2111
|
-
value: getDateRangeTitle(compareDateTimePicked.since, compareDateTimePicked.until),
|
|
2112
|
-
});
|
|
2113
|
-
}, [compareDateTimePicked, t]);
|
|
2114
|
-
return (jsx(BaseTimePicker, { dateTimeFilters: dateTimeFilters, rangeAddition: rangeAddition, popoverProps: popoverProps, isCompare: true, buttonValue: buttonValue }));
|
|
2115
2044
|
};
|
|
2116
2045
|
|
|
2117
|
-
const
|
|
2118
|
-
|
|
2046
|
+
const DateTimePickerContext = createContext({
|
|
2047
|
+
dateTimePicked: {
|
|
2048
|
+
since: dayjsTz().valueOf(),
|
|
2049
|
+
until: dayjsTz().valueOf(),
|
|
2050
|
+
title: 'Today',
|
|
2051
|
+
alias: 'today',
|
|
2052
|
+
},
|
|
2053
|
+
compareDateTimePicked: PREVIOUS_PERIOD_FILTER,
|
|
2054
|
+
setDateTimePicked: () => { },
|
|
2055
|
+
setCompareDateTimePicked: () => { },
|
|
2056
|
+
resetDateVersion: () => { },
|
|
2057
|
+
});
|
|
2058
|
+
const DateTimePickerProvider = ({ children, initDate, initDateCompare, }) => {
|
|
2059
|
+
const [dateTimePicked, setDateTimePicked] = useState(initDate || {
|
|
2060
|
+
since: dayjsTz().set('hour', 0).valueOf(),
|
|
2061
|
+
until: dayjsTz().set('hour', 0).valueOf(),
|
|
2062
|
+
title: 'Today',
|
|
2063
|
+
alias: 'today',
|
|
2064
|
+
});
|
|
2119
2065
|
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2120
|
-
const
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
};
|
|
2137
|
-
|
|
2138
|
-
const
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
const activatorContent = useMemo(() => {
|
|
2151
|
-
if (selectedOption) {
|
|
2152
|
-
const content = selectedOption.title ?? selectedOption.content;
|
|
2153
|
-
return activatorText ? `${activatorText}: ${content}` : content;
|
|
2154
|
-
}
|
|
2155
|
-
return activatorText;
|
|
2156
|
-
}, [selectedOption, activatorText]);
|
|
2157
|
-
const handleSelect = (value) => {
|
|
2158
|
-
onSelect(value);
|
|
2159
|
-
setPopoverActive(false);
|
|
2066
|
+
const getCompareDateTimePicked = useCallback((alias, source = dateTimePicked) => {
|
|
2067
|
+
return {
|
|
2068
|
+
...PREVIOUS_PERIOD_FILTER,
|
|
2069
|
+
...COMPARE_DATE_TIME_FILTERS_MAP[alias]({
|
|
2070
|
+
since: source.since,
|
|
2071
|
+
until: source.until,
|
|
2072
|
+
alias: source.alias,
|
|
2073
|
+
}),
|
|
2074
|
+
};
|
|
2075
|
+
}, [dateTimePicked]);
|
|
2076
|
+
const [compareDateTimePicked, setCompareDateTimePicked] = useState(initDateCompare || getCompareDateTimePicked(CompareDateTimePickerAlias.PREVIOUS_PERIOD));
|
|
2077
|
+
const updateCompareDateTimePicked = useCallback((source) => {
|
|
2078
|
+
if (compareDateTimePicked.alias === 'custom' ||
|
|
2079
|
+
compareDateTimePicked.alias === CompareDateTimePickerAlias.NO_COMPARISON)
|
|
2080
|
+
return;
|
|
2081
|
+
setCompareDateTimePicked(getCompareDateTimePicked(compareDateTimePicked.alias, source));
|
|
2082
|
+
}, [compareDateTimePicked, getCompareDateTimePicked]);
|
|
2083
|
+
const resetDateVersion = () => {
|
|
2084
|
+
const since = dayjs(dateTimePicked.since).startOf('day').valueOf();
|
|
2085
|
+
const until = dayjs(dateTimePicked.until).startOf('day').valueOf();
|
|
2086
|
+
const dateFilter = DATE_TIME_FILTERS.find((filter) => filter.since === since && filter.until === until);
|
|
2087
|
+
setDateTimePicked({
|
|
2088
|
+
...dateTimePicked,
|
|
2089
|
+
isVersion: false,
|
|
2090
|
+
versionId: undefined,
|
|
2091
|
+
isCurrentVersion: false,
|
|
2092
|
+
description: '',
|
|
2093
|
+
title: dateFilter?.title || dateTimePicked.title,
|
|
2094
|
+
alias: dateFilter?.alias || 'custom',
|
|
2095
|
+
});
|
|
2160
2096
|
};
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2097
|
+
const onSetDateTimePicked = useCallback((value) => {
|
|
2098
|
+
setDateTimePicked(value);
|
|
2099
|
+
updateCompareDateTimePicked(value);
|
|
2100
|
+
}, [updateCompareDateTimePicked]);
|
|
2101
|
+
return (jsx(DateTimePickerContext.Provider, { value: {
|
|
2102
|
+
dateTimePicked,
|
|
2103
|
+
setDateTimePicked: onSetDateTimePicked,
|
|
2104
|
+
compareDateTimePicked,
|
|
2105
|
+
setCompareDateTimePicked,
|
|
2106
|
+
resetDateVersion,
|
|
2107
|
+
}, children: children }));
|
|
2167
2108
|
};
|
|
2168
|
-
|
|
2169
|
-
const
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
else {
|
|
2175
|
-
window.open(item.inlineAction?.url, item.inlineAction?.target ?? '_blank');
|
|
2176
|
-
}
|
|
2177
|
-
}, children: item.inlineAction?.content }))] }));
|
|
2109
|
+
const useDateTimePickerContext = () => {
|
|
2110
|
+
const context = useContext(DateTimePickerContext);
|
|
2111
|
+
if (!context) {
|
|
2112
|
+
throw new Error('useDateTimePickerContext must be used within a DateTimePickerProvider');
|
|
2113
|
+
}
|
|
2114
|
+
return context;
|
|
2178
2115
|
};
|
|
2179
2116
|
|
|
2180
|
-
const
|
|
2181
|
-
const
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
if (
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
const styleByState = useMemo(() => {
|
|
2195
|
-
if (!isActive) {
|
|
2196
|
-
return {
|
|
2197
|
-
box: { outlineWidth: '025', outlineColor: 'border' },
|
|
2198
|
-
text: { fontWeight: 'regular' },
|
|
2117
|
+
const useDateTimePicker = ({ ranges, initialPicked, onApply }) => {
|
|
2118
|
+
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2119
|
+
const allRanges = ranges || DATE_TIME_FILTERS;
|
|
2120
|
+
const { dateTimePicked, setDateTimePicked } = useDateTimePickerContext();
|
|
2121
|
+
const [dateRange, setDateRange] = useState(dateTimePicked);
|
|
2122
|
+
const [{ month, year }, setDate] = useState({
|
|
2123
|
+
month: dayjs(dateTimePicked.since).month(),
|
|
2124
|
+
year: dayjs(dateTimePicked.since).year(),
|
|
2125
|
+
});
|
|
2126
|
+
useEffect(() => {
|
|
2127
|
+
if (dateTimePicked) {
|
|
2128
|
+
const untilDate = new Date(dateTimePicked.until);
|
|
2129
|
+
const monthDiff = (referenceDate, newDate) => {
|
|
2130
|
+
return newDate.month - referenceDate.month + 12 * (referenceDate.year - newDate.year);
|
|
2199
2131
|
};
|
|
2132
|
+
monthDiff({ year, month }, {
|
|
2133
|
+
year: untilDate.getFullYear(),
|
|
2134
|
+
month: untilDate.getMonth(),
|
|
2135
|
+
});
|
|
2136
|
+
// if (monthDifference > 1 || monthDifference < 0) {
|
|
2137
|
+
// setDate({
|
|
2138
|
+
// month: untilDate.getMonth(),
|
|
2139
|
+
// year: untilDate.getFullYear(),
|
|
2140
|
+
// });
|
|
2141
|
+
// }
|
|
2200
2142
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
box: { outlineWidth: '050', outlineColor: 'border-inverse' },
|
|
2205
|
-
text: { fontWeight: 'semibold' },
|
|
2206
|
-
};
|
|
2207
|
-
}, [activeStyle, isActive]);
|
|
2208
|
-
const checkBoxComponent = () => {
|
|
2209
|
-
return (jsx(Checkbox, { label: jsx(InlineStack, { gap: "100", children: jsx(Text, { truncate: true, as: "p", variant: "bodyMd", fontWeight: styleByState.text.fontWeight, children: item.label }) }), disabled: disabled, checked: isActive, name: item.type, ...(item.description && { helpText: jsx(ChoiceHelpText, { item: item }) }) }));
|
|
2143
|
+
}, [dateTimePicked, month, year]);
|
|
2144
|
+
const onMonthChange = (month, year) => {
|
|
2145
|
+
setDate({ month, year });
|
|
2210
2146
|
};
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2147
|
+
const onCalendarChange = (value) => {
|
|
2148
|
+
const { start, end, alias } = value;
|
|
2149
|
+
const customDateRange = {
|
|
2150
|
+
alias: 'custom',
|
|
2151
|
+
title: 'Custom',
|
|
2152
|
+
since: start.getTime(),
|
|
2153
|
+
until: end.getTime(),
|
|
2154
|
+
};
|
|
2155
|
+
const newDateRange = allRanges.find((range) => {
|
|
2156
|
+
const isSameAlias = range.alias === alias;
|
|
2157
|
+
const isSameUntil = range.until === end.getTime();
|
|
2158
|
+
const isSameSince = range.since === start.getTime();
|
|
2159
|
+
// const isSameVersionId = !!range.versionId && !!versionId && range.versionId === versionId;
|
|
2160
|
+
const isSameTime = isSameSince && isSameUntil;
|
|
2161
|
+
return isSameAlias || isSameTime;
|
|
2162
|
+
});
|
|
2163
|
+
const finalDateRange = newDateRange || initialPicked || customDateRange;
|
|
2164
|
+
setDateRange(finalDateRange);
|
|
2213
2165
|
};
|
|
2214
|
-
const
|
|
2215
|
-
|
|
2166
|
+
const onChange = ({ end }) => {
|
|
2167
|
+
setDate(getMonthAndYearByDateFilter(month, year, end));
|
|
2216
2168
|
};
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
const GChartSkeleton = () => {
|
|
2221
|
-
return jsx(GSkeletonDisplayText, { height: "188px" });
|
|
2222
|
-
};
|
|
2223
|
-
|
|
2224
|
-
const LINE_SERIES_COLORS = {
|
|
2225
|
-
comparison: SERIES_COLORS.comparison,
|
|
2226
|
-
single: SERIES_COLORS.current,
|
|
2227
|
-
all: [...SERIES_COLORS.all],
|
|
2228
|
-
};
|
|
2229
|
-
const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesColors = LINE_SERIES_COLORS, }) => {
|
|
2230
|
-
return (jsx(PolarisVizProvider, { themes: {
|
|
2231
|
-
Light: {
|
|
2232
|
-
chartContainer: {
|
|
2233
|
-
minHeight,
|
|
2234
|
-
},
|
|
2235
|
-
grid: {
|
|
2236
|
-
horizontalOverflow: true,
|
|
2237
|
-
verticalOverflow: true,
|
|
2238
|
-
horizontalMargin: 0,
|
|
2239
|
-
},
|
|
2240
|
-
seriesColors,
|
|
2241
|
-
},
|
|
2242
|
-
}, children: children }));
|
|
2243
|
-
};
|
|
2244
|
-
|
|
2245
|
-
const useFormatLineChartData = ({ metricKey, columnTypes }) => {
|
|
2246
|
-
const { formatData } = useAnalyticData();
|
|
2247
|
-
const formatter = metricKey ? columnTypes?.[metricKey] : undefined;
|
|
2248
|
-
const formatValue = (value) => {
|
|
2249
|
-
return String(formatData({ value, formatter }));
|
|
2169
|
+
const apply = () => {
|
|
2170
|
+
setDateTimePicked(dateRange);
|
|
2171
|
+
onApply?.(dateRange);
|
|
2250
2172
|
};
|
|
2251
|
-
const
|
|
2252
|
-
|
|
2253
|
-
return formatValue(Number(value) || 0);
|
|
2254
|
-
},
|
|
2173
|
+
const cancel = () => {
|
|
2174
|
+
setDateRange(dateTimePicked);
|
|
2255
2175
|
};
|
|
2256
|
-
return { formatValue, yAxisOptions };
|
|
2257
|
-
};
|
|
2258
|
-
|
|
2259
|
-
const useWindowSize = () => {
|
|
2260
|
-
const [windowSize, setWindowSize] = useState(() => ({
|
|
2261
|
-
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
2262
|
-
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
2263
|
-
}));
|
|
2264
|
-
const windowWidth = useMemo(() => {
|
|
2265
|
-
return {
|
|
2266
|
-
xs: windowSize.width <= 768,
|
|
2267
|
-
md: 768 < windowSize.width && windowSize.width <= 1024,
|
|
2268
|
-
lg: windowSize.width > 1024,
|
|
2269
|
-
xsDown: windowSize.width < 768,
|
|
2270
|
-
'1200Down': windowSize.width < 1200,
|
|
2271
|
-
'1040Down': windowSize.width < 1040,
|
|
2272
|
-
};
|
|
2273
|
-
}, [windowSize.width]);
|
|
2274
|
-
const isMobileTabletView = !windowWidth.lg;
|
|
2275
|
-
const isMobileView = windowWidth.xs;
|
|
2276
2176
|
useEffect(() => {
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
};
|
|
2284
|
-
}, []);
|
|
2285
|
-
return { windowSize, windowWidth, isMobileTabletView, isMobileView };
|
|
2286
|
-
};
|
|
2287
|
-
|
|
2288
|
-
const MetricChart = ({ lineChartData, isLoading, isEmptyMetricData, columnTypes, metricKey, }) => {
|
|
2289
|
-
const { formatValue, yAxisOptions } = useFormatLineChartData({ metricKey, columnTypes: columnTypes || {} });
|
|
2290
|
-
if (!metricKey) {
|
|
2291
|
-
return jsx(Fragment, {});
|
|
2292
|
-
}
|
|
2293
|
-
if (isLoading) {
|
|
2294
|
-
return jsx(GChartSkeleton, {});
|
|
2295
|
-
}
|
|
2296
|
-
if (isEmptyMetricData) {
|
|
2297
|
-
return jsx(MetricChartEmpty, { title: "No data yet", description: "Data needs time to gather" });
|
|
2298
|
-
}
|
|
2299
|
-
return (jsx(MetricChartProvider, { children: jsx(LineChart, { data: lineChartData, yAxisOptions: yAxisOptions, theme: "Light", tooltipOptions: {
|
|
2300
|
-
titleFormatter: () => `${ANALYTICS_METRIC_TOOLTIP[metricKey]?.title ?? ''}`,
|
|
2301
|
-
keyFormatter: (value) => {
|
|
2302
|
-
return value;
|
|
2303
|
-
},
|
|
2304
|
-
renderTooltipContent(data) {
|
|
2305
|
-
return jsx(MetricChartTooltip, { data: data, formatValue: formatValue });
|
|
2306
|
-
},
|
|
2307
|
-
}, showLegend: true }) }));
|
|
2308
|
-
};
|
|
2309
|
-
|
|
2310
|
-
var IMAGE_ANALYTIC_EMPTY = "data:image/png;base64,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";
|
|
2311
|
-
|
|
2312
|
-
const MetricChartEmpty = ({ boxProps, minHeight, description, title }) => {
|
|
2313
|
-
return (jsx(Box, { minWidth: "100%", ...boxProps, children: jsx(GBlockCenter, { minHeight: minHeight, children: jsx(Box, { padding: '400', children: jsxs(BlockStack, { gap: "400", align: "center", inlineAlign: "center", children: [jsx("div", { className: "h-[80px] w-[80px]", children: jsx(GThumbnail, { source: IMAGE_ANALYTIC_EMPTY, width: "80px", height: "80px", alt: title, classRemoved: true }) }), jsxs(BlockStack, { gap: "200", align: "center", inlineAlign: "center", children: [jsx(Text, { as: "h4", variant: "headingSm", fontWeight: "semibold", children: title }), jsx(Text, { as: "h4", variant: "bodyMd", tone: "subdued", children: description })] })] }) }) }) }));
|
|
2314
|
-
};
|
|
2315
|
-
|
|
2316
|
-
const DownIcon8px = () => {
|
|
2317
|
-
return (jsxs("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("g", { clipPath: "url(#clip0_18114_1160)", children: jsx("path", { d: "M1 1L6.5 6.5M6.5 6.5V1.5M6.5 6.5H1.5", stroke: "#8A8A8A", strokeWidth: "1.5" }) }), jsx("defs", { children: jsx("clipPath", { id: "clip0_18114_1160", children: jsx("rect", { width: "8", height: "8", fill: "white" }) }) })] }));
|
|
2318
|
-
};
|
|
2319
|
-
|
|
2320
|
-
const UpIcon8px = () => {
|
|
2321
|
-
return (jsxs("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("g", { clipPath: "url(#clip0_18114_1146)", children: jsx("path", { d: "M1 7L6.5 1.5M6.5 1.5H1.5M6.5 1.5V6.5", stroke: "#29845A", strokeWidth: "1.5" }) }), jsx("defs", { children: jsx("clipPath", { id: "clip0_18114_1146", children: jsx("rect", { width: "8", height: "8", fill: "white", transform: "matrix(0 -1 1 0 0 8)" }) }) })] }));
|
|
2322
|
-
};
|
|
2323
|
-
|
|
2324
|
-
const MetricPercentage = ({ change }) => {
|
|
2325
|
-
if (typeof change !== 'number') {
|
|
2326
|
-
return jsx("div", { style: { height: '2px', width: '11px', backgroundColor: '#8A8A8A' } });
|
|
2327
|
-
}
|
|
2328
|
-
return (jsxs("div", { style: {
|
|
2329
|
-
display: 'flex',
|
|
2330
|
-
maxHeight: '20px',
|
|
2331
|
-
width: 'fit-content',
|
|
2332
|
-
alignItems: 'center',
|
|
2333
|
-
gap: '4px',
|
|
2334
|
-
borderRadius: '8px',
|
|
2335
|
-
fontSize: '12px',
|
|
2336
|
-
color: change > 0 ? TREND_TONE.POSITIVE : TREND_TONE.NEUTRAL,
|
|
2337
|
-
}, children: [change < 0 && (jsx(InlineStack, { align: "center", children: jsx(DownIcon8px, {}) })), change > 0 && (jsx(InlineStack, { align: "center", children: jsx(UpIcon8px, {}) })), jsx(Text, { as: "span", variant: "bodyXs", fontWeight: "semibold", children: formatPercentage(Math.abs(change || 0)) })] }));
|
|
2338
|
-
};
|
|
2339
|
-
|
|
2340
|
-
const MetricChartTooltip = ({ data, formatValue }) => {
|
|
2341
|
-
const { activeIndex } = data;
|
|
2342
|
-
const currentData = data?.dataSeries[0]?.data[activeIndex];
|
|
2343
|
-
const previousData = data?.dataSeries[1]?.data[activeIndex];
|
|
2344
|
-
const formatPercent = () => {
|
|
2345
|
-
const value = currentData.trend?.value;
|
|
2346
|
-
if (!value)
|
|
2347
|
-
return PLACEHOLDER_VALUE;
|
|
2348
|
-
const valueNumber = Number(value.replace(/[%~]/g, ''));
|
|
2349
|
-
if (currentData.trend?.trend === 'negative') {
|
|
2350
|
-
return valueNumber * -1;
|
|
2177
|
+
if (dateTimePicked) {
|
|
2178
|
+
setDateRange(dateTimePicked);
|
|
2179
|
+
setDate({
|
|
2180
|
+
month: dayjs(dateTimePicked.since).month(),
|
|
2181
|
+
year: dayjs(dateTimePicked.since).year(),
|
|
2182
|
+
});
|
|
2351
2183
|
}
|
|
2352
|
-
|
|
2184
|
+
}, [dateTimePicked]);
|
|
2185
|
+
return {
|
|
2186
|
+
month,
|
|
2187
|
+
year,
|
|
2188
|
+
setDate,
|
|
2189
|
+
dateRange,
|
|
2190
|
+
apply,
|
|
2191
|
+
cancel,
|
|
2192
|
+
dateTimePicked,
|
|
2193
|
+
onChange,
|
|
2194
|
+
onMonthChange,
|
|
2195
|
+
onCalendarChange,
|
|
2353
2196
|
};
|
|
2354
|
-
return (jsx("div", { className: "w-fit min-w-[175px]", children: jsx(Card, { padding: '200', children: jsxs(BlockStack, { gap: '100', children: [jsx(Text, { as: "p", variant: "bodySm", fontWeight: "semibold", children: data.formatters?.titleFormatter?.(data.title || '') || data.title }), jsxs(BlockStack, { gap: '100', children: [jsxs(InlineStack, { gap: '400', align: "space-between", blockAlign: "center", children: [jsxs(InlineStack, { gap: '100', blockAlign: "center", children: [jsx("div", { className: "h-[2px] w-[12px] rounded-[10px] bg-[#4FA9EA]" }), jsx(Text, { as: "p", variant: "bodySm", fontWeight: "medium", tone: "subdued", children: currentData.tooltipKey })] }), jsxs(InlineStack, { blockAlign: "center", gap: "100", children: [jsx(Text, { as: "span", variant: "bodySm", fontWeight: "semibold", children: formatValue(currentData.value) }), jsx(MetricPercentage, { change: formatPercent() })] })] }), jsxs(InlineStack, { gap: '400', align: "space-between", blockAlign: "center", children: [jsxs(InlineStack, { gap: '100', blockAlign: "center", children: [jsx("div", { className: "w-[12px] border border-dashed border-[#A1CAE7]" }), jsx(Text, { as: "p", variant: "bodySm", tone: "subdued", fontWeight: "medium", children: previousData.tooltipKey })] }), jsxs(InlineStack, { blockAlign: "center", gap: "100", children: [jsx(Text, { as: "span", variant: "bodySm", fontWeight: "semibold", children: formatValue(previousData.value) }), jsx("div", { className: "opacity-0", children: jsx(MetricPercentage, { change: formatPercent() }) })] })] })] })] }) }) }));
|
|
2355
|
-
};
|
|
2356
|
-
|
|
2357
|
-
const MetricInfoSkeleton = ({ isShowOneLine }) => {
|
|
2358
|
-
if (isShowOneLine) {
|
|
2359
|
-
return (jsx(Box, { width: "40%", children: jsx(SkeletonBodyText, { lines: 1 }) }));
|
|
2360
|
-
}
|
|
2361
|
-
return (jsxs(BlockStack, { gap: "200", children: [jsx(Box, { width: "60%", children: jsx(SkeletonBodyText, { lines: 1 }) }), jsx(Box, { width: "40%", children: jsx(SkeletonBodyText, { lines: 1 }) })] }));
|
|
2362
|
-
};
|
|
2363
|
-
|
|
2364
|
-
const MetricDonutChartSkeleton = () => {
|
|
2365
|
-
return (jsx(Card, { children: jsxs(BlockStack, { gap: "400", children: [jsx(MetricInfoSkeleton, { isShowOneLine: true }), jsx(GChartSkeleton, {})] }) }));
|
|
2366
|
-
};
|
|
2367
|
-
|
|
2368
|
-
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 })] }) }));
|
|
2369
|
-
|
|
2370
|
-
const MetricInfoBlock = ({ item, isHovered, isLoading, hideComparison, titleVariant = 'headingMd', titleFontWeight, onClickTitle, }) => {
|
|
2371
|
-
const { key, title, totalValue } = item;
|
|
2372
|
-
const tooltip = ANALYTICS_METRIC_TOOLTIP[key];
|
|
2373
|
-
if (isLoading)
|
|
2374
|
-
return jsx(MetricInfoSkeleton, {});
|
|
2375
|
-
return (jsxs(BlockStack, { gap: "200", children: [jsx("div", { className: "hover:cursor-pointer hover:text-[--p-color-text-link-hover]", onClick: (e) => {
|
|
2376
|
-
e?.stopPropagation();
|
|
2377
|
-
onClickTitle?.(key);
|
|
2378
|
-
}, 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 })] }));
|
|
2379
|
-
};
|
|
2380
|
-
|
|
2381
|
-
const MetricChartTab = ({ item, isActive, isLoading, hideComparison, onSelect, onClickTitle, }) => {
|
|
2382
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
2383
|
-
const isHighlighted = isActive || isHovered;
|
|
2384
|
-
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 }) }) }));
|
|
2385
2197
|
};
|
|
2386
2198
|
|
|
2387
|
-
const
|
|
2388
|
-
const
|
|
2389
|
-
const
|
|
2390
|
-
|
|
2391
|
-
if (!chartData)
|
|
2199
|
+
const useVersionDateTimeFilters = (versions) => {
|
|
2200
|
+
const { t } = useTranslation();
|
|
2201
|
+
const rangers = useMemo(() => {
|
|
2202
|
+
if (!versions?.length)
|
|
2392
2203
|
return [];
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
gridTemplateColumns: `repeat(${metricInfo.length}, 1fr)`,
|
|
2401
|
-
gap: '16px',
|
|
2402
|
-
marginBottom: '16px',
|
|
2403
|
-
}, 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 })] }));
|
|
2204
|
+
return convertToDateTimeFilters(versions);
|
|
2205
|
+
}, [versions]);
|
|
2206
|
+
const rangeAddition = {
|
|
2207
|
+
title: t('Experiment periods'),
|
|
2208
|
+
rangers,
|
|
2209
|
+
};
|
|
2210
|
+
return { rangeAddition };
|
|
2404
2211
|
};
|
|
2405
2212
|
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2213
|
+
function DateTimeFilterInputs({ onBlur, dateRange, setDateTimePicked }) {
|
|
2214
|
+
const [isFocus, setIsFocus] = useState(false);
|
|
2215
|
+
const [inputValues, setInputValues] = useState({});
|
|
2216
|
+
const formatDisplayDate = useCallback((timestamp, isEnd = false) => {
|
|
2217
|
+
if (!dateRange.isVersion || (isEnd && dateRange.isCurrentVersion))
|
|
2218
|
+
return formatDate(timestamp, 'FULL');
|
|
2219
|
+
return formatDate(timestamp, 'FULL_WITH_TIME');
|
|
2220
|
+
}, [dateRange.isVersion, dateRange.isCurrentVersion]);
|
|
2221
|
+
useEffect(() => {
|
|
2222
|
+
if (isFocus)
|
|
2223
|
+
return;
|
|
2224
|
+
setInputValues({
|
|
2225
|
+
since: formatDisplayDate(dateRange.since),
|
|
2226
|
+
until: formatDisplayDate(dateRange.until, true),
|
|
2227
|
+
});
|
|
2228
|
+
}, [dateRange, formatDisplayDate]);
|
|
2229
|
+
function handleStartInputValueChange(value) {
|
|
2230
|
+
setInputValues((prevState) => {
|
|
2231
|
+
return { ...prevState, since: value };
|
|
2232
|
+
});
|
|
2233
|
+
if (isValidDate(value)) {
|
|
2234
|
+
const newSinceDate = convertDateToTz(value).startOf('day');
|
|
2235
|
+
const untilDate = convertDateToTz(dateRange.until).endOf('day');
|
|
2236
|
+
const endDate = newSinceDate.isAfter(untilDate) ? newSinceDate.endOf('day') : untilDate;
|
|
2237
|
+
setDateTimePicked({
|
|
2238
|
+
start: dayjsTzToLocalTZ(newSinceDate).toDate(),
|
|
2239
|
+
end: dayjsTzToLocalTZ(endDate).toDate(),
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2409
2242
|
}
|
|
2410
|
-
|
|
2411
|
-
|
|
2243
|
+
function handleEndInputValueChange(value) {
|
|
2244
|
+
setInputValues((prevState) => ({ ...prevState, until: value }));
|
|
2245
|
+
if (isValidDate(value)) {
|
|
2246
|
+
const nowEndOfDay = dayjsTz().endOf('day');
|
|
2247
|
+
const newUntilDate = convertDateToTz(value).endOf('day');
|
|
2248
|
+
const clampedUntil = newUntilDate.isAfter(nowEndOfDay) ? nowEndOfDay : newUntilDate;
|
|
2249
|
+
const sinceDate = convertDateToTz(dateRange.since).startOf('day');
|
|
2250
|
+
const startDate = clampedUntil.isBefore(sinceDate) ? clampedUntil.startOf('day') : sinceDate;
|
|
2251
|
+
setDateTimePicked({
|
|
2252
|
+
start: dayjsTzToLocalTZ(startDate).toDate(),
|
|
2253
|
+
end: dayjsTzToLocalTZ(clampedUntil).toDate(),
|
|
2254
|
+
});
|
|
2255
|
+
}
|
|
2412
2256
|
}
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
});
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2257
|
+
function handleInputBlur() {
|
|
2258
|
+
setIsFocus(false);
|
|
2259
|
+
setInputValues({
|
|
2260
|
+
since: formatDisplayDate(dateRange.since),
|
|
2261
|
+
until: formatDisplayDate(dateRange.until, true),
|
|
2262
|
+
});
|
|
2263
|
+
onBlur && onBlur();
|
|
2264
|
+
}
|
|
2265
|
+
function handleFocusStartInput() {
|
|
2266
|
+
setIsFocus(true);
|
|
2267
|
+
setInputValues({
|
|
2268
|
+
...inputValues,
|
|
2269
|
+
since: formatDate(dateRange.since, 'YMD'),
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
function handleFocusEndInput() {
|
|
2273
|
+
setIsFocus(true);
|
|
2274
|
+
setInputValues({
|
|
2275
|
+
...inputValues,
|
|
2276
|
+
until: formatDate(dateRange.until, 'YMD'),
|
|
2277
|
+
});
|
|
2278
|
+
}
|
|
2279
|
+
return (jsxs(InlineGrid, { gap: "200", columns: "1fr auto 1fr", children: [jsx(TextField, { role: "combobox", label: 'Since', labelHidden: true,
|
|
2280
|
+
// prefix={<Icon source={CalendarIcon} />}
|
|
2281
|
+
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,
|
|
2282
|
+
// prefix={<Icon source={CalendarIcon} />}
|
|
2283
|
+
value: dateRange.until ? inputValues.until : 'MMMM D, YYYY', onChange: handleEndInputValueChange, onBlur: () => handleInputBlur(), onFocus: () => handleFocusEndInput(), autoComplete: "off" })] }));
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
function DateTimeFilterAddition(props) {
|
|
2287
|
+
const { setDateTimePicked, dateTimePicked, rangeAddition, allRanges } = props;
|
|
2288
|
+
const { value: isExpanded, toggle: toggleExpanded } = useToggle(true);
|
|
2289
|
+
const rangesAdditions = rangeAddition?.rangers || [];
|
|
2290
|
+
const handleChangeFilterByOption = (value) => {
|
|
2291
|
+
const alias = value[0];
|
|
2292
|
+
const result = allRanges.find((range) => range.alias === alias) || allRanges[0];
|
|
2293
|
+
setDateTimePicked({
|
|
2294
|
+
start: dayjsTz(result?.since).toDate(),
|
|
2295
|
+
end: dayjsTz(result?.until).toDate(),
|
|
2296
|
+
alias: result?.alias,
|
|
2297
|
+
});
|
|
2298
|
+
};
|
|
2299
|
+
const options = rangesAdditions.map((range) => {
|
|
2300
|
+
const selected = dateTimePicked.alias === range.alias;
|
|
2301
|
+
return {
|
|
2302
|
+
value: range.alias,
|
|
2303
|
+
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})` })] }))] })),
|
|
2304
|
+
};
|
|
2305
|
+
});
|
|
2306
|
+
if (!rangeAddition || rangesAdditions.length === 0)
|
|
2307
|
+
return;
|
|
2308
|
+
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 }) })] }));
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
function DateTimeFilters(props) {
|
|
2312
|
+
const { setDateTimePicked, dateTimePicked, allRanges, isCompare } = props;
|
|
2313
|
+
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2314
|
+
const { mdDown } = useBreakpoints();
|
|
2315
|
+
const rangesDefault = isCompare ? [...DATE_TIME_COMPARISON_FILTERS] : [...DATE_TIME_FILTERS];
|
|
2316
|
+
const handleChangeFilterBySelect = (value) => {
|
|
2317
|
+
const result = allRanges.find(({ title, alias }) => title === value || alias === value) || allRanges[0];
|
|
2318
|
+
setDateTimePicked({
|
|
2319
|
+
start: dayjsTz(result?.since).toDate(),
|
|
2320
|
+
end: dayjsTz(result?.until).toDate(),
|
|
2321
|
+
alias: result?.alias,
|
|
2322
|
+
});
|
|
2323
|
+
};
|
|
2324
|
+
const handleChangeFilterByOption = (value) => {
|
|
2325
|
+
const result = allRanges.find((range) => range.alias === value[0]) || allRanges[0];
|
|
2326
|
+
setDateTimePicked({
|
|
2327
|
+
start: dayjsTz(result?.since).toDate(),
|
|
2328
|
+
end: dayjsTz(result?.until).toDate(),
|
|
2329
|
+
alias: result?.alias,
|
|
2330
|
+
});
|
|
2331
|
+
};
|
|
2332
|
+
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) => ({
|
|
2333
|
+
value: range.alias,
|
|
2334
|
+
label: range.title,
|
|
2335
|
+
})), selected: dateTimePicked ? [dateTimePicked.alias] : [], onChange: (value) => handleChangeFilterByOption(value) })] }) }) })) }));
|
|
2336
|
+
}
|
|
2337
|
+
|
|
2338
|
+
const useCompareDateTimePicker = ({ ranges, onApply }) => {
|
|
2339
|
+
const allRanges = ranges || DATE_TIME_COMPARISON_FILTERS;
|
|
2340
|
+
const { compareDateTimePicked, setCompareDateTimePicked } = useDateTimePickerContext();
|
|
2341
|
+
const { dateTimePicked: mainDateRange } = useDateTimePickerContext();
|
|
2342
|
+
const [dateRange, setDateRange] = useState(compareDateTimePicked);
|
|
2343
|
+
const [{ month, year }, setDate] = useState({
|
|
2344
|
+
month: dayjsTz(compareDateTimePicked.since).month(),
|
|
2345
|
+
year: dayjsTz(compareDateTimePicked.since).year(),
|
|
2346
|
+
});
|
|
2347
|
+
const onMonthChange = (month, year) => {
|
|
2348
|
+
setDate({ month, year });
|
|
2349
|
+
};
|
|
2350
|
+
const onCalendarChange = ({ start, end, alias }) => {
|
|
2351
|
+
const newDateRange = allRanges.find((range) => {
|
|
2352
|
+
return range.alias === alias;
|
|
2353
|
+
});
|
|
2354
|
+
// If the alias is not found, set the custom date range
|
|
2355
|
+
if (!newDateRange) {
|
|
2356
|
+
setDateRange({
|
|
2357
|
+
alias: 'custom',
|
|
2358
|
+
title: 'Custom',
|
|
2359
|
+
since: start.getTime(),
|
|
2360
|
+
until: end.getTime(),
|
|
2361
|
+
});
|
|
2362
|
+
return;
|
|
2363
|
+
}
|
|
2364
|
+
setDateRange({
|
|
2365
|
+
...newDateRange,
|
|
2366
|
+
...COMPARE_DATE_TIME_FILTERS_MAP[alias]({
|
|
2367
|
+
since: mainDateRange.since,
|
|
2368
|
+
until: mainDateRange.until,
|
|
2369
|
+
}),
|
|
2370
|
+
});
|
|
2371
|
+
};
|
|
2372
|
+
const apply = () => {
|
|
2373
|
+
setCompareDateTimePicked(dateRange);
|
|
2374
|
+
onApply?.(dateRange);
|
|
2375
|
+
};
|
|
2376
|
+
const cancel = () => {
|
|
2377
|
+
setDateRange(compareDateTimePicked);
|
|
2378
|
+
};
|
|
2379
|
+
const onChange = ({ end }) => {
|
|
2380
|
+
setDate(getMonthAndYearByDateFilter(month, year, end));
|
|
2381
|
+
};
|
|
2382
|
+
return {
|
|
2383
|
+
month,
|
|
2384
|
+
year,
|
|
2385
|
+
setDate,
|
|
2386
|
+
dateRange,
|
|
2387
|
+
apply,
|
|
2388
|
+
cancel,
|
|
2389
|
+
compareDateTimePicked,
|
|
2390
|
+
onChange,
|
|
2391
|
+
onMonthChange,
|
|
2392
|
+
onCalendarChange,
|
|
2393
|
+
};
|
|
2443
2394
|
};
|
|
2444
2395
|
|
|
2445
|
-
const
|
|
2446
|
-
const
|
|
2447
|
-
const
|
|
2448
|
-
const
|
|
2449
|
-
const
|
|
2450
|
-
const
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2396
|
+
const BaseTimePicker = (props) => {
|
|
2397
|
+
const { dateTimeFilters, rangeAddition, popoverProps, activatorProps, actionProps, isCompare, buttonValue, activator, } = props;
|
|
2398
|
+
const initialPicked = rangeAddition?.initialPicked;
|
|
2399
|
+
const ranges = [...(dateTimeFilters || []), ...(rangeAddition?.rangers || [])];
|
|
2400
|
+
const useHookDateTimePicker = isCompare ? useCompareDateTimePicker : useDateTimePicker;
|
|
2401
|
+
const { month, year, dateRange, apply, cancel, onMonthChange, onCalendarChange, onChange } = useHookDateTimePicker({
|
|
2402
|
+
ranges,
|
|
2403
|
+
initialPicked,
|
|
2404
|
+
onApply: props.onApply,
|
|
2405
|
+
});
|
|
2406
|
+
const { t } = useTranslation();
|
|
2407
|
+
const { mdDown, lgUp } = useBreakpoints();
|
|
2408
|
+
const shouldShowMultiMonth = lgUp;
|
|
2409
|
+
const rawTooltipContent = useMemo(() => {
|
|
2410
|
+
// Only show tooltip when selecting Period (isVersion)
|
|
2411
|
+
if (!dateRange.isVersion || !dateRange.since || !dateRange.until)
|
|
2412
|
+
return;
|
|
2413
|
+
return formatDateTimeRange({
|
|
2414
|
+
since: dateRange.since,
|
|
2415
|
+
until: dateRange.until,
|
|
2416
|
+
isShowNow: dateRange.isCurrentVersion,
|
|
2417
|
+
});
|
|
2418
|
+
}, [dateRange.since, dateRange.until, dateRange.isVersion, dateRange.isCurrentVersion]);
|
|
2419
|
+
const [popoverActive, setPopoverActive] = useState(false);
|
|
2420
|
+
// Freeze tooltip content while popover is open to prevent button remount (focus/CSS loss)
|
|
2421
|
+
const datePickerRef = useRef(null);
|
|
2422
|
+
const tooltipContentRef = useRef(rawTooltipContent);
|
|
2423
|
+
if (!popoverActive)
|
|
2424
|
+
tooltipContentRef.current = rawTooltipContent;
|
|
2425
|
+
const tooltipContent = tooltipContentRef.current;
|
|
2426
|
+
//@ts-ignore
|
|
2427
|
+
function nodeContainsDescendant(rootNode, descendant) {
|
|
2428
|
+
if (rootNode === descendant) {
|
|
2429
|
+
return true;
|
|
2430
|
+
}
|
|
2431
|
+
let parent = descendant.parentNode;
|
|
2432
|
+
while (parent != null) {
|
|
2433
|
+
if (parent === rootNode) {
|
|
2434
|
+
return true;
|
|
2435
|
+
}
|
|
2436
|
+
parent = parent.parentNode;
|
|
2437
|
+
}
|
|
2438
|
+
return false;
|
|
2454
2439
|
}
|
|
2455
|
-
|
|
2456
|
-
|
|
2440
|
+
//@ts-ignore
|
|
2441
|
+
function isNodeWithinPopover(node) {
|
|
2442
|
+
return datePickerRef?.current ? nodeContainsDescendant(datePickerRef.current, node) : false;
|
|
2443
|
+
}
|
|
2444
|
+
//@ts-ignore
|
|
2445
|
+
function handleInputBlur({ relatedTarget }) {
|
|
2446
|
+
const isRelatedTargetWithinPopover = relatedTarget != null && isNodeWithinPopover(relatedTarget);
|
|
2447
|
+
// If focus moves from the TextField to the Popover
|
|
2448
|
+
// we don't want to close the popover
|
|
2449
|
+
if (isRelatedTargetWithinPopover) {
|
|
2450
|
+
return;
|
|
2451
|
+
}
|
|
2452
|
+
setPopoverActive(false);
|
|
2453
|
+
}
|
|
2454
|
+
function applyFunc() {
|
|
2455
|
+
apply();
|
|
2456
|
+
setPopoverActive(false);
|
|
2457
|
+
}
|
|
2458
|
+
function cancelFunc() {
|
|
2459
|
+
cancel();
|
|
2460
|
+
setPopoverActive(false);
|
|
2461
|
+
}
|
|
2462
|
+
const handleTogglePopover = () => {
|
|
2463
|
+
if (isCompare) {
|
|
2464
|
+
return;
|
|
2465
|
+
}
|
|
2466
|
+
setPopoverActive(!popoverActive);
|
|
2457
2467
|
};
|
|
2458
|
-
const
|
|
2459
|
-
|
|
2460
|
-
|
|
2468
|
+
const onChangeDateTimeFilter = (data) => {
|
|
2469
|
+
onCalendarChange(data);
|
|
2470
|
+
onChange(data);
|
|
2461
2471
|
};
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2472
|
+
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: {
|
|
2473
|
+
xs: '1fr',
|
|
2474
|
+
md: 'max-content max-content',
|
|
2475
|
+
}, 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
|
|
2476
|
+
? undefined
|
|
2477
|
+
: {
|
|
2478
|
+
start: dayjs(dateRange.since).toDate(),
|
|
2479
|
+
end: dayjs(dateRange.until).toDate(),
|
|
2480
|
+
}, onMonthChange: onMonthChange, onChange: onCalendarChange, multiMonth: shouldShowMultiMonth, allowRange: true, disableDatesAfter: dayjsTzToDate() }) }), actionProps && (jsx(GButton, { ...actionProps, onClick: () => {
|
|
2481
|
+
setPopoverActive(false);
|
|
2482
|
+
actionProps.onClick?.();
|
|
2483
|
+
} }))] }) })] }) }) }), 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') })] }) }) }) })] }) }));
|
|
2468
2484
|
};
|
|
2469
2485
|
|
|
2470
|
-
const
|
|
2471
|
-
const
|
|
2472
|
-
|
|
2486
|
+
const CompareTimePicker = (props) => {
|
|
2487
|
+
const { rangeAddition, popoverProps } = props;
|
|
2488
|
+
const initialPicked = rangeAddition?.initialPicked;
|
|
2489
|
+
const dateTimeFilters = DATE_TIME_COMPARISON_FILTERS;
|
|
2490
|
+
const ranges = [...dateTimeFilters, ...(rangeAddition?.rangers || [])];
|
|
2491
|
+
const { t } = useTranslation();
|
|
2492
|
+
const { compareDateTimePicked } = useCompareDateTimePicker({ ranges, initialPicked });
|
|
2493
|
+
const buttonValue = useMemo(() => {
|
|
2494
|
+
if (compareDateTimePicked.alias === CompareDateTimePickerAlias.NO_COMPARISON) {
|
|
2495
|
+
return t('No comparison');
|
|
2496
|
+
}
|
|
2497
|
+
return t('Compare to: {{value}}', {
|
|
2498
|
+
value: getDateRangeTitle(compareDateTimePicked.since, compareDateTimePicked.until),
|
|
2499
|
+
});
|
|
2500
|
+
}, [compareDateTimePicked, t]);
|
|
2501
|
+
return (jsx(BaseTimePicker, { dateTimeFilters: dateTimeFilters, rangeAddition: rangeAddition, popoverProps: popoverProps, isCompare: true, buttonValue: buttonValue }));
|
|
2473
2502
|
};
|
|
2474
2503
|
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
},
|
|
2493
|
-
{
|
|
2494
|
-
id: EAnalyticMode.FIRST_SESSION,
|
|
2495
|
-
content: 'Entry session only',
|
|
2496
|
-
helpText: 'Count metrics for sessions only where this page was the very first page visited, then track how they moved through the funnel.',
|
|
2497
|
-
icon: IMAGE_FIRST_SESSION,
|
|
2498
|
-
},
|
|
2499
|
-
];
|
|
2500
|
-
const AnalyticModeSelector = ({ activatorText = 'View by', value, onChange }) => {
|
|
2501
|
-
const options = useMemo(() => {
|
|
2502
|
-
return VIEW_BY_OPTIONS.map((option) => ({
|
|
2503
|
-
...option,
|
|
2504
|
-
}));
|
|
2505
|
-
}, []);
|
|
2506
|
-
const onSelectMode = (value) => {
|
|
2507
|
-
onChange(value);
|
|
2504
|
+
const MainTimePicker = (props) => {
|
|
2505
|
+
const { rangeAddition, popoverProps, activator, onApply, activatorProps, actionProps } = props;
|
|
2506
|
+
const { DATE_TIME_FILTERS } = useDateTimeFilter();
|
|
2507
|
+
const dateTimeFilters = DATE_TIME_FILTERS;
|
|
2508
|
+
const additionalRanges = rangeAddition?.rangers || [];
|
|
2509
|
+
const initialPicked = rangeAddition?.initialPicked;
|
|
2510
|
+
const ranges = [...dateTimeFilters, ...additionalRanges];
|
|
2511
|
+
const { dateTimePicked } = useDateTimePicker({ ranges, initialPicked });
|
|
2512
|
+
const getButtonValue = () => {
|
|
2513
|
+
if (dateTimePicked.isVersion && additionalRanges.length > 0) {
|
|
2514
|
+
const time = dateTimePicked.description ? `at ${dateTimePicked.description}` : '';
|
|
2515
|
+
return `Period: ${dateTimePicked.title} ${time}`;
|
|
2516
|
+
}
|
|
2517
|
+
if (dateTimePicked.alias === 'custom') {
|
|
2518
|
+
return getDateRangeTitle(dateTimePicked.since, dateTimePicked.until);
|
|
2519
|
+
}
|
|
2520
|
+
return dateTimePicked.title;
|
|
2508
2521
|
};
|
|
2509
|
-
return (jsx(
|
|
2522
|
+
return (jsx(BaseTimePicker, { activatorProps: activatorProps, dateTimeFilters: dateTimeFilters, rangeAddition: rangeAddition, popoverProps: popoverProps, actionProps: actionProps, buttonValue: getButtonValue(), activator: activator, onApply: onApply }));
|
|
2510
2523
|
};
|
|
2511
2524
|
|
|
2512
|
-
const
|
|
2513
|
-
const
|
|
2514
|
-
|
|
2515
|
-
const onSelectRef = useRef(onSelect);
|
|
2516
|
-
const handleSelection = useCallback((value) => {
|
|
2517
|
-
onSelectRef.current?.(value);
|
|
2518
|
-
}, []);
|
|
2519
|
-
const actionItems = useMemo(() => {
|
|
2520
|
-
if (!currencies)
|
|
2521
|
-
return [];
|
|
2522
|
-
const formattedCurrencies = currencies.map((currency) => ({
|
|
2523
|
-
content: currency,
|
|
2524
|
-
id: currency,
|
|
2525
|
-
}));
|
|
2526
|
-
const hasCurrencyDefault = formattedCurrencies.some((item) => item.id === DEFAULT_CURRENCY_ANALYTIC);
|
|
2527
|
-
if (!hasCurrencyDefault) {
|
|
2528
|
-
formattedCurrencies.push({
|
|
2529
|
-
content: DEFAULT_CURRENCY_ANALYTIC,
|
|
2530
|
-
id: DEFAULT_CURRENCY_ANALYTIC,
|
|
2531
|
-
});
|
|
2532
|
-
}
|
|
2533
|
-
return sortByConditions(formattedCurrencies, [
|
|
2534
|
-
{ attr: 'content', order: 'asc', preferredValue: DEFAULT_CURRENCY_ANALYTIC },
|
|
2535
|
-
]);
|
|
2536
|
-
}, [currencies]);
|
|
2537
|
-
const actionListItems = useMemo(() => {
|
|
2538
|
-
return actionItems.map((option) => ({
|
|
2539
|
-
id: option.id,
|
|
2540
|
-
content: option.content,
|
|
2541
|
-
onAction: () => handleSelection(option.id),
|
|
2542
|
-
active: option.id === selected,
|
|
2543
|
-
suffix: option.id === selected && jsx(Icon, { source: SvgCheckIcon, tone: "success" }),
|
|
2544
|
-
helpText: option.id === DEFAULT_CURRENCY_ANALYTIC && (jsx(Text, { as: "p", fontWeight: "semibold", children: t('Default') })),
|
|
2545
|
-
}));
|
|
2546
|
-
}, [actionItems, selected, handleSelection, t]);
|
|
2547
|
-
const isHidden = useMemo(() => {
|
|
2548
|
-
if (!actionItems?.length)
|
|
2549
|
-
return true;
|
|
2550
|
-
return actionItems.length === 1 && actionItems[0]?.id === DEFAULT_CURRENCY_ANALYTIC;
|
|
2551
|
-
}, [actionItems]);
|
|
2552
|
-
useEffect(() => {
|
|
2553
|
-
onSelectRef.current = onSelect;
|
|
2554
|
-
});
|
|
2555
|
-
if (isHidden)
|
|
2556
|
-
return null;
|
|
2557
|
-
return (jsx(GSelector, { options: actionListItems, selected: selected, variant: "action-list",
|
|
2558
|
-
// value originates from our CurrencyCode option ids, so the widen-to-string round trip is safe
|
|
2559
|
-
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: {
|
|
2560
|
-
1: (text) => (jsx(GTextLink, { linkAction: {
|
|
2561
|
-
url: EXCHANGE_RATE_HELP_URL,
|
|
2562
|
-
target: '_blank',
|
|
2563
|
-
}, children: text }, text + 'text-link')),
|
|
2564
|
-
}, children: t("This will follow Shopify's current exchange rate. [1]Read more[]") }) }) }));
|
|
2525
|
+
const GTimePicker = (props) => {
|
|
2526
|
+
const { isCompare, ...timePickerProps } = props;
|
|
2527
|
+
return (jsxs(InlineStack, { gap: "200", children: [jsx(MainTimePicker, { ...timePickerProps }), isCompare && (jsx(CompareTimePicker, { rangeAddition: timePickerProps.rangeAddition, popoverProps: timePickerProps.popoverProps }))] }));
|
|
2565
2528
|
};
|
|
2566
2529
|
|
|
2567
|
-
export {
|
|
2530
|
+
export { AnalyticModeSelector, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricDonutChartCard, PREVIOUS_PERIOD_FILTER, SingleMetricChartCard, 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, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useVersionDateTimeFilters };
|