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

SAP / ui5-webcomponents-react / 9599598536

20 Jun 2024 02:47PM CUT coverage: 88.058% (+0.3%) from 87.716%
9599598536

Pull #5940

github

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

2877 of 4123 branches covered (69.78%)

17 of 18 new or added lines in 6 files covered. (94.44%)

7 existing lines in 3 files now uncovered.

5184 of 5887 relevant lines covered (88.06%)

69945.23 hits per line

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

99.42
/packages/main/src/components/FilterBar/FilterDialog.tsx
1
import BarDesign from '@ui5/webcomponents/dist/types/BarDesign.js';
2
import ButtonDesign from '@ui5/webcomponents/dist/types/ButtonDesign.js';
3
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel.js';
4
import TableMode from '@ui5/webcomponents-compat/dist/types/TableMode.js';
5
import group2Icon from '@ui5/webcomponents-icons/dist/group-2.js';
6
import listIcon from '@ui5/webcomponents-icons/dist/list.js';
7
import searchIcon from '@ui5/webcomponents-icons/dist/search.js';
8
import { enrichEventWithDetails, useI18nBundle, useIsomorphicId, useStylesheet } from '@ui5/webcomponents-react-base';
9
import type { Dispatch, MutableRefObject, ReactElement, SetStateAction } from 'react';
10
import { Children, cloneElement, useEffect, useReducer, useRef, useState } from 'react';
11
import { createPortal } from 'react-dom';
12
import {
13
  FlexBoxDirection,
14
  FlexBoxJustifyContent,
15
  MessageBoxActions,
16
  MessageBoxTypes,
17
  ToolbarStyle
18
} from '../../enums/index.js';
19
import {
20
  ACTIVE,
21
  ALL,
22
  BASIC,
23
  CANCEL,
24
  FIELDS_BY_ATTRIBUTE,
25
  FILTER_DIALOG_RESET_WARNING,
26
  FILTER,
27
  FILTERS,
28
  GROUP_VIEW,
29
  HIDE_VALUES,
30
  LIST_VIEW,
31
  MANDATORY,
32
  OK,
33
  RESET,
34
  SEARCH_FOR_FILTERS,
35
  SHOW_VALUES,
36
  VISIBLE,
37
  VISIBLE_AND_ACTIVE
38
} from '../../i18n/i18n-defaults.js';
39
import { addCustomCSSWithScoping } from '../../internal/addCustomCSSWithScoping.js';
40
import type { OnReorderParams } from '../../internal/FilterBarDialogContext.js';
41
import { FilterBarDialogContext } from '../../internal/FilterBarDialogContext.js';
42
import { useCanRenderPortal } from '../../internal/ssr.js';
43
import { stopPropagation } from '../../internal/stopPropagation.js';
44
import type { Ui5CustomEvent } from '../../types/index.js';
45
import type { DialogDomRef, SegmentedButtonPropTypes, TableDomRef, TableRowDomRef } from '../../webComponents/index.js';
46
import {
47
  Bar,
48
  Button,
49
  Dialog,
50
  Icon,
51
  Input,
52
  Option,
53
  Panel,
54
  SegmentedButton,
55
  SegmentedButtonItem,
56
  Select,
57
  Table,
58
  TableColumn,
59
  Title
60
} from '../../webComponents/index.js';
61
import type { FilterGroupItemInternalProps } from '../FilterGroupItem/types.js';
62
import { FlexBox } from '../FlexBox/index.js';
63
import { MessageBox } from '../MessageBox/index.js';
64
import { Toolbar } from '../Toolbar/index.js';
65
import { ToolbarSpacer } from '../ToolbarSpacer/index.js';
66
import { classNames, styleData } from './FilterBarDialog.module.css.js';
67
import type { FilterBarPropTypes } from './types.js';
68
import { filterValue, syncRef } from './utils.js';
69

70
addCustomCSSWithScoping(
277✔
71
  'ui5-table',
72
  `
140✔
73
/* hide table header of panel table */
74
:host([data-component-name="FilterBarDialogPanelTable"]) thead {
75
  visibility: collapse;
76
}
77

78
/* don't display border of panel table */
79
:host([data-component-name="FilterBarDialogPanelTable"]) table {
80
  border-collapse: unset;
81
}
140✔
82

83
/* don't allow table cells to grow
84
todo: FilterBarDialogPanelTable
85
*/
86
:host([data-component-name="FilterBarDialogTable"]) table {
87
  table-layout: fixed;
88
}
89

90
/* prevent focus by click on group-view thead */
91
:host([data-component-name="FilterBarDialogTable"][tabindex="-1"]) thead > tr {
140✔
92
  pointer-events: none;
93
}
94

95
:host([data-component-name="FilterBarDialogPanelTable"]) .ui5-table-root {
×
96
  border-bottom: none;
97
}
98
/* don't display select all checkbox */
99
:host([data-component-name="FilterBarDialogTable"]) thead th.ui5-table-select-all-column [ui5-checkbox] {
100
 visibility: hidden;
101
}
102

103
:host([data-component-name="FilterBarDialogPanelTable"]) thead th.ui5-table-select-all-column {
×
104
 display: none;
105
}
106
 `
107
);
108

109
type ActiveFilterAttributes = 'all' | 'visible' | 'active' | 'visibleAndActive' | 'mandatory';
110
const getActiveFilters = (
277✔
111
  activeFilterAttribute: ActiveFilterAttributes,
140✔
112
  filter: ReactElement<FilterGroupItemInternalProps>
113
) => {
114
  switch (activeFilterAttribute) {
120!
115
    case 'all':
116
      return true;
120✔
117
    case 'visible':
118
      return filter.props?.visibleInFilterBar;
119
    case 'active':
120
      return filter.props?.active;
121
    case 'visibleAndActive':
122
      return filter.props?.visibleInFilterBar && filter.props?.active;
×
123
    case 'mandatory':
124
      return filter.props?.required;
125
    default:
126
      return true;
127
  }
128
};
129

130
const compareObjects = (firstObj, secondObj) =>
277✔
131
  Object.keys(firstObj).find((first) =>
112✔
132
    Object.keys(secondObj).every((second) => firstObj[second] !== secondObj[first])
168✔
133
  );
134

135
interface FilterDialogPropTypes {
136
  filterBarRefs: any;
137
  open: boolean;
138
  handleDialogClose: (event: Ui5CustomEvent<DialogDomRef>) => void;
139
  children: ReactElement<FilterGroupItemInternalProps>[];
140
  showRestoreButton: boolean;
140✔
141
  handleRestoreFilters: (e, source, filterElements) => void;
142
  handleDialogSave: (e, newRefs, updatedToggledFilters, orderedChildren) => void;
143
  handleSearchValueChange: Dispatch<SetStateAction<string>>;
144
  handleSelectionChange?: (
145
    event: Ui5CustomEvent<
146
      TableDomRef,
147
      { element: TableRowDomRef; checked: boolean; selectedRows: unknown[]; previouslySelectedRows: unknown[] }
148
    >
149
  ) => void;
150
  handleDialogSearch?: (event: CustomEvent<{ value: string; element: HTMLElement }>) => void;
151
  handleDialogCancel?: (event: Ui5CustomEvent<HTMLElement>) => void;
152
  portalContainer: Element;
153
  onAfterFiltersDialogOpen: (event: Ui5CustomEvent<DialogDomRef>) => void;
154
  dialogRef: MutableRefObject<DialogDomRef>;
155
  enableReordering?: FilterBarPropTypes['enableReordering'];
156
  isPhone?: boolean;
157
}
158

159
export const FilterDialog = (props: FilterDialogPropTypes) => {
277✔
160
  const {
161
    filterBarRefs,
162
    open,
163
    handleDialogClose,
164
    children,
165
    showRestoreButton,
166
    handleRestoreFilters,
167
    handleDialogSave,
168
    handleSelectionChange,
169
    handleDialogSearch,
170
    handleDialogCancel,
171
    onAfterFiltersDialogOpen,
172
    portalContainer,
173
    dialogRef,
174
    enableReordering,
175
    isPhone
176
  } = props;
853✔
177
  useStylesheet(styleData, 'FilterBarDialog');
853✔
178
  const uniqueId = useIsomorphicId();
853✔
179
  const [searchString, setSearchString] = useState('');
853✔
180
  const [toggledFilters, setToggledFilters] = useState({});
853✔
181
  const dialogRefs = useRef({});
853!
182
  const dialogSearchRef = useRef(null);
853✔
183
  const [showValues, toggleValues] = useReducer((prev) => !prev, false);
853✔
184
  const [messageBoxOpen, setMessageBoxOpen] = useState(false);
853✔
185

186
  const [forceRequired, setForceRequired] = useState<undefined | TableRowDomRef>();
853✔
187
  const [showBtnsOnHover, setShowBtnsOnHover] = useState(true);
853✔
188
  const [isListView, setIsListView] = useState(true);
853✔
189
  const [filteredAttribute, setFilteredAttribute] = useState<ActiveFilterAttributes>('all');
853✔
190
  const [currentReorderedItem, setCurrentReorderedItem] = useState<OnReorderParams | Record<string, never>>({});
853✔
191
  const tableRef = useRef(null);
853✔
192
  const okBtnRef = useRef(null);
853✔
193
  const handleReorder = (e: OnReorderParams) => {
853✔
194
    setCurrentReorderedItem(e);
50✔
195
  };
196

197
  const prevOderId = useRef(undefined);
853✔
198
  const handleFocusFallback = () => {
853✔
199
    const orderId = currentReorderedItem?.target?.dataset.orderId;
65✔
200
    if (orderId && tableRef.current && orderId !== prevOderId.current) {
65✔
201
      // we have to retrigger the internal item navigation logic after reordering,
202
      // otherwise keyboard nav and general focus handling is not working properly
203
      setTimeout(() => {
50✔
204
        const itemNav = tableRef.current._itemNavigation;
50✔
205
        itemNav._getItems = () => Array.from(tableRef.current.querySelectorAll('[ui5-table-row]'));
680✔
206
        itemNav.setCurrentItem(tableRef.current.querySelector(`[data-order-id="${orderId}"]`));
50✔
207
      });
208
      prevOderId.current = orderId;
50✔
209
    }
210
  };
211

212
  const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
853✔
213

214
  const basicText = i18nBundle.getText(BASIC);
853✔
215
  const cancelText = i18nBundle.getText(CANCEL);
853!
216
  const okText = i18nBundle.getText(OK);
853✔
217
  const searchForFiltersText = i18nBundle.getText(SEARCH_FOR_FILTERS);
853✔
218
  const filtersTitle = i18nBundle.getText(FILTERS);
853✔
219
  const resetText = i18nBundle.getText(RESET);
853✔
220
  const allText = i18nBundle.getText(ALL);
853✔
221
  const activeText = i18nBundle.getText(ACTIVE);
853!
222
  const visibleText = i18nBundle.getText(VISIBLE);
853✔
223
  const visibleAndActiveText = i18nBundle.getText(VISIBLE_AND_ACTIVE);
853✔
224
  const mandatoryText = i18nBundle.getText(MANDATORY);
853✔
225
  const listViewText = i18nBundle.getText(LIST_VIEW);
853✔
226
  const groupViewText = i18nBundle.getText(GROUP_VIEW);
853✔
227
  const showValuesText = i18nBundle.getText(SHOW_VALUES);
853✔
228
  const hideValuesText = i18nBundle.getText(HIDE_VALUES);
853✔
229
  const filterText = i18nBundle.getText(FILTER);
853!
230
  const fieldsByAttributeText = i18nBundle.getText(FIELDS_BY_ATTRIBUTE);
853✔
231

×
232
  const visibleChildren = () =>
853✔
233
    children.filter((item) => {
131✔
234
      return !!item?.props && (typeof item.props.visible === 'undefined' || item?.props?.visible);
433✔
235
    });
236

237
  const [orderedChildren, setOrderedChildren] = useState([]);
853✔
238

239
  useEffect(() => {
853✔
240
    if (children.length) {
112!
241
      setOrderedChildren(visibleChildren());
112!
242
    }
243
  }, [children]);
244

245
  const renderChildren = () => {
853!
246
    const searchStringLower = searchString.toLowerCase();
741✔
247
    const filteredChildren =
248
      searchStringLower.length > 0 || filteredAttribute !== 'all'
741✔
249
        ? orderedChildren.filter(
250
            (item) =>
321✔
251
              (searchStringLower === '' || item.props.label?.toLowerCase().includes(searchStringLower)) &&
252
              getActiveFilters(filteredAttribute, item)
253
          )
254
        : orderedChildren;
×
255

256
    return filteredChildren.map((child, index) => {
741✔
257
      const filterBarItemRef = filterBarRefs.current[child.key];
2,640✔
258
      let isSelected =
×
259
        child.props.visibleInFilterBar || child.props.required || child.type.displayName !== 'FilterGroupItem';
2,640✔
260
      if (toggledFilters.hasOwnProperty(child.key)) {
2,640✔
261
        isSelected = toggledFilters[child.key];
308✔
262
      }
263

264
      const filterItemProps = filterBarItemRef ? filterValue(filterBarItemRef, child) : {};
2,640!
265

266
      return cloneElement<FilterGroupItemInternalProps>(child, {
2,640✔
267
        'data-selected': isSelected,
268
        'data-react-key': child.key,
269
        'data-index': index,
×
270
        children: {
271
          ...child.props.children,
272
          props: {
273
            ...(child.props.children.props || {}),
2,640!
274
            ...filterItemProps
275
          },
×
276
          ref: (node) => {
277
            if (node) {
×
278
              dialogRefs.current[child.key] = node;
UNCOV
279
              syncRef(child.props.children.ref, node);
×
280
            }
281
          }
282
        }
×
283
      });
284
    });
285
  };
286

287
  const handleSearch = (e) => {
853✔
288
    if (handleDialogSearch) {
138✔
289
      handleDialogSearch(enrichEventWithDetails(e, { value: e.target.value, element: e.target }));
99!
290
    }
291
    setSearchString(e.target.value);
138✔
292
  };
293
  const handleSave = (e) => {
853✔
294
    const orderedChildrenIds = enableReordering ? orderedChildren.map((child) => child.props.orderId) : [];
33✔
295
    handleDialogSave(e, dialogRefs.current, toggledFilters, orderedChildrenIds);
33✔
296
  };
297

298
  const handleClose = (e) => {
853✔
299
    setToggledFilters({});
14✔
300
    stopPropagation(e);
14✔
301
    if (handleDialogCancel) {
14✔
302
      handleDialogCancel(e);
14✔
303
    }
304
    handleDialogClose(e);
14!
305
  };
306

307
  const handleCancel = (e) => {
853✔
308
    if (handleDialogCancel) {
14✔
309
      handleDialogCancel(e);
14✔
310
    }
311
    handleDialogClose(e);
14✔
312
  };
313

314
  const handleRestore = () => {
853✔
315
    setMessageBoxOpen(true);
47!
316
  };
317
  const handleViewChange: SegmentedButtonPropTypes['onSelectionChange'] = (e) => {
853✔
318
    const selectedItem = e.detail.selectedItems.at(0);
20!
319
    setIsListView(selectedItem.dataset.id === 'list');
20✔
320
  };
×
321

322
  const handleMessageBoxClose = (e) => {
853✔
323
    if (e.detail.action === 'OK') {
47✔
324
      setToggledFilters({});
19✔
325
      setOrderedChildren(visibleChildren());
19✔
326
      handleRestoreFilters(e, 'dialog', { filters: Array.from(dialogRef.current.querySelectorAll('ui5-table-row')) });
19✔
327
    }
328
    setMessageBoxOpen(false);
47!
329
    okBtnRef.current.focus();
47✔
330
  };
331

332
  const [updatedIndex, setUpdatedIndex] = useState(undefined);
853✔
333
  useEffect(() => {
853✔
334
    if (currentReorderedItem?.index != null) {
162✔
335
      setOrderedChildren((prev: any[]) => {
50✔
336
        const { index, direction } = currentReorderedItem;
50!
337
        switch (direction) {
50✔
338
          case 'up':
339
            if (index > 0) {
10✔
340
              setUpdatedIndex(index - 1);
10✔
341
              const temp = prev[index];
10✔
342
              prev[index] = prev[index - 1];
10✔
343
              prev[index - 1] = temp;
10!
344
            }
345
            break;
10✔
346
          case 'down':
347
            if (index < prev.length - 1) {
10✔
348
              setUpdatedIndex(index + 1);
10✔
349
              const temp = prev[index];
10✔
350
              prev[index] = prev[index + 1];
10✔
351
              prev[index + 1] = temp;
10✔
352
            }
353
            break;
10✔
354
          case 'top':
355
            if (index > 0) {
10✔
356
              setUpdatedIndex(0);
10✔
357
              const item = prev.splice(index, 1)[0];
10!
358
              prev.unshift(item);
10✔
359
            }
360
            break;
10✔
361
          case 'bottom':
362
            if (index < prev.length - 1) {
20✔
363
              setUpdatedIndex(prev.length - 1);
20✔
364
              const item = prev.splice(index, 1)[0];
20✔
365
              prev.push(item);
20✔
366
            }
367
            break;
20!
368
        }
369
        return [...prev];
50✔
370
      });
371
      void currentReorderedItem.target.focus();
50✔
372
    }
373
  }, [currentReorderedItem]);
374

375
  useEffect(() => {
853✔
376
    if (updatedIndex != null) {
157✔
377
      prevOderId.current = undefined;
45✔
378
    }
379
  }, [updatedIndex]);
380

381
  const handleAttributeFilterChange = (e) => {
853!
382
    setFilteredAttribute(e.detail.selectedOption.dataset.id);
383
  };
384

385
  const handleCheckBoxChange = (e) => {
853!
386
    if (e.target.hasAttribute('ui5-table')) {
112✔
387
      // preventDefault should only be called if the target is the table, otherwise bubbled `selection-change` events
388
      // also prevent their default behavior (e.g. the event of the MultiComboBox)
×
389
      e.preventDefault();
112✔
390
      const prevRowsByKey = e.detail.previouslySelectedRows.reduce(
112✔
391
        (acc, prevSelRow) => ({ ...acc, [prevSelRow.dataset.reactKey]: prevSelRow }),
280✔
392
        {}
393
      );
×
394
      const rowsByKey = e.detail.selectedRows.reduce(
112✔
395
        (acc, selRow) => ({ ...acc, [selRow.dataset.reactKey]: selRow }),
168✔
396
        {}
397
      );
398

399
      const changedRowKey =
400
        e.detail.previouslySelectedRows > e.detail.selectedRows
112!
401
          ? compareObjects(prevRowsByKey, rowsByKey)
402
          : compareObjects(rowsByKey, prevRowsByKey);
403

404
      const element = rowsByKey[changedRowKey] || prevRowsByKey[changedRowKey];
112!
405

406
      // todo: workaround until specific rows can be disabled
407
      if (element.dataset?.required === 'true') {
112!
408
        setForceRequired(element);
409
        return;
410
      }
411

×
412
      if (typeof handleSelectionChange === 'function') {
112✔
413
        handleSelectionChange(enrichEventWithDetails(e, { element, checked: element.selected }));
112✔
414
      }
415

416
      setToggledFilters((prev) => {
112✔
417
        return { ...prev, [changedRowKey]: element.selected };
112✔
418
      });
×
419
    }
×
420
  };
421

422
  useEffect(() => {
853✔
423
    if (forceRequired) {
112!
424
      forceRequired.setAttribute('selected', 'true');
425
      setForceRequired(undefined);
426
    }
427
  }, [forceRequired]);
×
428

429
  const canRenderPortal = useCanRenderPortal();
853✔
430
  if (!canRenderPortal) {
853✔
431
    return null;
112✔
432
  }
×
433

434
  const renderGroups = () => {
741!
435
    const groups = {};
74✔
436
    Children.forEach(renderChildren(), (child) => {
74✔
437
      const childGroups = child.props.groupName ?? 'default';
132✔
438
      if (groups[childGroups]) {
132✔
439
        groups[childGroups].push(child);
22✔
440
      } else {
441
        groups[childGroups] = [child];
110✔
442
      }
443
    });
444

445
    const filterGroups = Object.keys(groups)
74✔
446
      .sort((x, y) => (x === 'default' ? -1 : y === 'role' ? 1 : 0))
81!
447
      .map((item, index) => {
448
        return (
110✔
449
          <Panel
×
450
            headerText={item === 'default' ? basicText : item}
110✔
451
            className={classNames.groupPanel}
452
            key={`${item === 'default' ? basicText : item}${index}`}
110✔
453
          >
454
            <Table
455
              mode={TableMode.MultiSelect}
456
              data-component-name="FilterBarDialogPanelTable"
457
              onSelectionChange={handleCheckBoxChange}
458
            >
459
              {groups[item]}
460
            </Table>
461
          </Panel>
462
        );
463
      });
464
    return filterGroups;
74✔
465
  };
466

467
  const currentReorderedItemOrderId = currentReorderedItem?.orderId;
741✔
468

469
  return (
741✔
470
    <FilterBarDialogContext.Provider
471
      value={{
472
        isFilterInDialog: true,
473
        enableReordering,
474
        onReorder: handleReorder,
475
        isListView,
476
        withValues: showValues,
477
        handleFocusFallback,
478
        showBtnsOnHover,
479
        setShowBtnsOnHover,
480
        currentReorderedItemOrderId
481
      }}
482
    >
483
      {createPortal(
484
        <Dialog
485
          open={open}
486
          ref={dialogRef}
487
          data-component-name="FilterBarDialog"
488
          data-is-phone={isPhone}
489
          onClose={handleClose}
490
          onOpen={onAfterFiltersDialogOpen}
491
          resizable
492
          draggable
493
          className={classNames.dialogComponent}
494
          preventFocusRestore
495
          initialFocus={`${uniqueId}-fb-dialog-search`}
496
          header={
497
            <Bar
498
              design={BarDesign.Header}
499
              startContent={
×
500
                <Title level={TitleLevel.H4} title={filtersTitle}>
501
                  {filtersTitle}
502
                </Title>
503
              }
504
              endContent={
505
                showRestoreButton && (
1,259✔
506
                  <Button design={ButtonDesign.Transparent} onClick={handleRestore}>
507
                    {resetText}
508
                  </Button>
509
                )
510
              }
511
            />
512
          }
513
          footer={
514
            <Bar
515
              design={BarDesign.Footer}
516
              endContent={
517
                <FlexBox justifyContent={FlexBoxJustifyContent.End} className={classNames.footer}>
518
                  <Button
519
                    ref={okBtnRef}
520
                    onClick={handleSave}
521
                    data-component-name="FilterBarDialogSaveBtn"
522
                    design={ButtonDesign.Emphasized}
523
                  >
524
                    {okText}
525
                  </Button>
526
                  <Button
527
                    design={ButtonDesign.Transparent}
528
                    onClick={handleCancel}
529
                    data-component-name="FilterBarDialogCancelBtn"
530
                  >
531
                    {cancelText}
532
                  </Button>
533
                </FlexBox>
534
              }
535
            />
536
          }
537
        >
538
          <FlexBox direction={FlexBoxDirection.Column} className={classNames.subheaderContainer}>
539
            <Toolbar className={classNames.subheader} toolbarStyle={ToolbarStyle.Clear}>
540
              <Select
541
                onChange={handleAttributeFilterChange}
542
                title={fieldsByAttributeText}
543
                accessibleName={fieldsByAttributeText}
544
              >
545
                <Option selected={filteredAttribute === 'all'} data-id="all">
546
                  {allText}
547
                </Option>
548
                <Option selected={filteredAttribute === 'visible'} data-id="visible">
549
                  {visibleText}
550
                </Option>
551
                <Option selected={filteredAttribute === 'active'} data-id="active">
552
                  {activeText}
553
                </Option>
554
                <Option selected={filteredAttribute === 'visibleAndActive'} data-id="visibleAndActive">
555
                  {visibleAndActiveText}
556
                </Option>
557
                <Option selected={filteredAttribute === 'mandatory'} data-id="mandatory">
×
558
                  {mandatoryText}
559
                </Option>
560
              </Select>
561
              <ToolbarSpacer />
562
              <Button design={ButtonDesign.Transparent} onClick={toggleValues} aria-live="polite">
563
                {showValues ? hideValuesText : showValuesText}
741✔
564
              </Button>
565
              <SegmentedButton onSelectionChange={handleViewChange}>
566
                <SegmentedButtonItem
567
                  icon={listIcon}
568
                  data-id="list"
569
                  selected={isListView}
570
                  accessibleName={listViewText}
571
                />
572
                <SegmentedButtonItem
573
                  icon={group2Icon}
574
                  data-id="group"
575
                  selected={!isListView}
576
                  accessibleName={groupViewText}
577
                />
578
              </SegmentedButton>
579
            </Toolbar>
580
            <FlexBox className={classNames.searchInputContainer}>
581
              <Input
582
                id={`${uniqueId}-fb-dialog-search`}
583
                noTypeahead
584
                placeholder={searchForFiltersText}
585
                onInput={handleSearch}
586
                showClearIcon
587
                icon={<Icon name={searchIcon} />}
588
                ref={dialogSearchRef}
589
                className={classNames.searchInput}
590
                data-component-name="FilterBarDialogSearchInput"
591
              />
592
            </FlexBox>
×
593
          </FlexBox>
×
594
          <Table
595
            ref={tableRef}
596
            data-component-name="FilterBarDialogTable"
597
            hideNoData={!isListView}
598
            mode={TableMode.MultiSelect}
599
            onSelectionChange={handleCheckBoxChange}
600
            tabIndex={!isListView ? -1 : undefined}
741✔
601
            columns={
602
              <>
×
603
                <TableColumn>{filterText}</TableColumn>
604
                {!showValues && <TableColumn className={classNames.tHactive}>{activeText}</TableColumn>}
1,216✔
605
              </>
606
            }
×
607
          >
608
            {isListView && renderChildren()}
1,408!
609
          </Table>
610
          {!isListView && renderGroups()}
815!
611
        </Dialog>,
612
        portalContainer ?? document.body
1,482!
613
      )}
614
      {showRestoreButton &&
1,306✔
615
        messageBoxOpen &&
616
        createPortal(
617
          <MessageBox
618
            open
619
            type={MessageBoxTypes.Warning}
620
            actions={[MessageBoxActions.OK, MessageBoxActions.Cancel]}
621
            onClose={handleMessageBoxClose}
622
            data-component-name="FilterBarDialogResetMessageBox"
623
          >
624
            {i18nBundle.getText(FILTER_DIALOG_RESET_WARNING)}
×
625
          </MessageBox>,
626
          portalContainer ?? document.body
94✔
627
        )}
628
    </FilterBarDialogContext.Provider>
629
  );
630
};
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