@webitel/ui-datalist 26.8.7 → 26.8.9
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/package.json +1 -1
- package/src/modules/filter-presets/components/apply-preset/apply-preset-action.vue +16 -4
- package/src/modules/filter-presets/components/save-preset/save-preset-action.vue +18 -4
- package/src/modules/filters/components/column/column-filter-preview.vue +70 -0
- package/src/modules/filters/components/column/column-filter.vue +77 -0
- package/src/modules/filters/components/config/dynamic-view/dynamic-filter-config-form-value-input.vue +2 -0
- package/src/modules/filters/components/config/dynamic-view/dynamic-filter-config-form.vue +43 -5
- package/src/modules/filters/components/config/static-view/static-filter-field.vue +6 -21
- package/src/modules/filters/components/filters-actions-menu.vue +177 -0
- package/src/modules/filters/components/preview/dynamic-filter-preview.vue +5 -60
- package/src/modules/filters/components/table-filters-panel.vue +6 -28
- package/src/modules/filters/components/types/Filter.types.ts +5 -0
- package/src/modules/filters/composables/useColumnFilter.ts +116 -0
- package/src/modules/filters/composables/useFilterValueChange.ts +58 -0
- package/src/modules/filters/composables/useFilterValuePreview.ts +87 -0
- package/src/modules/filters/composables/useSelectedFilters.ts +64 -0
- package/src/modules/filters/index.ts +4 -0
- package/src/modules/filters/modules/filterConfig/components/_custom/type-extension-filter-value-field.vue +9 -5
- package/src/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-options/date-time-options-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/_shared/durations/duration-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/_shared/string-filter/string-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/agent/agent-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/amd-result/amd-result-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/call-direction/call-direction-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-assignee/case-assignee-filter-value-field.vue +4 -4
- package/src/modules/filters/modules/filterConfig/components/case-author/case-author-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-close-reason-groups/case-close-reason-groups-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/case-impacted/case-impacted-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-priority/case-priority-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-reporter/case-reporter-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-service/case-service-filter-value-field.vue +1 -32
- package/src/modules/filters/modules/filterConfig/components/case-sla/case-sla-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-sla-condition/case-sla-condition-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/case-source/case-source-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/case-status/case-status-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/contact/contact-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/contact-owner/contact-owner-filter-value-field.vue +3 -3
- package/src/modules/filters/modules/filterConfig/components/gateway/gateway-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/grantee/grantee-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/hangup-cause/hangup-cause-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/has-attachment/has-attachment-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/rated-by/rated-by-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/rating/rating-from-to-filter-value-field.vue +7 -4
- package/src/modules/filters/modules/filterConfig/components/score/score-from-to-filter-value-field.vue +4 -4
- package/src/modules/filters/modules/filterConfig/components/tag/tag-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/user/user-filter-value-field.vue +6 -3
- package/src/modules/filters/modules/filterConfig/components/variable/variable-filter-value-field.vue +6 -3
- package/src/modules/table/createTableStore.store.ts +24 -3
- package/src/modules/types/tableStore.types.ts +18 -1
- package/types/.tsbuildinfo +1 -1
- package/types/modules/filter-presets/components/apply-preset/apply-preset-action.vue.d.ts +15 -1
- package/types/modules/filter-presets/components/save-preset/save-preset-action.vue.d.ts +17 -1
- package/types/modules/filter-presets/stores/createFilterPresetsStore.d.ts +2 -35
- package/types/modules/filters/components/column/column-filter-preview.vue.d.ts +21 -0
- package/types/modules/filters/components/column/column-filter.vue.d.ts +36 -0
- package/types/modules/filters/components/config/dynamic-view/dynamic-filter-config-form-label.vue.d.ts +2 -2
- package/types/modules/filters/components/config/dynamic-view/dynamic-filter-config-form-value-input.vue.d.ts +3 -2
- package/types/modules/filters/components/config/dynamic-view/dynamic-filter-config-form.vue.d.ts +13 -1
- package/types/modules/filters/components/config/static-view/static-filter-field.vue.d.ts +2 -2
- package/types/modules/filters/components/filters-actions-menu.vue.d.ts +29 -0
- package/types/modules/filters/components/table-filters-panel.vue.d.ts +6 -6
- package/types/modules/filters/components/types/Filter.types.d.ts +4 -0
- package/types/modules/filters/composables/useColumnFilter.d.ts +27 -0
- package/types/modules/filters/composables/useFilterValueChange.d.ts +23 -0
- package/types/modules/filters/composables/useFilterValuePreview.d.ts +21 -0
- package/types/modules/filters/composables/useSelectedFilters.d.ts +22 -0
- package/types/modules/filters/index.d.ts +3 -1
- package/types/modules/filters/modules/filterConfig/components/_custom/type-extension-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/_shared/date-time-filter/date-time-options/date-time-options-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/_shared/durations/duration-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/_shared/string-filter/string-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/agent/agent-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/agent-status/agent-status-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/amd-result/amd-result-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/auditor/auditor-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/auditor/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/bucket/bucket-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/bucket/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/call-direction/call-direction-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/call-reporting-result/call-reporting-result-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/case-assignee/case-assignee-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/case-assignee/filterConfig.d.ts +4 -2
- package/types/modules/filters/modules/filterConfig/components/case-author/case-author-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-close-reason-groups/case-close-reason-groups-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-impacted/case-impacted-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-priority/case-priority-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-reporter/case-reporter-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-sla/case-sla-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-sla-condition/case-sla-condition-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-source/case-source-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/case-status/case-status-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/contact/contact-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/contact-group/contact-group-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-group/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-label/contact-label-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-label/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/contact-owner/contact-owner-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/contact-owner/index.d.ts +4 -2
- package/types/modules/filters/modules/filterConfig/components/gateway/gateway-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/grantee/grantee-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/hangup-cause/hangup-cause-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/has-attachment/has-attachment-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/has-file/has-file-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/has-rating/has-rating-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/has-transcription/has-transcription-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/has-user/has-user-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/index.d.ts +24 -22
- package/types/modules/filters/modules/filterConfig/components/queue/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/queue/queue-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/queue-period/queue-period-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/queue-type/queue-type-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/rated-by/rated-by-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/rating/rating-from-to-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/region/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/region/region-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/score/score-from-to-filter-value-field.vue.d.ts +3 -2
- package/types/modules/filters/modules/filterConfig/components/skill/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/skill/skill-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/stop-cause/stop-cause-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/supervisor/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/supervisor/supervisor-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/tag/tag-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/tags/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/tags/tags-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/talk-duration/talk-duration-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/team/index.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/team/team-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/total-duration/total-duration-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/user/user-filter-value-field.vue.d.ts +8 -4
- package/types/modules/filters/modules/filterConfig/components/utilization-progress/utilization-progress-filter-value-field.vue.d.ts +2 -2
- package/types/modules/filters/modules/filterConfig/components/variable/variable-filter-value-field.vue.d.ts +8 -4
- package/types/modules/headers/createTableHeadersStore.d.ts +24 -0
- package/types/modules/permissions-page/stores/createPermissionsStore.d.ts +4 -70
- package/types/modules/table/createTableStore.store.d.ts +76 -141
- package/types/modules/types/tableStore.types.d.ts +15 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
:label="t('webitelUI.filters.filterValue')"
|
|
4
4
|
:options="CallHistoryTagFilterOptions"
|
|
5
5
|
v-model:model-value="model"
|
|
6
|
-
:v="v$.model"
|
|
6
|
+
:v="!disableValidation && v$.model"
|
|
7
7
|
data-key="value"
|
|
8
8
|
option-value="value"
|
|
9
9
|
/>
|
|
@@ -18,6 +18,10 @@ import { useI18n } from 'vue-i18n';
|
|
|
18
18
|
|
|
19
19
|
import { CallHistoryTagFilterOptions } from '../../enums/options/CallHistoryTagFilterOptions';
|
|
20
20
|
|
|
21
|
+
const props = defineProps<{
|
|
22
|
+
disableValidation?: boolean;
|
|
23
|
+
}>();
|
|
24
|
+
|
|
21
25
|
const model = defineModel<string>();
|
|
22
26
|
const { t } = useI18n();
|
|
23
27
|
|
|
@@ -35,8 +39,7 @@ const v$ = useVuelidate(
|
|
|
35
39
|
},
|
|
36
40
|
);
|
|
37
41
|
|
|
38
|
-
v$.value.$touch();
|
|
39
|
-
|
|
42
|
+
if (!props?.disableValidation) v$.value.$touch();
|
|
40
43
|
const emit = defineEmits<{
|
|
41
44
|
'update:invalid': [
|
|
42
45
|
boolean,
|
package/src/modules/filters/modules/filterConfig/components/user/user-filter-value-field.vue
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
:label="t('webitelUI.filters.filterValue')"
|
|
4
4
|
:search-method="searchMethod"
|
|
5
5
|
:model-value="model"
|
|
6
|
-
:v="v$.model"
|
|
6
|
+
:v="!disableValidation && v$.model"
|
|
7
7
|
option-value="id"
|
|
8
8
|
@update:model-value="handleInput"
|
|
9
9
|
/>
|
|
@@ -20,6 +20,10 @@ import { searchMethod } from './config.js';
|
|
|
20
20
|
|
|
21
21
|
type ModelValue = number[];
|
|
22
22
|
|
|
23
|
+
const props = defineProps<{
|
|
24
|
+
disableValidation?: boolean;
|
|
25
|
+
}>();
|
|
26
|
+
|
|
23
27
|
const model = defineModel<ModelValue>();
|
|
24
28
|
|
|
25
29
|
const emit = defineEmits<{
|
|
@@ -42,8 +46,7 @@ const v$ = useVuelidate(
|
|
|
42
46
|
$autoDirty: true,
|
|
43
47
|
},
|
|
44
48
|
);
|
|
45
|
-
v$.value.$touch();
|
|
46
|
-
|
|
49
|
+
if (!props?.disableValidation) v$.value.$touch();
|
|
47
50
|
watch(
|
|
48
51
|
() => v$.value.$invalid,
|
|
49
52
|
(invalid) => {
|
package/src/modules/filters/modules/filterConfig/components/variable/variable-filter-value-field.vue
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<wt-input-text
|
|
3
3
|
v-model:model-value="model"
|
|
4
4
|
:label="t('webitelUI.filters.filterValue')"
|
|
5
|
-
:v="v$.model"
|
|
5
|
+
:v="!disableValidation && v$.model"
|
|
6
6
|
/>
|
|
7
7
|
</template>
|
|
8
8
|
|
|
@@ -14,6 +14,10 @@ import { useI18n } from 'vue-i18n';
|
|
|
14
14
|
|
|
15
15
|
type ModelValue = string;
|
|
16
16
|
|
|
17
|
+
const props = defineProps<{
|
|
18
|
+
disableValidation?: boolean;
|
|
19
|
+
}>();
|
|
20
|
+
|
|
17
21
|
const model = defineModel<ModelValue>();
|
|
18
22
|
if (!model.value) {
|
|
19
23
|
model.value = '';
|
|
@@ -35,8 +39,7 @@ const v$ = useVuelidate(
|
|
|
35
39
|
},
|
|
36
40
|
);
|
|
37
41
|
|
|
38
|
-
v$.value.$touch();
|
|
39
|
-
|
|
42
|
+
if (!props?.disableValidation) v$.value.$touch();
|
|
40
43
|
const emit = defineEmits<{
|
|
41
44
|
'update:invalid': [
|
|
42
45
|
boolean,
|
|
@@ -1,21 +1,28 @@
|
|
|
1
1
|
import deepEqual from 'deep-equal';
|
|
2
2
|
import { set } from 'lodash-es';
|
|
3
|
-
import { nextTick, type Ref, ref, toRaw, watch } from 'vue';
|
|
3
|
+
import { computed, nextTick, type Ref, ref, toRaw, watch } from 'vue';
|
|
4
4
|
|
|
5
5
|
import {
|
|
6
6
|
createDatalistStore,
|
|
7
7
|
makeThisToRefs,
|
|
8
8
|
} from '../_shared/createDatalistStore';
|
|
9
|
+
import type { FilterName } from '../filters';
|
|
9
10
|
import { createTableFiltersStore } from '../filters/createTableFiltersStore';
|
|
10
11
|
import { createTableHeadersStore } from '../headers/createTableHeadersStore';
|
|
11
12
|
import { createTablePaginationStore } from '../pagination/createTablePaginationStore';
|
|
12
13
|
import type { Identifiable } from '../types/createDatalistStore.types';
|
|
13
14
|
import type {
|
|
15
|
+
DatalistTableHeader,
|
|
14
16
|
LoadDataListOptions,
|
|
15
17
|
PatchItemPropertyParams,
|
|
16
18
|
useTableStoreConfig,
|
|
17
19
|
} from '../types/tableStore.types';
|
|
18
20
|
|
|
21
|
+
const getFilterName = (
|
|
22
|
+
filter: DatalistTableHeader['filter'],
|
|
23
|
+
): FilterName | undefined =>
|
|
24
|
+
typeof filter === 'object' ? filter?.name : filter;
|
|
25
|
+
|
|
19
26
|
export const tableStoreBody = <Entity extends Identifiable>(
|
|
20
27
|
namespace: string,
|
|
21
28
|
config: useTableStoreConfig<Entity>,
|
|
@@ -58,8 +65,8 @@ export const tableStoreBody = <Entity extends Identifiable>(
|
|
|
58
65
|
|
|
59
66
|
const headersStore = useHeadersStore();
|
|
60
67
|
const {
|
|
61
|
-
headers,
|
|
62
|
-
shownHeaders,
|
|
68
|
+
headers: rawHeaders,
|
|
69
|
+
shownHeaders: rawShownHeaders,
|
|
63
70
|
fields,
|
|
64
71
|
sort,
|
|
65
72
|
columnWidths,
|
|
@@ -90,6 +97,20 @@ export const tableStoreBody = <Entity extends Identifiable>(
|
|
|
90
97
|
updateSearchMode,
|
|
91
98
|
} = filtersStore;
|
|
92
99
|
|
|
100
|
+
const withFilteredFlag = (list: DatalistTableHeader[]) =>
|
|
101
|
+
list.map((header) => {
|
|
102
|
+
const name = getFilterName(header.filter);
|
|
103
|
+
return name
|
|
104
|
+
? {
|
|
105
|
+
...header,
|
|
106
|
+
filtered: filtersManager.value.hasFilter(name),
|
|
107
|
+
}
|
|
108
|
+
: header;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const headers = computed(() => withFilteredFlag(rawHeaders.value));
|
|
112
|
+
const shownHeaders = computed(() => withFilteredFlag(rawShownHeaders.value));
|
|
113
|
+
|
|
93
114
|
/**
|
|
94
115
|
* @internal
|
|
95
116
|
* @description
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ApiModule } from '@webitel/ui-sdk/api/types/ApiModule';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
WtTableHeader,
|
|
4
|
+
WtTableHeaderFilter,
|
|
5
|
+
} from '@webitel/ui-sdk/components/wt-table/types/WtTable';
|
|
3
6
|
import type { Ref } from 'vue';
|
|
4
7
|
|
|
5
8
|
import type { IFiltersManager } from '../filters';
|
|
@@ -20,6 +23,20 @@ export type DatalistTableHeader = WtTableHeader & {
|
|
|
20
23
|
* restorable from persisted state. Omitted means allowed.
|
|
21
24
|
*/
|
|
22
25
|
access?: () => boolean | Ref<boolean>;
|
|
26
|
+
/**
|
|
27
|
+
* Name of the filter shown in the column header popover (`column-filter` slot),
|
|
28
|
+
* or an already-resolved config for it (build one with `createFilterConfig`). Passing a
|
|
29
|
+
* config here lets `headers.ts` map the header to its filter once, instead of
|
|
30
|
+
* `useColumnFilter` searching `filterOptions`/`filterableExtensionFields` for it on every
|
|
31
|
+
* column.
|
|
32
|
+
*
|
|
33
|
+
* {@link WtTableHeaderFilter} deliberately keeps only the `name` of a resolved config and not
|
|
34
|
+
* the full `AnyFilterConfig` (with its `Component` props): `createTableHeadersStore` keeps
|
|
35
|
+
* headers in a plain `ref<DatalistTableHeader[]>`, and `Component` props there send Vue's
|
|
36
|
+
* `UnwrapRef` into excessive type-instantiation depth (TS2589). `useColumnFilter`'s
|
|
37
|
+
* `isResolvedFilterConfig` narrows it back to `AnyFilterConfig` for actual use.
|
|
38
|
+
*/
|
|
39
|
+
filter?: WtTableHeaderFilter;
|
|
23
40
|
};
|
|
24
41
|
|
|
25
42
|
export type TrackSelectedRowBy<T> = (row: T) => T;
|