@uxland/primary-shell 5.4.7 → 5.5.0

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.
Files changed (59) hide show
  1. package/dist/index.js +818 -660
  2. package/dist/index.js.map +1 -1
  3. package/dist/index.umd.cjs +63 -30
  4. package/dist/index.umd.cjs.map +1 -1
  5. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/domain/specs/up-filter-spec.d.ts +8 -0
  6. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/domain/specs/up-filter-spec.test.d.ts +1 -0
  7. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/UI/active-filters-badges/active-filters-badges.d.ts +3 -1
  8. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/UI/active-filters-header/active-filters-header.d.ts +1 -0
  9. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/UI/activity-history-filters/activity-history-filters.d.ts +4 -1
  10. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/model.d.ts +13 -1
  11. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/slice.d.ts +4 -0
  12. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/actions.d.ts +1 -0
  13. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/bootstrapper.d.ts +4 -0
  14. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/handler.d.ts +6 -0
  15. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/reducer.d.ts +4 -0
  16. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/reducer.test.d.ts +1 -0
  17. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/request.d.ts +6 -0
  18. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/handle-add-up-options-from-item.d.ts +4 -0
  19. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/selectors.d.ts +185 -0
  20. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/actions.d.ts +1 -0
  21. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/bootstrapper.d.ts +4 -0
  22. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/handler.d.ts +6 -0
  23. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/reducer.d.ts +3 -0
  24. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/request.d.ts +4 -0
  25. package/dist/primary/shell/src/internal-plugins/activity-history/activity-history-item/selectors.d.ts +60 -0
  26. package/package.json +1 -1
  27. package/src/UI/components/communication-action-menu/template.ts +3 -2
  28. package/src/UI/internal-views/upper-nav-views.ts +2 -2
  29. package/src/internal-plugins/activity-history/activity-history-item/add/add-history-item/handler.ts +2 -0
  30. package/src/internal-plugins/activity-history/activity-history-item/add/add-history-items/handler.ts +2 -0
  31. package/src/internal-plugins/activity-history/activity-history-item/domain/specs/up-filter-spec.test.ts +38 -0
  32. package/src/internal-plugins/activity-history/activity-history-item/domain/specs/up-filter-spec.ts +18 -0
  33. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/active-filters-badges/active-filters-badges.ts +15 -1
  34. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/active-filters-badges/template.ts +45 -1
  35. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/active-filters-header/active-filters-header.ts +4 -0
  36. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/active-filters-header/template.ts +1 -0
  37. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/activity-history-filters/activity-history-filters.ts +16 -10
  38. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/activity-history-filters/styles.css +1 -0
  39. package/src/internal-plugins/activity-history/activity-history-item/filter/UI/activity-history-filters/template.ts +51 -15
  40. package/src/internal-plugins/activity-history/activity-history-item/filter/bootstrapper.ts +6 -0
  41. package/src/internal-plugins/activity-history/activity-history-item/filter/custom-filters/reset-custom-filter/reducer.ts +1 -2
  42. package/src/internal-plugins/activity-history/activity-history-item/filter/model.ts +14 -8
  43. package/src/internal-plugins/activity-history/activity-history-item/filter/slice.ts +4 -0
  44. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/actions.ts +3 -0
  45. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/bootstrapper.ts +14 -0
  46. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/handler.ts +14 -0
  47. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/reducer.test.ts +93 -0
  48. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/reducer.ts +22 -0
  49. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/add/request.ts +5 -0
  50. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/handle-add-up-options-from-item.ts +20 -0
  51. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/selectors.ts +14 -0
  52. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/actions.ts +3 -0
  53. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/bootstrapper.ts +14 -0
  54. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/handler.ts +13 -0
  55. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/reducer.ts +11 -0
  56. package/src/internal-plugins/activity-history/activity-history-item/filter/up-filters/set/request.ts +3 -0
  57. package/src/internal-plugins/activity-history/activity-history-item/selectors.ts +10 -23
  58. package/src/internal-plugins/activity-history/utils/get-unique-values-by-prop-path.ts +3 -1
  59. package/src/locales.ts +3 -6
@@ -38,13 +38,25 @@ const renderDiagnosticChip = (id, value, props) => html`
38
38
  ></dss-chip>
39
39
  `;
40
40
 
41
+ const renderUpChip = (id, value, props) => html`
42
+ <dss-chip
43
+ label=${value}
44
+ size="sm"
45
+ hasdelete
46
+ selected
47
+ @click=${() => props._onDeleteUpFilterValue(id)}
48
+ @onDelete=${() => props._onDeleteUpFilterValue(id)}
49
+ ></dss-chip>
50
+ `;
51
+
41
52
  const renderFilterTitle = (title) => html`<div class="filter-title">${`${title}:`}</div>`;
42
53
 
43
54
  export const template = (props: ActiveFiltersBadges) => {
44
55
  if (
45
56
  props.enabledFilters.length === 0 &&
46
57
  props.enabledCommonFilters.length === 0 &&
47
- props.diagnosticFilterEnabled.enabledValues.length === 0
58
+ props.diagnosticFilterEnabled.enabledValues.length === 0 &&
59
+ props.upFilterEnabled.enabledValues.length === 0
48
60
  )
49
61
  return nothing;
50
62
 
@@ -85,6 +97,38 @@ export const template = (props: ActiveFiltersBadges) => {
85
97
  }
86
98
  }
87
99
 
100
+ const up = props.upFilterEnabled;
101
+
102
+ if (up) {
103
+ const { title, values, enabledValues } = up;
104
+ const selectedOptions = values.filter((opt) => enabledValues.includes(opt.value));
105
+
106
+ if (selectedOptions.length > 0) {
107
+ let titleAddedToVisible = false;
108
+ let titleAddedToHidden = false;
109
+
110
+ for (const option of selectedOptions) {
111
+ const chip = renderUpChip(option.value, option.label, props);
112
+
113
+ if (visibleCount < MAX_VISIBLE_CHIPS) {
114
+ if (!titleAddedToVisible) {
115
+ visibleChips.push(renderFilterTitle(title));
116
+ titleAddedToVisible = true;
117
+ }
118
+ visibleChips.push(chip);
119
+ visibleCount++;
120
+ } else {
121
+ if (!titleAddedToHidden) {
122
+ hiddenElements.push(renderFilterTitle(title));
123
+ titleAddedToHidden = true;
124
+ }
125
+ hiddenElements.push(chip);
126
+ hiddenChips.push(chip);
127
+ }
128
+ }
129
+ }
130
+ }
131
+
88
132
  for (const filter of props.enabledCommonFilters) {
89
133
  const chip = renderCommonChip(filter, props);
90
134
 
@@ -7,6 +7,7 @@ import { activityHistorySearchStringSelector } from "../../../search/selectors";
7
7
  import { areCustomFiltersActive } from "../../custom-filters/selectors";
8
8
  import { areCommonFiltersActive } from "../../common-filters/selectors";
9
9
  import { areDiagnosticFiltersActive } from "../../diagnostic-filters/selectors";
10
+ import { areUpFiltersActive } from "../../up-filters/selectors";
10
11
 
11
12
  //@ts-ignore
12
13
  @customElement("active-filters-header")
@@ -30,4 +31,7 @@ export class ActiveFiltersHeader extends LitElement {
30
31
 
31
32
  @connectedProperty(areDiagnosticFiltersActive)
32
33
  areDiagnosticFiltersActive: boolean;
34
+
35
+ @connectedProperty(areUpFiltersActive)
36
+ areUpFiltersActive: boolean;
33
37
  }
@@ -7,6 +7,7 @@ export const template = (props: ActiveFiltersHeader) => {
7
7
  !props.areCustomFiltersActive &&
8
8
  !props.areCommonFiltersActive &&
9
9
  !props.areDiagnosticFiltersActive &&
10
+ !props.areUpFiltersActive &&
10
11
  props.searchString.length < 1
11
12
  )
12
13
  return nothing;
@@ -8,6 +8,7 @@ import {
8
8
  IActivityHistoryCommonFilter,
9
9
  IActivityHistoryCustomFilterGroup,
10
10
  IActivityHistoryDiagnosticsFilter,
11
+ IActivityHistoryUpFilter,
11
12
  } from "../../model";
12
13
  import styles from "./styles.css?inline";
13
14
  import { template } from "./template";
@@ -16,11 +17,10 @@ import { SetCommonFilter } from "../../common-filters/set-common-filter/request"
16
17
  import { activityHistoryCommonFiltersSelector } from "../../common-filters/selectors";
17
18
  import { SetCustomFilterValue } from "../../custom-filters/set-custom-filter-value/request";
18
19
  import { customFilterGroupsWithOptionsSelector } from "../../../selectors";
19
- import {
20
- diagnosticFilterEnabledValuesSelector,
21
- diagnosticFilterSelector,
22
- } from "../../diagnostic-filters/selectors";
20
+ import { diagnosticFilterEnabledValuesSelector, diagnosticFilterSelector } from "../../diagnostic-filters/selectors";
23
21
  import { SetDiagnosticFiltersCommand } from "../../diagnostic-filters/set/request";
22
+ import { upFilterEnabledValuesSelector, upFilterSelector } from "../../up-filters/selectors";
23
+ import { SetUpFiltersCommand } from "../../up-filters/set/request";
24
24
 
25
25
  //@ts-ignore
26
26
  @customElement("activity-history-filters")
@@ -45,6 +45,12 @@ export class ActivityHistoryFilters extends LitElement {
45
45
  @connectedProperty(diagnosticFilterEnabledValuesSelector)
46
46
  diagnosticFilterEnabledValues: string[];
47
47
 
48
+ @connectedProperty(upFilterSelector)
49
+ upFilter: IActivityHistoryUpFilter;
50
+
51
+ @connectedProperty(upFilterEnabledValuesSelector)
52
+ upFilterEnabledValues: string[];
53
+
48
54
  @lazyInject(TYPES.primaryApi)
49
55
  api: PrimariaApi;
50
56
 
@@ -72,12 +78,7 @@ export class ActivityHistoryFilters extends LitElement {
72
78
  this.api.broker.send(new SetCustomFilterGroup({ id: filterGroupId, enabled: value }));
73
79
  }
74
80
 
75
- _onChangeCustomFilterValue(
76
- filterGroupId: string,
77
- filterId: string,
78
- optionId: string,
79
- value: boolean,
80
- ) {
81
+ _onChangeCustomFilterValue(filterGroupId: string, filterId: string, optionId: string, value: boolean) {
81
82
  this.api.broker.send(
82
83
  new SetCustomFilterValue({
83
84
  filterGroupId,
@@ -92,4 +93,9 @@ export class ActivityHistoryFilters extends LitElement {
92
93
  const selectedValues = e.detail.selectedValue;
93
94
  this.api.broker.send(new SetDiagnosticFiltersCommand(selectedValues));
94
95
  }
96
+
97
+ _handleUpFilterChange(e: CustomEvent) {
98
+ const selectedValues = e.detail.selectedValue;
99
+ this.api.broker.send(new SetUpFiltersCommand(selectedValues));
100
+ }
95
101
  }
@@ -41,6 +41,7 @@
41
41
  display: flex;
42
42
  flex-direction: column;
43
43
  padding-top: 12px;
44
+ gap: var(--dss-spacing-xs);
44
45
 
45
46
  .custom-filter{
46
47
  display: flex;
@@ -22,6 +22,12 @@ const filterTemplates = {
22
22
  <input slot="input" id="checkboxStory-${id}" type="checkbox" ?disabled=${!isEnabled}>
23
23
  <label slot="label" for="checkboxStory-${id}">${title}</label>
24
24
  </dss-checkbox>`,
25
+
26
+ [ActivityHistoryFilterType.Dropdown]: (id, title, handleChange, isSelected, isEnabled) => html`
27
+ <dss-input-dropdown type="default" .checked=${isSelected} @onChange=${(e) => handleChange(e)}>
28
+ <input slot="input" id="dropdownStory-${id}" type="text" ?disabled=${!isEnabled}>
29
+ <label slot="label" for="dropdownStory-${id}">${title}</label>
30
+ </dss-input-dropdown>`,
25
31
  };
26
32
 
27
33
  const getFilterTemplate = (
@@ -33,7 +39,7 @@ const getFilterTemplate = (
33
39
  const isCustom = !!filterGroup?.id && !!option;
34
40
  //const id = isCustom ? `${filterGroupId}-${filter.id}-${option.id}` : filter.id;
35
41
  const id = crypto.randomUUID();
36
- const title = isCustom ? option.title : filter.title;
42
+ const title = isCustom ? option.title || option.id : filter.title;
37
43
 
38
44
  const handleChange = (e) => {
39
45
  if (filter.singleOption) onChangeValue(filterGroup?.id, filter.id, null, e.detail);
@@ -67,6 +73,15 @@ export const template = (props: ActivityHistoryFilters) =>
67
73
  </dss-input-dropdown>
68
74
  </div>`
69
75
  }
76
+ ${
77
+ props.upFilter &&
78
+ html`<div class="filter">
79
+ <dss-input-dropdown icon="" multiple dropdownFixed type="default" .elements=${props.upFilter?.values} @onInputDropdownChange=${props._handleUpFilterChange} .selectedValue=${props.upFilterEnabledValues} selectorStyle=${"max-height: 450px"}>
80
+ <label slot="label" for="up-filter">${props.upFilter.title}</label>
81
+ <input id="up-filter" slot="input" type="text" class="dss-input" autocomplete="off"/>
82
+ </dss-input-dropdown>
83
+ </div>`
84
+ }
70
85
  ${repeat(
71
86
  props.customFilterGroups,
72
87
  (group: IActivityHistoryCustomFilterGroup) => html`
@@ -91,17 +106,38 @@ const customFilterTemplate = (
91
106
  filter: IActivityHistoryCustomFilter,
92
107
  props: ActivityHistoryFilters,
93
108
  group: IActivityHistoryCustomFilterGroup,
94
- ) =>
95
- html`
96
- <div class="custom-filter">
97
- ${
98
- filter.singleOption
99
- ? getFilterTemplate(filter, props._onChangeCustomFilterValue.bind(props), group)
100
- : html`
101
- <primaria-accordion isOpen=${true}>
102
- <div class="custom-filter-title" slot="title">${filter.title}</div>
103
- <div class="custom-filter-content" slot="content">${repeat(filter.options, (option) => html`${getFilterTemplate(filter, props._onChangeCustomFilterValue.bind(props), group, option)}`)}</div>
104
- </primaria-accordion>`
105
- }
106
- </div>
107
- `;
109
+ ) => {
110
+ if (filter.type === ActivityHistoryFilterType.Dropdown) {
111
+ const elements = filter?.options.map(option => ({ value: option.id, label: option.title }));
112
+ return html`
113
+ <dss-input-dropdown
114
+ icon=""
115
+ multiple
116
+ dropdownFixed
117
+ type="default"
118
+ .elements=${elements}
119
+ @onInputDropdownChange=${(e) =>
120
+ props._onChangeCustomFilterValue(group.id, filter.id, e.detail.selectedValue[e.detail.selectedValue.length-1], true)
121
+ }
122
+ .selectedValue=${filter.enabledValues}
123
+ selectorStyle="max-height: 450px"
124
+ >
125
+ <label slot="label">${filter.title}</label>
126
+ <input slot="input" type="text" class="dss-input" autocomplete="off" />
127
+ </dss-input-dropdown>
128
+ `;
129
+ }
130
+
131
+ return filter.singleOption
132
+ ? getFilterTemplate(filter, props._onChangeCustomFilterValue.bind(props), group)
133
+ : html`
134
+ <primaria-accordion isOpen>
135
+ <div class="custom-filter-title" slot="title">${filter.title}</div>
136
+ <div class="custom-filter-content" slot="content">
137
+ ${filter.options.map(option =>
138
+ getFilterTemplate(filter, props._onChangeCustomFilterValue.bind(props), group, option)
139
+ )}
140
+ </div>
141
+ </primaria-accordion>
142
+ `;
143
+ };
@@ -14,6 +14,8 @@ import { bootstrapAddDiagnosticFilter, teardownAddDiagnosticFilter } from "./dia
14
14
  import { bootstrapSetDiagnosticFilter, teardownSetDiagnosticFilter } from "./diagnostic-filters/set/bootstrapper";
15
15
  import { bootstrapResetCommonFilter, teardownResetCommonFilter } from "./common-filters/reset-common-filter/bootstrapper";
16
16
  import { bootstrapResetCustomFilter, teardownResetCustomFilter } from "./custom-filters/reset-custom-filter/bootstrapper";
17
+ import { bootstrapAddUpFilter, teardownAddUpFilter } from "./up-filters/add/bootstrapper";
18
+ import { bootstrapSetUpFilter, teardownSetUpFilter } from "./up-filters/set/bootstrapper";
17
19
 
18
20
  export const bootstrapFilters = (broker: BrokerExtensions) => {
19
21
  bootstrapSetCommonFilter(broker);
@@ -24,6 +26,8 @@ export const bootstrapFilters = (broker: BrokerExtensions) => {
24
26
  bootstrapSetDiagnosticFilter(broker);
25
27
  bootstrapResetCommonFilter(broker);
26
28
  bootstrapResetCustomFilter(broker);
29
+ bootstrapAddUpFilter(broker);
30
+ bootstrapSetUpFilter(broker);
27
31
  };
28
32
 
29
33
  export const teardownFilters = () => {
@@ -35,4 +39,6 @@ export const teardownFilters = () => {
35
39
  teardownSetDiagnosticFilter();
36
40
  teardownResetCommonFilter();
37
41
  teardownResetCustomFilter();
42
+ teardownAddUpFilter();
43
+ teardownSetUpFilter();
38
44
  };
@@ -1,7 +1,6 @@
1
1
  export function resetCustomFilterValuesReducer(state) {
2
2
  state.filters = state.filters.map((f) => {
3
- if (f.id !== "common" && f.id !== "history-diagnostics") {
4
- console.log("filter", f);
3
+ if (f.id !== "common" && f.id !== "history-diagnostics" && f.id !== "history-up") {
5
4
  return {
6
5
  ...f,
7
6
  filters: f.filters.map((ff) => ({ ...ff, enabled: false, enabledValues: [] })),
@@ -6,6 +6,7 @@ type Constructor<T> = new (...args: any[]) => T;
6
6
  export enum ActivityHistoryFilterType {
7
7
  Switch = "switch",
8
8
  Checkbox = "checkbox",
9
+ Dropdown = "dropdown",
9
10
  }
10
11
 
11
12
  export enum ActivityHistoryFilterOperation {
@@ -56,14 +57,11 @@ export interface IActivityHistoryCustomFilter {
56
57
  }
57
58
 
58
59
  export const isCommonFilterGroup = (group: IActivityHistoryFilter) => group.id === "common";
59
- export const isNotCommonFilterGroup = (group: IActivityHistoryFilter) =>
60
- !isCommonFilterGroup(group);
61
- export const isDiagnosticFilter = (filter: IActivityHistoryFilter) =>
62
- filter.id === diagnosticsfilterId;
63
- export const isNotDiagnosticFilter = (filter: IActivityHistoryFilter) =>
64
- !isDiagnosticFilter(filter);
65
- export const isCustomFilter = (filter: IActivityHistoryFilter) =>
66
- !isCommonFilterGroup(filter) && !isDiagnosticFilter(filter);
60
+ export const isNotCommonFilterGroup = (group: IActivityHistoryFilter) => !isCommonFilterGroup(group);
61
+ export const isDiagnosticFilter = (filter: IActivityHistoryFilter) => filter.id === diagnosticsfilterId;
62
+ export const isNotDiagnosticFilter = (filter: IActivityHistoryFilter) => !isDiagnosticFilter(filter);
63
+ export const isCustomFilter = (filter: IActivityHistoryFilter) => !isCommonFilterGroup(filter) && !isDiagnosticFilter(filter) && !isUpFilter(filter);
64
+ export const isUpFilter = (filter: IActivityHistoryFilter) => filter.id === upFilterId;
67
65
  export interface IActivityHistoryDiagnosticsFilter {
68
66
  id: string;
69
67
  title: string;
@@ -71,6 +69,14 @@ export interface IActivityHistoryDiagnosticsFilter {
71
69
  enabledValues: string[];
72
70
  }
73
71
 
72
+ export interface IActivityHistoryUpFilter {
73
+ id: string;
74
+ title: string;
75
+ values: { label: string; value: string }[];
76
+ enabledValues: string[];
77
+ }
78
+
74
79
  export const diagnosticsfilterId = "history-diagnostics";
75
80
  export const relevantFilterId = "history-relevant";
76
81
  export const ownFilterId = "history-own";
82
+ export const upFilterId = "history-up";
@@ -10,6 +10,8 @@ import { addDiagnosticFiltersReducer } from "./diagnostic-filters/add/reducer";
10
10
  import { setDiagnosticFilterValuesReducer } from "./diagnostic-filters/set/reducer";
11
11
  import { resetCommonFilterValuesReducer } from "./common-filters/reset-common-filter/reducer";
12
12
  import { resetCustomFilterValuesReducer } from "./custom-filters/reset-custom-filter/reducer";
13
+ import { addUpFiltersReducer } from "./up-filters/add/reducer";
14
+ import { setUpFilterValuesReducer } from "./up-filters/set/reducer";
13
15
 
14
16
  export const activityHistoryFiltersSlice = createSlice({
15
17
  name: "activity-history-filters",
@@ -27,5 +29,7 @@ export const activityHistoryFiltersSlice = createSlice({
27
29
  resetCustomFilterValues: resetCustomFilterValuesReducer,
28
30
  addDiagnosticFilters: addDiagnosticFiltersReducer,
29
31
  setDiagnosticFilterValues: setDiagnosticFilterValuesReducer,
32
+ addUpFilters: addUpFiltersReducer,
33
+ setUpFilterValues: setUpFilterValuesReducer,
30
34
  },
31
35
  });
@@ -0,0 +1,3 @@
1
+ import { activityHistoryFiltersSlice } from "../../slice";
2
+
3
+ export const { addUpFilters } = activityHistoryFiltersSlice.actions;
@@ -0,0 +1,14 @@
1
+ import { BrokerExtensions } from "@primaria/plugins-core";
2
+ import { BrokerDisposableHandler } from "../../../../../../api/broker/primaria-broker";
3
+ import { AddUpFiltersHandler } from "./handler";
4
+ import { AddUpFiltersCommand } from "./request";
5
+
6
+ let request: BrokerDisposableHandler;
7
+
8
+ export const bootstrapAddUpFilter = (broker: BrokerExtensions) => {
9
+ request = broker.registerRequest(AddUpFiltersCommand, AddUpFiltersHandler);
10
+ };
11
+
12
+ export const teardownAddUpFilter = () => {
13
+ request?.dispose();
14
+ };
@@ -0,0 +1,14 @@
1
+ import { StoreBaseHandler } from "../../../../infrastructure/base-handlers";
2
+ import { addUpFilters } from "./actions";
3
+ import { AddUpFiltersCommand } from "./request";
4
+
5
+ export class AddUpFiltersHandler extends StoreBaseHandler {
6
+ async handle(request: AddUpFiltersCommand) {
7
+ try {
8
+ //TODO ensure are valid filters
9
+ this.store.dispatch(addUpFilters(request.payload));
10
+ } catch (e) {
11
+ console.log(e.message);
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,93 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
3
+ import { IActivityHistoryUpFilter, isUpFilter } from "../../model";
4
+ import { addUpFiltersReducer } from "./reducer";
5
+
6
+ vi.mock("../../model", () => ({
7
+ isUpFilter: vi.fn(),
8
+ }));
9
+
10
+ describe("addUpFiltersReducer", () => {
11
+ let initialState: { filters: IActivityHistoryUpFilter[] };
12
+
13
+ const baseFilter = (values: any[]): IActivityHistoryUpFilter => ({
14
+ id: "up",
15
+ title: "UP",
16
+ values,
17
+ enabledValues: [],
18
+ });
19
+
20
+ beforeEach(() => {
21
+ initialState = {
22
+ filters: [],
23
+ };
24
+ vi.clearAllMocks();
25
+ });
26
+
27
+ const slice = createSlice({
28
+ name: "activity",
29
+ initialState,
30
+ reducers: {
31
+ addUpFilters: addUpFiltersReducer,
32
+ },
33
+ });
34
+
35
+ const { addUpFilters } = slice.actions;
36
+ const reducer = slice.reducer;
37
+
38
+ it("should add a new up filter if none exists", () => {
39
+ (isUpFilter as any).mockReturnValue(false);
40
+
41
+ const newUp = baseFilter([{ label: "0773", value: "0773" }]);
42
+
43
+ const nextState = reducer(initialState, addUpFilters(newUp));
44
+
45
+ expect(nextState.filters).toHaveLength(1);
46
+ expect(nextState.filters[0]).toEqual(newUp);
47
+ });
48
+
49
+ it("should merge values if a up filter already exists", () => {
50
+ const existingFilter = baseFilter([{ label: "0773", value: "0773" }]);
51
+ initialState.filters = [existingFilter];
52
+
53
+ (isUpFilter as any).mockImplementation((f) => f.id === "up");
54
+
55
+ const incomingFilter = baseFilter([{ label: "0444", value: "0444" }]);
56
+
57
+ const nextState = reducer(initialState, addUpFilters(incomingFilter));
58
+
59
+ expect(nextState.filters).toHaveLength(1);
60
+ expect(nextState.filters[0].values).toContainEqual({ label: "0773", value: "0773" });
61
+ expect(nextState.filters[0].values).toContainEqual({ label: "0444", value: "0444" });
62
+ });
63
+
64
+ it("should avoid duplicate values when merging", () => {
65
+ const existingFilter = baseFilter([{ label: "0444", value: "0444" }]);
66
+ initialState.filters = [existingFilter];
67
+
68
+ (isUpFilter as any).mockImplementation((f) => f.id === "up");
69
+
70
+ const incomingFilter = baseFilter([{ label: "0444", value: "0444" }]);
71
+
72
+ const nextState = reducer(initialState, addUpFilters(incomingFilter));
73
+
74
+ expect(nextState.filters).toHaveLength(1);
75
+ expect(nextState.filters[0].values).toEqual([{ label: "0444", value: "0444" }]);
76
+ });
77
+
78
+ it("should preserve other properties of the existing filter", () => {
79
+ const existingFilter = {
80
+ ...baseFilter([{ label: "A", value: "1" }]),
81
+ enabledValues: ["1"],
82
+ };
83
+ initialState.filters = [existingFilter];
84
+
85
+ (isUpFilter as any).mockReturnValue(true);
86
+
87
+ const incomingFilter = baseFilter([{ label: "B", value: "2" }]);
88
+
89
+ const nextState = reducer(initialState, addUpFilters(incomingFilter));
90
+
91
+ expect(nextState.filters[0].enabledValues).toEqual(["1"]); // no se sobreescribe
92
+ });
93
+ });
@@ -0,0 +1,22 @@
1
+ import { PayloadAction } from "@reduxjs/toolkit";
2
+ import { IActivityHistoryUpFilter, isUpFilter } from "../../model";
3
+
4
+ export function addUpFiltersReducer(state, action: PayloadAction<IActivityHistoryUpFilter>) {
5
+ const index = state.filters.findIndex(isUpFilter);
6
+
7
+ if (index === -1) {
8
+ state.filters.push(action.payload);
9
+ } else {
10
+ const existing = state.filters[index];
11
+
12
+ const mergedValues = [
13
+ ...existing.values,
14
+ ...action.payload.values.filter((v) => !existing.values.some((ev) => ev.value === v.value)),
15
+ ];
16
+
17
+ state.filters[index] = {
18
+ ...existing,
19
+ values: mergedValues,
20
+ };
21
+ }
22
+ }
@@ -0,0 +1,5 @@
1
+ import { IActivityHistoryUpFilter } from "../../model";
2
+
3
+ export class AddUpFiltersCommand {
4
+ constructor(public payload: IActivityHistoryUpFilter) {}
5
+ }
@@ -0,0 +1,20 @@
1
+ import { mapArrayToLabelValue } from "@primaria/plugins-core";
2
+ import { Store } from "@reduxjs/toolkit";
3
+ import { IActivityHistoryItem } from "../../domain/model";
4
+ import { upFilterId } from "../model";
5
+ import { addUpFilters } from "./add/actions";
6
+
7
+ export const handleAddUpFilter = (items: IActivityHistoryItem[], store: Store) => {
8
+ const allUps = items.flatMap((item) => item.up ?? []).filter((up, index, self) => index === self.findIndex((u) => u.id === up.id));
9
+
10
+ if (allUps.length > 0) {
11
+ const newUpFilter = {
12
+ id: upFilterId,
13
+ title: "UP",
14
+ values: mapArrayToLabelValue(allUps, "description", "id"),
15
+ enabledValues: [],
16
+ };
17
+
18
+ store.dispatch(addUpFilters(newUpFilter));
19
+ }
20
+ };
@@ -0,0 +1,14 @@
1
+ import { createSelector } from "@reduxjs/toolkit";
2
+ import { IActivityHistoryFilter, IActivityHistoryUpFilter, isUpFilter } from "../model";
3
+ import { activityHistoryFiltersSelector } from "../selectors";
4
+
5
+ export const upFilterSelector = createSelector(activityHistoryFiltersSelector, (filters: IActivityHistoryFilter[]) =>
6
+ filters.find(isUpFilter),
7
+ );
8
+
9
+ export const upFilterEnabledValuesSelector = createSelector(
10
+ upFilterSelector,
11
+ (filter: IActivityHistoryUpFilter) => filter?.enabledValues || [],
12
+ );
13
+
14
+ export const areUpFiltersActive = createSelector(upFilterEnabledValuesSelector, (filters) => !!filters.length);
@@ -0,0 +1,3 @@
1
+ import { activityHistoryFiltersSlice } from "../../slice";
2
+
3
+ export const { setUpFilterValues } = activityHistoryFiltersSlice.actions;
@@ -0,0 +1,14 @@
1
+ import { BrokerExtensions } from "@primaria/plugins-core";
2
+ import { BrokerDisposableHandler } from "../../../../../../api/broker/primaria-broker";
3
+ import { SetUpFiltersHandler } from "./handler";
4
+ import { SetUpFiltersCommand } from "./request";
5
+
6
+ let request: BrokerDisposableHandler;
7
+
8
+ export const bootstrapSetUpFilter = (broker: BrokerExtensions) => {
9
+ request = broker.registerRequest(SetUpFiltersCommand, SetUpFiltersHandler);
10
+ };
11
+
12
+ export const teardownSetUpFilter = () => {
13
+ request?.dispose();
14
+ };
@@ -0,0 +1,13 @@
1
+ import { StoreBaseHandler } from "../../../../infrastructure/base-handlers";
2
+ import { setUpFilterValues } from "./actions";
3
+ import { SetUpFiltersCommand } from "./request";
4
+
5
+ export class SetUpFiltersHandler extends StoreBaseHandler {
6
+ async handle(request: SetUpFiltersCommand) {
7
+ try {
8
+ this.store.dispatch(setUpFilterValues(request.payload));
9
+ } catch (e) {
10
+ console.log(e.message);
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,11 @@
1
+ import { PayloadAction } from "@reduxjs/toolkit";
2
+ import { IActivityHistoryUpFilter, isUpFilter } from "../../model";
3
+
4
+ export function setUpFilterValuesReducer(state, action: PayloadAction<string[]>) {
5
+ state.filters = [...state.filters].map((f) => {
6
+ if (isUpFilter(f)) {
7
+ return { ...f, enabledValues: action.payload } as IActivityHistoryUpFilter;
8
+ }
9
+ return f;
10
+ });
11
+ }
@@ -0,0 +1,3 @@
1
+ export class SetUpFiltersCommand {
2
+ constructor(public payload: string[]) {}
3
+ }