@pushwoosh/dumb-components 1.1.119 → 1.1.121
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/Calendar/helpers.js +1 -1
- package/DateTimePicker/helpers.js +1 -1
- package/FrequencyCapping/FrequencyCappingInApps.js +56 -15
- package/FrequencyCapping/components/Condition/index.d.ts +2 -3
- package/FrequencyCapping/components/Condition/index.js +3 -4
- package/FrequencyCapping/components/Description/index.d.ts +3 -2
- package/FrequencyCapping/components/Description/index.js +18 -23
- package/FrequencyCapping/helpers/getCappingChipText.d.ts +3 -0
- package/FrequencyCapping/helpers/getCappingChipText.js +18 -0
- package/FrequencyCapping/helpers/getDescriptionMessages.d.ts +16 -0
- package/FrequencyCapping/helpers/getDescriptionMessages.js +66 -0
- package/FrequencyCapping/helpers/getReadonlyCappingHelpers.js +4 -6
- package/FrequencyCapping/types.d.ts +11 -2
- package/NumberPicker/NumberPicker.js +1 -0
- package/package.json +1 -1
package/Calendar/helpers.js
CHANGED
|
@@ -65,7 +65,7 @@ export const differenceInDays = (ds1, ds2) => {
|
|
|
65
65
|
};
|
|
66
66
|
export const monthName = (month, monthFormat = 'long') => {
|
|
67
67
|
const date = new Date(2023, month - 1, 1);
|
|
68
|
-
return date.toLocaleString('
|
|
68
|
+
return date.toLocaleString('en-US', {
|
|
69
69
|
month: monthFormat
|
|
70
70
|
});
|
|
71
71
|
};
|
|
@@ -33,7 +33,7 @@ export const differenceInDays = (d1, d2) => {
|
|
|
33
33
|
};
|
|
34
34
|
export const monthName = (month, monthFormat = 'long') => {
|
|
35
35
|
const date = new Date(2023, month - 1, 1);
|
|
36
|
-
return date.toLocaleString('
|
|
36
|
+
return date.toLocaleString('en-US', {
|
|
37
37
|
month: monthFormat
|
|
38
38
|
});
|
|
39
39
|
};
|
|
@@ -1,30 +1,56 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
2
|
import { Color } from '@pushwoosh/kit-constants';
|
|
3
3
|
import { Vertical } from '@pushwoosh/kit-helpers';
|
|
4
|
+
import { OpenIcon } from '@pushwoosh/kit-icons';
|
|
5
|
+
import { Description } from './components/Description';
|
|
6
|
+
import { EditInAppCappingSettings } from './components/Settings';
|
|
7
|
+
import { getCappingOption } from './helpers/getCappingOption';
|
|
8
|
+
import { CappingTypes } from './types';
|
|
4
9
|
import { FieldBox } from '../FieldBox';
|
|
10
|
+
import { Link } from '../Link';
|
|
5
11
|
import { Select } from '../Select';
|
|
6
|
-
import { EditInAppCappingSettings } from './components/Settings';
|
|
7
12
|
import { cappingOptions } from './constants';
|
|
8
|
-
import { Container } from './styles';
|
|
9
|
-
import { CappingTypes } from './types';
|
|
13
|
+
import { Container, LinkWrapper } from './styles';
|
|
10
14
|
export function FrequencyCappingInApps(props) {
|
|
11
15
|
const {
|
|
12
16
|
capping,
|
|
13
|
-
|
|
14
|
-
onChange
|
|
17
|
+
globalCapping,
|
|
18
|
+
onChange,
|
|
19
|
+
editGlobalClicked,
|
|
20
|
+
applicationCode,
|
|
21
|
+
isInJourney = false,
|
|
22
|
+
isDisabled = false
|
|
15
23
|
} = props;
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
const {
|
|
25
|
+
enabled,
|
|
26
|
+
ignoreGlobalCapping
|
|
27
|
+
} = capping;
|
|
28
|
+
const cappingOption = getCappingOption(enabled, ignoreGlobalCapping);
|
|
29
|
+
const isGlobalCappingDisabled = globalCapping.count === 0 && globalCapping.days === 0;
|
|
30
|
+
const globalCappingLinkText = isGlobalCappingDisabled ? 'Set up' : 'Settings';
|
|
20
31
|
const onChangeFrequencyCapping = useCallback(value => {
|
|
21
32
|
if (value === CappingTypes.IGNORE) {
|
|
22
|
-
onChange(
|
|
33
|
+
onChange({
|
|
34
|
+
...capping,
|
|
35
|
+
enabled: false,
|
|
36
|
+
ignoreGlobalCapping: true
|
|
37
|
+
});
|
|
23
38
|
}
|
|
24
39
|
if (value === CappingTypes.CUSTOM) {
|
|
25
|
-
onChange({
|
|
40
|
+
onChange({
|
|
41
|
+
...capping,
|
|
42
|
+
enabled: true,
|
|
43
|
+
ignoreGlobalCapping: false
|
|
44
|
+
});
|
|
26
45
|
}
|
|
27
|
-
|
|
46
|
+
if (value === CappingTypes.GLOBAL) {
|
|
47
|
+
onChange({
|
|
48
|
+
...capping,
|
|
49
|
+
enabled: false,
|
|
50
|
+
ignoreGlobalCapping: false
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}, [capping, onChange]);
|
|
28
54
|
const onSettingsChange = useCallback(newCapping => {
|
|
29
55
|
onChange(newCapping);
|
|
30
56
|
}, [onChange]);
|
|
@@ -39,10 +65,25 @@ export function FrequencyCappingInApps(props) {
|
|
|
39
65
|
}, React.createElement(Select, {
|
|
40
66
|
name: "cappingOption",
|
|
41
67
|
isDisabled: isDisabled,
|
|
42
|
-
options:
|
|
43
|
-
value:
|
|
68
|
+
options: cappingOptions,
|
|
69
|
+
value: cappingOptions.find(option => option.value === cappingOption),
|
|
44
70
|
onChange: newValue => onChangeFrequencyCapping(newValue.value)
|
|
45
|
-
})),
|
|
71
|
+
})), React.createElement(Description, {
|
|
72
|
+
cappingOption: cappingOption,
|
|
73
|
+
messages: globalCapping.count,
|
|
74
|
+
days: globalCapping.days,
|
|
75
|
+
isInJourney: isInJourney,
|
|
76
|
+
variant: "in-app"
|
|
77
|
+
}, cappingOption === CappingTypes.GLOBAL && React.createElement(Link, {
|
|
78
|
+
target: "_blank",
|
|
79
|
+
href: `/applications/${applicationCode}/message-delivery?tab=capping`,
|
|
80
|
+
title: globalCappingLinkText,
|
|
81
|
+
onClick: editGlobalClicked
|
|
82
|
+
}, React.createElement(LinkWrapper, null, globalCappingLinkText, React.createElement(OpenIcon, {
|
|
83
|
+
size: "small",
|
|
84
|
+
view: "lined",
|
|
85
|
+
as: "span"
|
|
86
|
+
})))), cappingOption === CappingTypes.CUSTOM && !isDisabled && React.createElement(EditInAppCappingSettings, {
|
|
46
87
|
capping: capping,
|
|
47
88
|
onChange: onSettingsChange
|
|
48
89
|
})));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
type ChipFrequencyCappingProps = {
|
|
3
|
-
|
|
4
|
-
days: number;
|
|
3
|
+
text: string;
|
|
5
4
|
tooltip?: string;
|
|
6
5
|
$inText?: boolean;
|
|
7
6
|
};
|
|
8
|
-
export declare function ChipFrequencyCapping({
|
|
7
|
+
export declare function ChipFrequencyCapping({ text, tooltip, $inText }: ChipFrequencyCappingProps): React.JSX.Element;
|
|
9
8
|
export {};
|
|
@@ -5,8 +5,7 @@ import { ChipWithinTextContainer } from './styles';
|
|
|
5
5
|
import { Chip } from '../../../Chip';
|
|
6
6
|
import { Tooltip } from '../../../Tooltip';
|
|
7
7
|
export function ChipFrequencyCapping({
|
|
8
|
-
|
|
9
|
-
days,
|
|
8
|
+
text,
|
|
10
9
|
tooltip,
|
|
11
10
|
$inText = false
|
|
12
11
|
}) {
|
|
@@ -19,7 +18,7 @@ export function ChipFrequencyCapping({
|
|
|
19
18
|
"$variant": "primary",
|
|
20
19
|
"$readOnly": true,
|
|
21
20
|
as: "span"
|
|
22
|
-
},
|
|
21
|
+
}, text, React.createElement(HelpRoundIcon, {
|
|
23
22
|
as: "span",
|
|
24
23
|
size: "small",
|
|
25
24
|
view: "lined",
|
|
@@ -28,5 +27,5 @@ export function ChipFrequencyCapping({
|
|
|
28
27
|
"$variant": "primary",
|
|
29
28
|
"$readOnly": true,
|
|
30
29
|
as: "span"
|
|
31
|
-
},
|
|
30
|
+
}, text));
|
|
32
31
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React, { type ReactNode } from 'react';
|
|
2
|
-
import { CappingTypes } from '../../types';
|
|
2
|
+
import { type CappingTypes } from '../../types';
|
|
3
3
|
type Props = {
|
|
4
4
|
cappingOption: CappingTypes;
|
|
5
5
|
messages: number;
|
|
6
6
|
days: number;
|
|
7
7
|
children?: ReactNode;
|
|
8
8
|
isInJourney: boolean;
|
|
9
|
+
variant?: 'message' | 'in-app';
|
|
9
10
|
};
|
|
10
|
-
export declare function Description(props: Props): React.JSX.Element
|
|
11
|
+
export declare function Description(props: Props): React.JSX.Element;
|
|
11
12
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Paragraph } from '@pushwoosh/kit-typography';
|
|
3
|
-
import {
|
|
3
|
+
import { getDescriptionMessages } from '../../helpers/getDescriptionMessages';
|
|
4
4
|
import { ChipFrequencyCapping } from '../Condition';
|
|
5
5
|
export function Description(props) {
|
|
6
6
|
const {
|
|
@@ -8,27 +8,22 @@ export function Description(props) {
|
|
|
8
8
|
messages,
|
|
9
9
|
days,
|
|
10
10
|
children,
|
|
11
|
-
isInJourney
|
|
11
|
+
isInJourney,
|
|
12
|
+
variant = 'message'
|
|
12
13
|
} = props;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return React.createElement(Paragraph, null, `Instead of Global frequency capping, the limit of sent messages you set will be used. If the
|
|
29
|
-
subscriber exceeds the limit of received messages, they will not receive this message${isInJourney ? ', and will proceed to the next step' : ''}. `, children);
|
|
30
|
-
}
|
|
31
|
-
if (cappingOption === CappingTypes.IGNORE) {
|
|
32
|
-
return React.createElement(Paragraph, null, "The user will receive this message regardless, even if they have exceeded the set message limits for the channel. Use with caution to avoid sending too many messages.", ' ', children);
|
|
33
|
-
}
|
|
14
|
+
const {
|
|
15
|
+
prefix,
|
|
16
|
+
chip,
|
|
17
|
+
suffix
|
|
18
|
+
} = getDescriptionMessages({
|
|
19
|
+
cappingOption,
|
|
20
|
+
variant,
|
|
21
|
+
messages,
|
|
22
|
+
days,
|
|
23
|
+
isInJourney
|
|
24
|
+
});
|
|
25
|
+
return React.createElement(Paragraph, null, prefix, chip && React.createElement(ChipFrequencyCapping, {
|
|
26
|
+
text: chip,
|
|
27
|
+
"$inText": true
|
|
28
|
+
}), suffix, ' ', children);
|
|
34
29
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const unitLabels = {
|
|
2
|
+
message: {
|
|
3
|
+
singular: 'message',
|
|
4
|
+
plural: 'messages'
|
|
5
|
+
},
|
|
6
|
+
'in-app': {
|
|
7
|
+
singular: 'in-app',
|
|
8
|
+
plural: 'in-apps'
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export function getCappingChipText(messages, days, unit = 'message') {
|
|
12
|
+
if (messages === 0 && days === 0) {
|
|
13
|
+
return 'unlimited';
|
|
14
|
+
}
|
|
15
|
+
const unitLabel = messages === 1 ? unitLabels[unit].singular : unitLabels[unit].plural;
|
|
16
|
+
const daysLabel = days > 1 ? 'days' : 'day';
|
|
17
|
+
return `${messages} ${unitLabel} per ${days} ${daysLabel}`;
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CappingTypes } from '../types';
|
|
2
|
+
type Variant = 'message' | 'in-app';
|
|
3
|
+
type Params = {
|
|
4
|
+
cappingOption: CappingTypes;
|
|
5
|
+
variant: Variant;
|
|
6
|
+
messages: number;
|
|
7
|
+
days: number;
|
|
8
|
+
isInJourney: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type DescriptionMessages = {
|
|
11
|
+
prefix: string;
|
|
12
|
+
chip?: string;
|
|
13
|
+
suffix?: string;
|
|
14
|
+
};
|
|
15
|
+
export declare function getDescriptionMessages(params: Params): DescriptionMessages;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { CappingTypes } from '../types';
|
|
2
|
+
import { getCappingChipText } from './getCappingChipText';
|
|
3
|
+
export function getDescriptionMessages(params) {
|
|
4
|
+
const {
|
|
5
|
+
cappingOption
|
|
6
|
+
} = params;
|
|
7
|
+
if (cappingOption === CappingTypes.GLOBAL) {
|
|
8
|
+
return getGlobalMessages(params);
|
|
9
|
+
}
|
|
10
|
+
if (cappingOption === CappingTypes.CUSTOM) {
|
|
11
|
+
return getCustomMessages(params);
|
|
12
|
+
}
|
|
13
|
+
return getIgnoreMessages();
|
|
14
|
+
}
|
|
15
|
+
function getGlobalMessages({
|
|
16
|
+
variant,
|
|
17
|
+
messages,
|
|
18
|
+
days,
|
|
19
|
+
isInJourney
|
|
20
|
+
}) {
|
|
21
|
+
const isUnset = messages === 0 && days === 0;
|
|
22
|
+
if (variant === 'in-app') {
|
|
23
|
+
if (isUnset) {
|
|
24
|
+
return {
|
|
25
|
+
prefix: 'This in-app will use a global frequency capping because limit isn’t set.'
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
prefix: 'Under the current setup, If the user receives more than',
|
|
30
|
+
chip: getCappingChipText(messages, days, 'in-app'),
|
|
31
|
+
suffix: 'this in-app will not be delivered.'
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (isUnset) {
|
|
35
|
+
return {
|
|
36
|
+
prefix: 'This message will use an',
|
|
37
|
+
chip: getCappingChipText(0, 0),
|
|
38
|
+
suffix: 'global frequency capping because limit isn’t set.'
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const journeySuffix = isInJourney ? ', and the user will proceed to the next step' : '';
|
|
42
|
+
return {
|
|
43
|
+
prefix: 'Under the current setup, If the user receives more than',
|
|
44
|
+
chip: getCappingChipText(messages, days),
|
|
45
|
+
suffix: `, this message will not be delivered${journeySuffix}.`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function getCustomMessages({
|
|
49
|
+
variant,
|
|
50
|
+
isInJourney
|
|
51
|
+
}) {
|
|
52
|
+
if (variant === 'in-app') {
|
|
53
|
+
return {
|
|
54
|
+
prefix: 'Instead of Global frequency capping, the limit of shown in-apps you set will be used. ' + 'If the subscriber exceeds the limit of received in-apps, they will not see the in-app again.'
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const journeySuffix = isInJourney ? ', and will proceed to the next step' : '';
|
|
58
|
+
return {
|
|
59
|
+
prefix: 'Instead of Global frequency capping, the limit of sent messages you set will be used. ' + 'If the subscriber exceeds the limit of received messages, ' + `they will not receive this message${journeySuffix}.`
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function getIgnoreMessages() {
|
|
63
|
+
return {
|
|
64
|
+
prefix: 'The user will receive this message regardless, even if they have exceeded the set ' + 'message limits for the channel. Use with caution to avoid sending too many messages.'
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Horizontal } from '@pushwoosh/kit-helpers';
|
|
3
3
|
import { HelpRoundIcon } from '@pushwoosh/kit-icons';
|
|
4
|
+
import { getCappingChipText } from './getCappingChipText';
|
|
4
5
|
import { Tooltip } from '../../Tooltip';
|
|
5
6
|
import { ChipFrequencyCapping } from '../components/Condition';
|
|
6
7
|
import { IconWrapper } from '../styles';
|
|
@@ -9,8 +10,7 @@ export function getReadonlyCappingLabel(cappingOption, isGlobalCappingDisabled,
|
|
|
9
10
|
const tooltip = getReadonlyTooltip(cappingOption, isInJourney);
|
|
10
11
|
if (cappingOption === CappingTypes.CUSTOM) {
|
|
11
12
|
return React.createElement(React.Fragment, null, "Custom frequency capping for this message:", React.createElement(ChipFrequencyCapping, {
|
|
12
|
-
|
|
13
|
-
days: capping.days,
|
|
13
|
+
text: getCappingChipText(capping.messages, capping.days),
|
|
14
14
|
tooltip: tooltip
|
|
15
15
|
}));
|
|
16
16
|
}
|
|
@@ -30,11 +30,9 @@ export function getReadonlyCappingLabel(cappingOption, isGlobalCappingDisabled,
|
|
|
30
30
|
}))));
|
|
31
31
|
}
|
|
32
32
|
return isGlobalCappingDisabled ? React.createElement(React.Fragment, null, "Global frequency capping:", React.createElement(ChipFrequencyCapping, {
|
|
33
|
-
|
|
34
|
-
messages: 0
|
|
33
|
+
text: getCappingChipText(0, 0)
|
|
35
34
|
}), "because limit isn\u2019t set") : React.createElement(React.Fragment, null, "Global frequency capping:", React.createElement(ChipFrequencyCapping, {
|
|
36
|
-
|
|
37
|
-
days: globalCapping.days,
|
|
35
|
+
text: getCappingChipText(globalCapping.count, globalCapping.days),
|
|
38
36
|
tooltip: tooltip
|
|
39
37
|
}));
|
|
40
38
|
}
|
|
@@ -14,6 +14,8 @@ export type CappingBase = {
|
|
|
14
14
|
ignoreGlobalCapping: boolean;
|
|
15
15
|
};
|
|
16
16
|
export type CappingInAppBase = {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
ignoreGlobalCapping: boolean;
|
|
17
19
|
total?: {
|
|
18
20
|
count: number;
|
|
19
21
|
};
|
|
@@ -48,7 +50,14 @@ export type FrequencyCappingReadonlyProps<T extends CappingBase> = {
|
|
|
48
50
|
isInJourney?: boolean;
|
|
49
51
|
};
|
|
50
52
|
export type FrequencyCappingInAppsProps = {
|
|
51
|
-
capping: CappingInAppBase
|
|
53
|
+
capping: CappingInAppBase;
|
|
54
|
+
globalCapping: {
|
|
55
|
+
count: number;
|
|
56
|
+
days: number;
|
|
57
|
+
};
|
|
58
|
+
onChange: (newCappingState: CappingInAppBase) => void;
|
|
59
|
+
editGlobalClicked: () => void;
|
|
60
|
+
applicationCode: string;
|
|
61
|
+
isInJourney?: boolean;
|
|
52
62
|
isDisabled?: boolean;
|
|
53
|
-
onChange: (newCappingState: CappingInAppBase | null) => void;
|
|
54
63
|
};
|