• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SAP / ui5-webcomponents-react / 9598168049

20 Jun 2024 01:15PM CUT coverage: 88.056% (+0.3%) from 87.716%
9598168049

Pull #5940

github

web-flow
Merge 14dd3ac8d into cb684cdfb
Pull Request #5940: feat: update to @ui5/webcomonents 2.0.0-rc.6

2877 of 4064 branches covered (70.79%)

14 of 15 new or added lines in 6 files covered. (93.33%)

7 existing lines in 3 files now uncovered.

5183 of 5886 relevant lines covered (88.06%)

69957.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.45
/packages/main/src/components/VariantManagement/SaveViewDialog.tsx
1
import BarDesign from '@ui5/webcomponents/dist/types/BarDesign.js';
2
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
3
import { enrichEventWithDetails, useI18nBundle, useIsomorphicId, useStylesheet } from '@ui5/webcomponents-react-base';
4
import { clsx } from 'clsx';
5
import { useRef, useState } from 'react';
6
import { createPortal } from 'react-dom';
7
import { FlexBoxAlignItems, FlexBoxDirection } from '../../enums/index.js';
8
import {
9
  APPLY_AUTOMATICALLY,
10
  CANCEL,
11
  PUBLIC,
12
  SAVE,
13
  SAVE_VIEW,
14
  SET_AS_DEFAULT,
15
  SPECIFY_VIEW_NAME,
16
  VARIANT_MANAGEMENT_ERROR_DUPLICATE,
17
  VIEW
18
} from '../../i18n/i18n-defaults.js';
19
import { useCanRenderPortal } from '../../internal/ssr.js';
20
import { trimAndRemoveSpaces } from '../../internal/utils.js';
21
import type { SelectedVariant } from '../../internal/VariantManagementContext.js';
22
import type { Ui5CustomEvent } from '../../types/index.js';
23
import type { ButtonDomRef, DialogDomRef, InputPropTypes } from '../../webComponents/index.js';
24
import { Bar, Button, CheckBox, Dialog, Input, Label } from '../../webComponents/index.js';
25
import { FlexBox } from '../FlexBox/index.js';
26
import { classNames, styleData } from './SaveViewDialog.module.css.js';
27
import type { VariantManagementPropTypes } from './types.js';
28

29
interface SaveViewDialogPropTypes {
30
  onAfterClose: (event: Ui5CustomEvent<DialogDomRef>) => void;
31
  handleSave: (event: Ui5CustomEvent<ButtonDomRef>, selectedVariant: SelectedVariant) => void;
32
  selectedVariant: SelectedVariant;
33
  showShare: boolean;
34
  showApplyAutomatically: boolean;
35
  showSetAsDefault: boolean;
36
  variantNames: string[];
37
  portalContainer: VariantManagementPropTypes['portalContainer'];
38
  saveViewInputProps?: Omit<InputPropTypes, 'value'>;
39
  onSaveViewCancel?: VariantManagementPropTypes['onSaveViewCancel'];
140✔
40
}
41

42
export const SaveViewDialog = (props: SaveViewDialogPropTypes) => {
277✔
43
  const {
44
    onAfterClose,
45
    handleSave,
46
    selectedVariant,
47
    showShare,
48
    showApplyAutomatically,
49
    showSetAsDefault,
50
    variantNames,
51
    portalContainer,
52
    saveViewInputProps,
53
    onSaveViewCancel
54
  } = props;
598✔
55
  const saveViewDialogRef = useRef<DialogDomRef | null>(null);
598✔
56
  const inputRef = useRef(undefined);
598✔
57
  const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
598✔
58
  useStylesheet(styleData, 'SaveViewDialog');
598✔
59
  const uniqueId = useIsomorphicId();
598✔
60

61
  const cancelText = i18nBundle.getText(CANCEL);
598✔
62
  const saveText = i18nBundle.getText(SAVE);
598✔
63
  const headingText = i18nBundle.getText(SAVE_VIEW);
598✔
64
  const defaultCbLabel = i18nBundle.getText(SET_AS_DEFAULT);
598✔
65
  const publicCbLabel = i18nBundle.getText(PUBLIC);
598✔
66
  const applyAutomaticallyCbLabel = i18nBundle.getText(APPLY_AUTOMATICALLY);
598✔
67
  const inputLabelText = i18nBundle.getText(VIEW);
598✔
68
  const errorTextAlreadyExists = i18nBundle.getText(VARIANT_MANAGEMENT_ERROR_DUPLICATE);
598✔
69
  const errorTextEmpty = i18nBundle.getText(SPECIFY_VIEW_NAME);
598✔
70

71
  const [isDefault, setDefault] = useState(selectedVariant.isDefault);
598✔
72
  const [isPublic, setPublic] = useState(selectedVariant.global);
598✔
73
  const [applyAutomatically, setApplyAutomatically] = useState(selectedVariant.applyAutomatically);
598✔
74
  const [variantName, setVariantName] = useState(selectedVariant.children);
598✔
75
  const [variantNameInvalid, setVariantNameInvalid] = useState<string | boolean>(false);
598!
76
  const [isInvalid, setIsInvalid] = useState(false);
598✔
77

78
  const handleInputChange = (e) => {
598✔
79
    if (typeof saveViewInputProps?.onInput === 'function') {
303✔
80
      saveViewInputProps.onInput(e);
75!
81
    }
82
    const trimmedValue = trimAndRemoveSpaces(e.target.value);
303!
83
    setVariantName(trimmedValue);
303✔
84
    if (variantNames.includes(trimmedValue)) {
303!
85
      setVariantNameInvalid(errorTextAlreadyExists);
6✔
86
    } else if (trimmedValue.length === 0) {
297✔
87
      setVariantNameInvalid(errorTextEmpty);
33✔
88
    } else if (e.isInvalid) {
264✔
89
      setIsInvalid(true);
45✔
90
    } else {
91
      setVariantNameInvalid(false);
219✔
92
      setIsInvalid(false);
219✔
93
    }
×
94
  };
95

96
  const onSave = (e) => {
598!
97
    if (variantNames.includes(variantName)) {
36!
98
      setVariantNameInvalid(errorTextAlreadyExists);
×
UNCOV
99
      inputRef.current?.focus();
×
100
    } else if (variantName.length === 0) {
36!
101
      setVariantNameInvalid(errorTextEmpty);
UNCOV
102
      inputRef.current?.focus();
×
103
    } else if (isInvalid) {
36✔
104
      inputRef.current?.focus();
15✔
105
    } else {
106
      setVariantNameInvalid(false);
21✔
107
      handleSave(e, { ...selectedVariant, children: variantName, isDefault, global: isPublic, applyAutomatically });
21✔
108
    }
×
109
  };
110

111
  const handleClose = (e) => {
598✔
112
    if (e.detail.escPressed) {
51✔
113
      handleCancel(e);
15✔
114
    } else {
115
      onAfterClose(e);
36✔
116
    }
×
117
  };
118

119
  const handleCancel = (e) => {
598✔
120
    if (typeof onSaveViewCancel === 'function') {
36✔
121
      onSaveViewCancel(
30✔
122
        enrichEventWithDetails(e, {
123
          ...selectedVariant,
124
          children: variantName,
125
          isDefault,
126
          global: isPublic,
127
          applyAutomatically,
128
          isInvalid
129
        })
130
      );
131
    }
132
    setIsInvalid(false);
36✔
133
    inputRef.current.isInvalid = false;
36✔
134
    saveViewDialogRef.current.open = false;
36✔
135
  };
136

137
  const handleChangeDefault = (e) => {
598✔
138
    setDefault(e.target.checked);
6✔
139
  };
140
  const handleChangePublic = (e) => {
598✔
141
    setPublic(e.target.checked);
6✔
142
  };
143
  const handleChangeApplyAutomatically = (e) => {
598✔
144
    setApplyAutomatically(e.target.checked);
21✔
145
  };
146

147
  const canRenderPortal = useCanRenderPortal();
598✔
148
  if (!canRenderPortal) {
598✔
149
    return null;
71✔
150
  }
151

152
  return createPortal(
527✔
153
    <Dialog
154
      open
155
      className={classNames.dialog}
156
      ref={saveViewDialogRef}
157
      headerText={headingText}
158
      onClose={onAfterClose}
159
      onBeforeClose={handleClose}
160
      initialFocus={`view-${uniqueId}`}
161
      footer={
162
        <Bar
163
          design={BarDesign.Footer}
164
          endContent={
165
            <>
166
              <Button design={ButtonDesign.Emphasized} onClick={onSave}>
167
                {saveText}
168
              </Button>
169
              <Button design={ButtonDesign.Transparent} onClick={handleCancel}>
170
                {cancelText}
171
              </Button>
172
            </>
173
          }
174
        />
175
      }
176
    >
×
177
      <FlexBox direction={FlexBoxDirection.Column} alignItems={FlexBoxAlignItems.Start}>
×
178
        <Label for={`view-${uniqueId}`} showColon>
179
          {inputLabelText}
180
        </Label>
181
        <Input
182
          accessibleName={inputLabelText}
183
          ref={inputRef}
184
          {...saveViewInputProps}
185
          valueState={saveViewInputProps?.valueState ?? (!variantNameInvalid ? 'None' : 'Negative')}
1,371✔
186
          valueStateMessage={saveViewInputProps?.valueStateMessage ?? <div>{variantNameInvalid}</div>}
949✔
187
          className={clsx(classNames.input, saveViewInputProps?.className)}
188
          id={`view-${uniqueId}`}
×
189
          value={variantName}
×
190
          onInput={handleInputChange}
×
191
        />
192
        <FlexBox
193
          alignItems={FlexBoxAlignItems.Start}
194
          direction={FlexBoxDirection.Column}
195
          className={classNames.checkBoxesContainer}
196
        >
197
          {showSetAsDefault && <CheckBox onChange={handleChangeDefault} text={defaultCbLabel} checked={isDefault} />}
1,047✔
198
          {showShare && <CheckBox onChange={handleChangePublic} text={publicCbLabel} checked={isPublic} />}
1,047✔
199
          {showApplyAutomatically && (
1,047✔
200
            <CheckBox
201
              onChange={handleChangeApplyAutomatically}
202
              text={applyAutomaticallyCbLabel}
203
              checked={applyAutomatically}
204
            />
205
          )}
206
        </FlexBox>
207
      </FlexBox>
208
    </Dialog>,
209
    portalContainer ?? document.body
1,054✔
210
  );
211
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc