@pushwoosh/dumb-components 1.1.119 → 1.1.120

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.
@@ -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
- isDisabled,
14
- onChange
17
+ globalCapping,
18
+ onChange,
19
+ editGlobalClicked,
20
+ applicationCode,
21
+ isInJourney = false,
22
+ isDisabled = false
15
23
  } = props;
16
- const options = cappingOptions.filter(({
17
- value
18
- }) => value !== CappingTypes.GLOBAL);
19
- const cappingOption = capping !== null ? CappingTypes.CUSTOM : CappingTypes.IGNORE;
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(null);
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
- }, [onChange]);
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: options,
43
- value: options.find(option => option.value === cappingOption),
68
+ options: cappingOptions,
69
+ value: cappingOptions.find(option => option.value === cappingOption),
44
70
  onChange: newValue => onChangeFrequencyCapping(newValue.value)
45
- })), capping !== null && !isDisabled && React.createElement(EditInAppCappingSettings, {
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
- messages: number;
4
- days: number;
3
+ text: string;
5
4
  tooltip?: string;
6
5
  $inText?: boolean;
7
6
  };
8
- export declare function ChipFrequencyCapping({ messages, days, tooltip, $inText }: ChipFrequencyCappingProps): React.JSX.Element;
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
- messages,
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
- }, `${messages} messages per ${days} ${days > 1 ? 'days' : 'day'}`, React.createElement(HelpRoundIcon, {
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
- }, messages === 0 && days === 0 ? 'unlimited' : `${messages} messages per ${days} ${days > 1 ? 'days' : 'day'}`));
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 | undefined;
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 { CappingTypes } from '../../types';
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
- if (cappingOption === CappingTypes.GLOBAL) {
14
- if (messages === 0 && days === 0) {
15
- return React.createElement(Paragraph, null, "This message will use an", React.createElement(ChipFrequencyCapping, {
16
- days: 0,
17
- messages: 0,
18
- "$inText": true
19
- }), "global frequency capping because limit isn\u2019t set.", ' ', children);
20
- }
21
- return React.createElement(Paragraph, null, "Under the current setup, If the user receives more than", React.createElement(ChipFrequencyCapping, {
22
- messages: messages,
23
- days: days,
24
- "$inText": true
25
- }), `, this message will not be delivered${isInJourney ? ', and the user will proceed to the next step' : ''}. `, children);
26
- }
27
- if (cappingOption === CappingTypes.CUSTOM) {
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,3 @@
1
+ type Unit = 'message' | 'in-app';
2
+ export declare function getCappingChipText(messages: number, days: number, unit?: Unit): string;
3
+ export {};
@@ -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
- messages: capping.messages,
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
- days: 0,
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
- messages: globalCapping.count,
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 | null;
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
  };
@@ -85,6 +85,7 @@ export function NumberPicker({
85
85
  value: localValue,
86
86
  placeholder: placeholder,
87
87
  isDisabled: isDisabled,
88
+ disabled: isDisabled,
88
89
  onChange: handleChange,
89
90
  onKeyDown: handleKeyDown,
90
91
  onKeyUp: resetAutoDiff,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushwoosh/dumb-components",
3
- "version": "1.1.119",
3
+ "version": "1.1.120",
4
4
  "description": "React components to build Pushwoosh products",
5
5
  "main": "index.js",
6
6
  "module": "index.js",