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

SAP / ui5-webcomponents-react / 14304969491

07 Apr 2025 08:53AM CUT coverage: 87.54% (+0.08%) from 87.46%
14304969491

Pull #7187

github

web-flow
Merge f9635f7ca into 8d652b4c7
Pull Request #7187: feat(ObjectPage): allow customizing `role` of `footerArea` container

2966 of 3932 branches covered (75.43%)

5185 of 5923 relevant lines covered (87.54%)

84562.43 hits per line

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

93.15
/packages/main/src/components/AnalyticalTable/defaults/Column/ColumnHeaderModal.tsx
1
import IconMode from '@ui5/webcomponents/dist/types/IconMode.js';
2
import ListItemType from '@ui5/webcomponents/dist/types/ListItemType.js';
3
import PopoverHorizontalAlign from '@ui5/webcomponents/dist/types/PopoverHorizontalAlign.js';
4
import PopoverPlacement from '@ui5/webcomponents/dist/types/PopoverPlacement.js';
5
import { getScopedVarName } from '@ui5/webcomponents-base/dist/CustomElementsScope.js';
6
import iconDecline from '@ui5/webcomponents-icons/dist/decline.js';
7
import iconFilter from '@ui5/webcomponents-icons/dist/filter.js';
8
import iconGroup from '@ui5/webcomponents-icons/dist/group-2.js';
9
import iconSortAscending from '@ui5/webcomponents-icons/dist/sort-ascending.js';
10
import iconSortDescending from '@ui5/webcomponents-icons/dist/sort-descending.js';
11
import { enrichEventWithDetails, useI18nBundle } from '@ui5/webcomponents-react-base';
12
import { useEffect, useMemo, useRef } from 'react';
13
import { FlexBoxAlignItems } from '../../../../enums/FlexBoxAlignItems.js';
14
import { TextAlign } from '../../../../enums/TextAlign.js';
15
import {
16
  CLEAR_SORTING,
17
  FILTER,
18
  GROUP,
19
  SORT_ASCENDING,
20
  SORT_DESCENDING,
21
  UNGROUP
22
} from '../../../../i18n/i18n-defaults.js';
23
import { stopPropagation } from '../../../../internal/stopPropagation.js';
24
import { getUi5TagWithSuffix } from '../../../../internal/utils.js';
25
import { Icon } from '../../../../webComponents/Icon/index.js';
26
import { List } from '../../../../webComponents/List/index.js';
27
import { ListItemCustom } from '../../../../webComponents/ListItemCustom/index.js';
28
import { ListItemStandard } from '../../../../webComponents/ListItemStandard/index.js';
29
import type { PopoverDomRef } from '../../../../webComponents/Popover/index.js';
30
import { Popover } from '../../../../webComponents/Popover/index.js';
31
import { Text } from '../../../../webComponents/Text/index.js';
32
import { FlexBox } from '../../../FlexBox/index.js';
33
import type { TableInstanceWithPopoverProps } from '../../types/index.js';
34

35
export const ColumnHeaderModal = (instance: TableInstanceWithPopoverProps) => {
427✔
36
  const { setOpen, openerRef } = instance.popoverProps;
5,608✔
37
  const { column, state, webComponentsReactProperties } = instance;
5,608✔
38
  const { isRtl, groupBy } = state;
5,608✔
39
  const { onGroup, onSort, classes: classNames } = webComponentsReactProperties;
5,608✔
40

41
  const showFilter = column.canFilter;
5,608✔
42
  const showGroup = column.canGroupBy;
5,608✔
43
  const showSort = column.canSort;
5,608✔
44

45
  const ref = useRef<PopoverDomRef>(null);
5,608✔
46
  const listRef = useRef(null);
5,608✔
47
  const { Filter } = column;
5,608✔
48

49
  const i18nBundle = useI18nBundle('@ui5/webcomponents-react');
5,608✔
50

51
  const clearSortingText = i18nBundle.getText(CLEAR_SORTING);
5,608✔
52
  const sortAscendingText = i18nBundle.getText(SORT_ASCENDING);
5,608✔
53
  const sortDescendingText = i18nBundle.getText(SORT_DESCENDING);
5,608✔
54
  const groupText = i18nBundle.getText(GROUP);
5,608✔
55
  const ungroupText = i18nBundle.getText(UNGROUP);
5,608✔
56
  const filterText = i18nBundle.getText(FILTER);
5,608✔
57

58
  const filterStyles = useMemo(() => {
5,608✔
59
    if (showFilter) {
1,556✔
60
      return {
732✔
61
        iconDimensions: `var(${getScopedVarName('--_ui5_list_item_icon_size')})`,
62
        fontSize: `var(${getScopedVarName('--_ui5_list_item_title_size')})`
63
      };
64
    }
65
  }, [showFilter]);
66

67
  const handleSort = (e) => {
5,608✔
68
    const sortType = e.detail.item.getAttribute('data-sort');
464✔
69

70
    switch (sortType) {
464✔
71
      case 'asc':
72
        column.toggleSortBy(false, !!column.enableMultiSort);
207✔
73
        if (typeof onSort === 'function') {
207✔
74
          onSort(
51✔
75
            enrichEventWithDetails(e, {
76
              column,
77
              sortDirection: sortType
78
            })
79
          );
80
        }
81
        break;
207✔
82
      case 'desc':
83
        column.toggleSortBy(true, !!column.enableMultiSort);
78✔
84
        if (typeof onSort === 'function') {
78✔
85
          onSort(
51✔
86
            enrichEventWithDetails(e, {
87
              column,
88
              sortDirection: sortType
89
            })
90
          );
91
        }
92
        break;
78✔
93
      case 'clear':
94
        column.clearSortBy();
78✔
95
        if (typeof onSort === 'function') {
78✔
96
          onSort(
51✔
97
            enrichEventWithDetails(e, {
98
              column,
99
              sortDirection: sortType
100
            })
101
          );
102
        }
103
        break;
78✔
104
      case 'group': {
105
        const willGroup = !column.isGrouped;
101✔
106
        column.toggleGroupBy(willGroup);
101✔
107
        let groupedColumns;
108
        if (willGroup) {
101✔
109
          groupedColumns = [...groupBy, column.id];
85✔
110
        } else {
111
          groupedColumns = groupBy.filter((group) => group !== column.id);
16✔
112
        }
113
        if (typeof onGroup === 'function') {
101✔
114
          onGroup(
12✔
115
            enrichEventWithDetails(e, {
116
              column,
117
              groupedColumns,
118
              isGrouped: willGroup
119
            })
120
          );
121
        }
122
        break;
101✔
123
      }
124
    }
125
    setOpen(false);
464✔
126
  };
127

128
  const isSortedAscending = column.isSorted && column.isSortedDesc === false;
5,608✔
129
  const isSortedDescending = column.isSorted && column.isSortedDesc === true;
5,608✔
130

131
  const onAfterClose = (e) => {
5,608✔
132
    stopPropagation(e);
776✔
133
    setOpen(false);
776✔
134
  };
135

136
  const onAfterOpen = () => {
5,608✔
137
    listRef.current?.children?.[0]?.focus();
605✔
138
  };
139

140
  const horizontalAlign = (() => {
5,608✔
141
    switch (column.hAlign) {
5,608!
142
      case TextAlign.Begin:
143
        return PopoverHorizontalAlign.Start;
×
144
      case TextAlign.End:
145
        return PopoverHorizontalAlign.End;
×
146
      case TextAlign.Left:
147
        return isRtl ? PopoverHorizontalAlign.End : PopoverHorizontalAlign.Start;
×
148
      case TextAlign.Right:
149
        return isRtl ? PopoverHorizontalAlign.Start : PopoverHorizontalAlign.End;
×
150
      case TextAlign.Center:
151
        return PopoverHorizontalAlign.Center;
×
152
      default:
153
        return PopoverHorizontalAlign.Start;
5,608✔
154
    }
155
  })();
156

157
  const handleCustomLiKeyDown = (e) => {
5,608✔
158
    if (e.key === 'Enter') {
208✔
159
      setOpen(false);
208✔
160
    }
161
  };
162

163
  const handleListKeyDown = (e) => {
5,608✔
164
    if (e.key !== 'Escape') {
208✔
165
      stopPropagation(e);
208✔
166
    }
167
  };
168

169
  useEffect(() => {
5,608✔
170
    if (open && ref.current && openerRef.current) {
1,556✔
171
      void customElements.whenDefined(getUi5TagWithSuffix('ui5-popover')).then(() => {
1,556✔
172
        ref.current.opener = openerRef.current;
1,556✔
173
        ref.current.open = true;
1,556✔
174
      });
175
    }
176
  }, [open]);
177

178
  return (
5,608✔
179
    <Popover
180
      hideArrow
181
      horizontalAlign={horizontalAlign}
182
      placement={PopoverPlacement.Bottom}
183
      ref={ref}
184
      className={classNames.popover}
185
      onClick={stopPropagation}
186
      onClose={onAfterClose}
187
      onOpen={onAfterOpen}
188
      data-component-name="ATHeaderPopover"
189
    >
190
      <List
191
        onItemClick={handleSort}
192
        ref={listRef}
193
        onKeyDown={handleListKeyDown}
194
        data-component-name="ATHeaderPopoverList"
195
      >
196
        {isSortedAscending && (
5,742✔
197
          <ListItemStandard type={ListItemType.Active} icon={iconDecline} data-sort="clear">
198
            {clearSortingText}
199
          </ListItemStandard>
200
        )}
201
        {showSort && !isSortedAscending && (
8,202✔
202
          <ListItemStandard type={ListItemType.Active} icon={iconSortAscending} data-sort="asc">
203
            {sortAscendingText}
204
          </ListItemStandard>
205
        )}
206
        {showSort && !isSortedDescending && (
8,058✔
207
          <ListItemStandard type={ListItemType.Active} icon={iconSortDescending} data-sort="desc">
208
            {sortDescendingText}
209
          </ListItemStandard>
210
        )}
211
        {isSortedDescending && (
5,886✔
212
          <ListItemStandard type={ListItemType.Active} icon={iconDecline} data-sort="clear">
213
            {clearSortingText}
214
          </ListItemStandard>
215
        )}
216
        {showFilter && (
10,044✔
217
          <ListItemCustom type={ListItemType.Inactive} onKeyDown={handleCustomLiKeyDown} accessibleName={filterText}>
218
            <FlexBox alignItems={FlexBoxAlignItems.Center}>
219
              <Icon
220
                name={iconFilter}
221
                className={classNames.filterIcon}
222
                mode={IconMode.Decorative}
223
                style={{
224
                  minWidth: filterStyles.iconDimensions,
225
                  minHeight: filterStyles.iconDimensions
226
                }}
227
              />
228
              <Text
229
                maxLines={1}
230
                className={classNames.filterText}
231
                style={{
232
                  fontSize: filterStyles.fontSize
233
                }}
234
              >
235
                {filterText}
236
              </Text>
237
              <Filter column={column} popoverRef={ref} />
238
            </FlexBox>
239
          </ListItemCustom>
240
        )}
241
        {showGroup && (
6,184✔
242
          <ListItemStandard type={ListItemType.Active} icon={iconGroup} data-sort={'group'}>
243
            {column.isGrouped ? ungroupText : groupText}
576✔
244
          </ListItemStandard>
245
        )}
246
      </List>
247
    </Popover>
248
  );
249
};
250
ColumnHeaderModal.displayName = 'ColumnHeaderModal';
427✔
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