@salesforcedevs/dx-components 1.40.11 → 1.41.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.
- package/package.json +2 -2
- package/src/modules/dx/filterMenu/filterMenu.css +19 -0
- package/src/modules/dx/filterMenu/filterMenu.html +17 -2
- package/src/modules/dx/filterMenu/filterMenu.ts +43 -0
- package/src/modules/dx/searchHybrid/searchHybrid.css +56 -61
- package/src/modules/dx/searchHybrid/searchHybrid.html +133 -112
- package/src/modules/dx/searchHybrid/searchHybrid.mock.ts +244 -0
- package/src/modules/dx/searchHybrid/searchHybrid.ts +81 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/dx-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.41.0",
|
|
4
4
|
"description": "DX Lightning web components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"luxon": "3.4.4",
|
|
45
45
|
"msw": "^2.12.4"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "505fb7062378be9370bdb2dd44f66b5b327b3665"
|
|
48
48
|
}
|
|
@@ -132,3 +132,22 @@ svg,
|
|
|
132
132
|
display: inline-block;
|
|
133
133
|
content: "(.\00a0\00a0)";
|
|
134
134
|
}
|
|
135
|
+
|
|
136
|
+
.single-option {
|
|
137
|
+
display: block;
|
|
138
|
+
width: 100%;
|
|
139
|
+
padding: 6px 0;
|
|
140
|
+
text-align: left;
|
|
141
|
+
font-family: var(--dx-g-font-sans);
|
|
142
|
+
font-size: 14px;
|
|
143
|
+
color: rgb(24 24 24);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.single-option:hover,
|
|
147
|
+
.single-option-selected {
|
|
148
|
+
color: var(--dx-g-blue-vibrant-50);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.single-option-selected {
|
|
152
|
+
font-weight: bold;
|
|
153
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<form class="container">
|
|
3
3
|
<span class="title-group-main title-group" onclick={dropdownToggle}>
|
|
4
|
-
<p class="filter-menu-title">{
|
|
4
|
+
<p class="filter-menu-title">{displayTitle}</p>
|
|
5
5
|
<svg
|
|
6
6
|
xmlns="http://www.w3.org/2000/svg"
|
|
7
7
|
width="28"
|
|
@@ -18,7 +18,22 @@
|
|
|
18
18
|
</span>
|
|
19
19
|
<ul class="nested first-layer always-visible-scrollbar">
|
|
20
20
|
<li>
|
|
21
|
-
<template if:true={
|
|
21
|
+
<template if:true={singleSelect}>
|
|
22
|
+
<template for:each={singleOptions} for:item="option">
|
|
23
|
+
<button
|
|
24
|
+
key={option.id}
|
|
25
|
+
type="button"
|
|
26
|
+
class={option.className}
|
|
27
|
+
role="option"
|
|
28
|
+
aria-selected={option.selected}
|
|
29
|
+
data-id={option.id}
|
|
30
|
+
onclick={onSingleSelect}
|
|
31
|
+
>
|
|
32
|
+
{option.name}
|
|
33
|
+
</button>
|
|
34
|
+
</template>
|
|
35
|
+
</template>
|
|
36
|
+
<template if:true={isCheckboxList}>
|
|
22
37
|
<template for:each={filterMenuOptions} for:item="option">
|
|
23
38
|
<dx-checkbox
|
|
24
39
|
key={option.id}
|
|
@@ -11,6 +11,10 @@ export default class FilterMenu extends LightningElement {
|
|
|
11
11
|
@api header: string = "Filter Menu";
|
|
12
12
|
@api variant: string = "base";
|
|
13
13
|
@api filtersDatesLoading?: boolean;
|
|
14
|
+
/** Render a single-choice list; the header shows the selected option. */
|
|
15
|
+
@api singleSelect: boolean = false;
|
|
16
|
+
/** Id of the selected option when singleSelect is set. */
|
|
17
|
+
@api value?: string;
|
|
14
18
|
|
|
15
19
|
@api
|
|
16
20
|
get options(): Option[] {
|
|
@@ -31,6 +35,31 @@ export default class FilterMenu extends LightningElement {
|
|
|
31
35
|
return this.variant === "nested";
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
get isCheckboxList() {
|
|
39
|
+
return this.isBaseVariant && !this.singleSelect;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get selectedOption() {
|
|
43
|
+
return this.options.find((o) => String(o.id) === this.value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get displayTitle() {
|
|
47
|
+
return (this.singleSelect && this.selectedOption?.name) || this.header;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get singleOptions() {
|
|
51
|
+
return this.options.map((o) => {
|
|
52
|
+
const selected = String(o.id) === this.value;
|
|
53
|
+
return {
|
|
54
|
+
...o,
|
|
55
|
+
selected,
|
|
56
|
+
className: selected
|
|
57
|
+
? "single-option single-option-selected"
|
|
58
|
+
: "single-option"
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
34
63
|
get showViewMoreBtn() {
|
|
35
64
|
return this.options.length > 20;
|
|
36
65
|
}
|
|
@@ -93,6 +122,20 @@ export default class FilterMenu extends LightningElement {
|
|
|
93
122
|
this.showMore = !this.showMore;
|
|
94
123
|
}
|
|
95
124
|
|
|
125
|
+
private onSingleSelect(e: any) {
|
|
126
|
+
const id = e.currentTarget.dataset.id;
|
|
127
|
+
const value = this.options.find((o) => String(o.id) === id);
|
|
128
|
+
this.template.querySelector(".nested")?.classList.remove("active");
|
|
129
|
+
this.template
|
|
130
|
+
.querySelector(".header-caret")
|
|
131
|
+
?.classList.remove("caret-down");
|
|
132
|
+
this.dispatchEvent(
|
|
133
|
+
new CustomEvent("change", {
|
|
134
|
+
detail: { name: this.name, value, checked: true }
|
|
135
|
+
})
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
96
139
|
private onChange(e: any) {
|
|
97
140
|
const { checked, value } = e.detail;
|
|
98
141
|
this.dispatchEvent(
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import "dxHelpers/text";
|
|
2
|
+
|
|
1
3
|
:host {
|
|
2
4
|
display: block;
|
|
3
5
|
font-family: var(--dx-g-font-sans);
|
|
@@ -42,56 +44,68 @@
|
|
|
42
44
|
margin-top: var(--dx-g-spacing-md);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
/* Body
|
|
47
|
+
/* Body --------------------------------------------------------------- */
|
|
46
48
|
.dx-search-body {
|
|
47
49
|
margin: 0 auto;
|
|
48
50
|
max-width: 1200px;
|
|
49
51
|
padding: var(--dx-g-spacing-xl);
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
.dx-search-
|
|
54
|
+
.dx-search-layout {
|
|
53
55
|
display: flex;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
align-items: flex-start;
|
|
57
|
+
gap: var(--dx-g-spacing-2xl);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.dx-search-filters {
|
|
61
|
+
flex: 0 0 280px;
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
57
64
|
gap: var(--dx-g-spacing-md);
|
|
58
|
-
margin-bottom: var(--dx-g-spacing-lg);
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
.dx-
|
|
67
|
+
.dx-filter-header {
|
|
62
68
|
display: flex;
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
justify-content: space-between;
|
|
70
|
+
align-items: baseline;
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
.dx-
|
|
68
|
-
|
|
69
|
-
color: var(--dx-g-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
.dx-filter-title {
|
|
74
|
+
margin: 0;
|
|
75
|
+
color: var(--dx-g-text-heading-color);
|
|
76
|
+
font-family: var(--dx-g-font-display);
|
|
77
|
+
font-size: var(--dx-g-text-lg);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.dx-filter-clear {
|
|
81
|
+
color: var(--dx-g-blue-vibrant-50);
|
|
82
|
+
font-family: var(--dx-g-font-display);
|
|
73
83
|
font-size: var(--dx-g-text-sm);
|
|
74
|
-
cursor: pointer;
|
|
75
84
|
}
|
|
76
85
|
|
|
77
|
-
.dx-
|
|
78
|
-
|
|
86
|
+
.dx-filter-clear:disabled {
|
|
87
|
+
opacity: 0.4;
|
|
88
|
+
cursor: default;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
.dx-
|
|
82
|
-
|
|
83
|
-
color: white;
|
|
84
|
-
font-weight: var(--dx-g-font-demi);
|
|
91
|
+
.dx-search-range {
|
|
92
|
+
margin: 0 0 var(--dx-g-spacing-lg);
|
|
85
93
|
}
|
|
86
94
|
|
|
87
|
-
.dx-
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
.dx-search-main {
|
|
96
|
+
flex: 1 1 0;
|
|
97
|
+
min-width: 0;
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
@media (max-width: 768px) {
|
|
101
|
+
.dx-search-layout {
|
|
102
|
+
flex-direction: column;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.dx-search-filters {
|
|
106
|
+
flex-basis: auto;
|
|
107
|
+
width: 100%;
|
|
108
|
+
}
|
|
95
109
|
}
|
|
96
110
|
|
|
97
111
|
/* Status states -------------------------------------------------------- */
|
|
@@ -113,49 +127,30 @@
|
|
|
113
127
|
}
|
|
114
128
|
|
|
115
129
|
.dx-result {
|
|
116
|
-
background: white;
|
|
117
|
-
border-radius: 16px;
|
|
118
|
-
border: 1px solid rgb(24 24 24 / 4%);
|
|
119
|
-
box-shadow: 0 0 2px 0 rgb(24 24 24 / 8%), 0 2px 4px 1px rgb(24 24 24 / 16%);
|
|
120
|
-
padding: 20px;
|
|
121
|
-
margin-bottom: var(--dx-g-spacing-lg);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.dx-result-info {
|
|
125
130
|
display: flex;
|
|
126
|
-
|
|
127
|
-
|
|
131
|
+
flex-direction: column;
|
|
132
|
+
align-items: flex-start;
|
|
133
|
+
gap: var(--dx-g-spacing-smd);
|
|
134
|
+
border-bottom: 1px solid var(--sds-g-gray-4);
|
|
135
|
+
padding-bottom: var(--dx-g-spacing-xl);
|
|
136
|
+
margin-bottom: var(--dx-g-spacing-xl);
|
|
128
137
|
}
|
|
129
138
|
|
|
130
|
-
.dx-
|
|
131
|
-
|
|
132
|
-
align-items: center;
|
|
133
|
-
border-radius: 4px;
|
|
134
|
-
padding: 2px 8px;
|
|
135
|
-
font-size: var(--dx-g-text-xs);
|
|
136
|
-
background-color: var(--dx-g-blue-vibrant-95);
|
|
137
|
-
color: var(--dx-g-blue-vibrant-20);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.dx-result-title {
|
|
141
|
-
color: var(--dx-g-blue-vibrant-20);
|
|
142
|
-
display: block;
|
|
143
|
-
font-family: var(--dx-g-font-display);
|
|
144
|
-
font-size: var(--dx-g-text-lg);
|
|
145
|
-
margin: 0 0 var(--dx-g-spacing-sm);
|
|
139
|
+
.dx-result-title:hover {
|
|
140
|
+
--dx-c-card-title-color: var(--dx-g-blue-vibrant-40);
|
|
146
141
|
}
|
|
147
142
|
|
|
148
143
|
.dx-result-date {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
margin: 0 0 var(--dx-g-spacing-xs);
|
|
144
|
+
margin: 0;
|
|
145
|
+
text-align: start;
|
|
152
146
|
}
|
|
153
147
|
|
|
154
148
|
.dx-result-excerpt {
|
|
155
|
-
color: var(--dx-g-gray-10);
|
|
156
|
-
font-size: 14px;
|
|
157
|
-
line-height: 20px;
|
|
158
149
|
margin: 0;
|
|
150
|
+
display: box;
|
|
151
|
+
-webkit-line-clamp: 3;
|
|
152
|
+
-webkit-box-orient: vertical;
|
|
153
|
+
overflow: hidden;
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
/* Pagination ----------------------------------------------------------- */
|
|
@@ -12,133 +12,154 @@
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
14
|
<div class="dx-search-body">
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
role="group"
|
|
21
|
-
aria-label="Filter by content type"
|
|
22
|
-
>
|
|
23
|
-
<template for:each={facetChips} for:item="chip">
|
|
15
|
+
<div class="dx-search-layout">
|
|
16
|
+
<!-- Sidebar: content-type filter + language (like content archive) -->
|
|
17
|
+
<aside class="dx-search-filters" aria-label="Search filters">
|
|
18
|
+
<div class="dx-filter-header">
|
|
19
|
+
<p class="dx-filter-title">Filters</p>
|
|
24
20
|
<button
|
|
25
|
-
key={chip.value}
|
|
26
21
|
type="button"
|
|
27
|
-
class=
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
onclick={handleFacetClick}
|
|
22
|
+
class="dx-filter-clear"
|
|
23
|
+
disabled={noActiveFilters}
|
|
24
|
+
onclick={handleClearFilters}
|
|
31
25
|
>
|
|
32
|
-
|
|
33
|
-
<span class="dx-facet-chip-count">
|
|
34
|
-
{chip.count}
|
|
35
|
-
</span>
|
|
26
|
+
Clear all
|
|
36
27
|
</button>
|
|
37
|
-
</template>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
<div class="dx-search-controls">
|
|
41
|
-
<div if:true={showLocaleSelector} class="dx-search-locale">
|
|
42
|
-
<dx-select
|
|
43
|
-
label="Language"
|
|
44
|
-
options={localeSelectOptions}
|
|
45
|
-
value={localeValue}
|
|
46
|
-
onchange={handleLocaleChange}
|
|
47
|
-
></dx-select>
|
|
48
28
|
</div>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
29
|
+
<dx-filter-menu
|
|
30
|
+
if:true={hasFacets}
|
|
31
|
+
class="dx-filter-type"
|
|
32
|
+
name="contentType"
|
|
33
|
+
header="Content Type"
|
|
34
|
+
single-select
|
|
35
|
+
options={typeFilterOptions}
|
|
36
|
+
value={selectedTypeValue}
|
|
37
|
+
onchange={handleTypeFilterChange}
|
|
38
|
+
></dx-filter-menu>
|
|
39
|
+
<dx-filter-menu
|
|
40
|
+
if:true={showLocaleSelector}
|
|
41
|
+
class="dx-filter-locale"
|
|
42
|
+
name="language"
|
|
43
|
+
header="Language"
|
|
44
|
+
single-select
|
|
45
|
+
options={localeFilterOptions}
|
|
46
|
+
value={localeValue}
|
|
47
|
+
onchange={handleLocaleChange}
|
|
48
|
+
></dx-filter-menu>
|
|
49
|
+
</aside>
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
<div class="dx-search-main">
|
|
52
|
+
<p
|
|
53
|
+
if:true={showRange}
|
|
54
|
+
class="dx-search-range dx-text-body-2"
|
|
55
|
+
aria-live="polite"
|
|
56
|
+
>
|
|
57
|
+
Showing {rangeStart} - {rangeEnd} of {total}
|
|
58
|
+
</p>
|
|
59
|
+
<!-- Loading -->
|
|
60
|
+
<template if:true={isLoading}>
|
|
61
|
+
<div class="dx-search-status" aria-live="polite">
|
|
62
|
+
<dx-spinner
|
|
63
|
+
size="medium"
|
|
64
|
+
variant="base"
|
|
65
|
+
></dx-spinner>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
69
|
+
<!-- Idle prompt (no query yet) -->
|
|
70
|
+
<template if:true={isIdle}>
|
|
71
|
+
<div class="dx-search-status" aria-live="polite">
|
|
72
|
+
<dx-empty-state
|
|
73
|
+
header="Search the developer site"
|
|
74
|
+
subtitle="Enter a search term to get started."
|
|
75
|
+
variant="alt"
|
|
76
|
+
></dx-empty-state>
|
|
77
|
+
</div>
|
|
78
|
+
</template>
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
<!-- Empty (query ran, no results) -->
|
|
81
|
+
<template if:true={isEmpty}>
|
|
82
|
+
<div class="dx-search-status" aria-live="polite">
|
|
83
|
+
<dx-empty-state
|
|
84
|
+
header="No results found"
|
|
85
|
+
subtitle="Try different keywords or check your spelling."
|
|
86
|
+
variant="alt"
|
|
87
|
+
></dx-empty-state>
|
|
88
|
+
</div>
|
|
89
|
+
</template>
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
<!-- Error -->
|
|
92
|
+
<template if:true={isError}>
|
|
93
|
+
<div
|
|
94
|
+
class="dx-search-status dx-search-error"
|
|
95
|
+
role="alert"
|
|
96
|
+
>
|
|
97
|
+
<p>{errorMessage}</p>
|
|
98
|
+
</div>
|
|
99
|
+
</template>
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if:true={result.hasBadge}
|
|
103
|
-
class="dx-result-info"
|
|
101
|
+
<!-- Results -->
|
|
102
|
+
<template if:true={hasResults}>
|
|
103
|
+
<ul class="dx-result-list">
|
|
104
|
+
<template
|
|
105
|
+
for:each={displayResults}
|
|
106
|
+
for:item="result"
|
|
104
107
|
>
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
<li key={result.key} class="dx-result">
|
|
109
|
+
<dx-type-badge
|
|
110
|
+
if:true={result.hasBadge}
|
|
111
|
+
class="dx-result-badge"
|
|
112
|
+
variant={result.contentType}
|
|
113
|
+
value={result.contentTypeLabel}
|
|
114
|
+
size="small"
|
|
115
|
+
></dx-type-badge>
|
|
116
|
+
<dx-card-title
|
|
117
|
+
class="dx-result-title"
|
|
118
|
+
href={result.href}
|
|
119
|
+
header={result.title}
|
|
120
|
+
></dx-card-title>
|
|
121
|
+
<p
|
|
122
|
+
if:true={result.hasDate}
|
|
123
|
+
class="dx-result-date dx-text-label-1-dark"
|
|
124
|
+
>
|
|
125
|
+
{result.displayDate}
|
|
126
|
+
</p>
|
|
127
|
+
<!-- Highlighted snippet (P4.5): innerHTML set in
|
|
116
128
|
renderedCallback, keyed by data-snippet-key. -->
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
129
|
+
<template lwc:if={result.hasSnippetHtml}>
|
|
130
|
+
<p
|
|
131
|
+
class="dx-result-excerpt dx-text-body-2"
|
|
132
|
+
data-snippet-key={result.key}
|
|
133
|
+
lwc:dom="manual"
|
|
134
|
+
></p>
|
|
135
|
+
</template>
|
|
136
|
+
<template
|
|
137
|
+
lwc:elseif={result.hasDescription}
|
|
138
|
+
>
|
|
139
|
+
<p
|
|
140
|
+
class="dx-result-excerpt dx-text-body-2"
|
|
141
|
+
>
|
|
142
|
+
{result.description}
|
|
143
|
+
</p>
|
|
144
|
+
</template>
|
|
145
|
+
</li>
|
|
123
146
|
</template>
|
|
124
|
-
|
|
125
|
-
<p class="dx-result-excerpt">
|
|
126
|
-
{result.description}
|
|
127
|
-
</p>
|
|
128
|
-
</template>
|
|
129
|
-
</li>
|
|
130
|
-
</template>
|
|
131
|
-
</ul>
|
|
147
|
+
</ul>
|
|
132
148
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
<div
|
|
150
|
+
if:true={showPagination}
|
|
151
|
+
class="dx-pagination-container"
|
|
152
|
+
>
|
|
153
|
+
<dx-pagination
|
|
154
|
+
current-page={currentPage}
|
|
155
|
+
total-pages={totalPages}
|
|
156
|
+
pages-to-show="5"
|
|
157
|
+
onpagechange={handlePageChange}
|
|
158
|
+
></dx-pagination>
|
|
159
|
+
</div>
|
|
160
|
+
</template>
|
|
140
161
|
</div>
|
|
141
|
-
</
|
|
162
|
+
</div>
|
|
142
163
|
</div>
|
|
143
164
|
</div>
|
|
144
165
|
</template>
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sample /api/search response for the "apex" query, used by the WithResults
|
|
3
|
+
* story. Shared fields are filled in by `row()`. The two blog rows are
|
|
4
|
+
* invented so the "blog" filter has something to show; the facet counts are
|
|
5
|
+
* from the real response.
|
|
6
|
+
*/
|
|
7
|
+
const DEV = "https://developer.salesforce.com/";
|
|
8
|
+
const G = "Apex Developer Guide";
|
|
9
|
+
|
|
10
|
+
interface Row {
|
|
11
|
+
url: string;
|
|
12
|
+
title: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
contentType?: string;
|
|
15
|
+
lastmod?: string | null;
|
|
16
|
+
matchType?: string;
|
|
17
|
+
sectionTitle?: string | null;
|
|
18
|
+
sectionHash?: string | null;
|
|
19
|
+
snippet: string;
|
|
20
|
+
snippetSource?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const row = (r: Row, i: number) => ({
|
|
24
|
+
url: r.url,
|
|
25
|
+
title: r.title,
|
|
26
|
+
description: r.description ?? G,
|
|
27
|
+
locale: "en-us",
|
|
28
|
+
site: "developer",
|
|
29
|
+
contentType: r.contentType ?? "docs",
|
|
30
|
+
lastmod: r.lastmod ?? null,
|
|
31
|
+
score: 2 - i * 0.04,
|
|
32
|
+
lexScore: 18,
|
|
33
|
+
semScore: 0.45,
|
|
34
|
+
matchType: r.matchType ?? "hybrid",
|
|
35
|
+
sectionUrl: r.sectionHash ? `${r.url}#${r.sectionHash}` : null,
|
|
36
|
+
sectionTitle: r.sectionTitle ?? null,
|
|
37
|
+
snippet: r.snippet,
|
|
38
|
+
snippetSource: r.snippetSource ?? "headline"
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const APEX = `${DEV}docs/platform/apex-dev/references/apex-dev/`;
|
|
42
|
+
const REF = `${DEV}docs/platform/apex-ref/references`;
|
|
43
|
+
const CLI = `${DEV}docs/platform/salesforce-cli-reference/guide/`;
|
|
44
|
+
|
|
45
|
+
const ROWS: Row[] = [
|
|
46
|
+
{
|
|
47
|
+
url: `${APEX}apex-intro.html`,
|
|
48
|
+
title: `Introducing Apex | ${G}`,
|
|
49
|
+
snippet:
|
|
50
|
+
"Introducing <b>Apex</b> | <b>Apex</b> Developer Guide\n\nof hosting server code, such as Java or .NET, in a secure and robust environment. What is <b>Apex</b>?"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
url: `${APEX}apex-intro-what-is-apex.html`,
|
|
54
|
+
title: `What is Apex? | ${G}`,
|
|
55
|
+
snippet: "What is <b>Apex</b>?"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
url: `${APEX}connectapi-overview.html`,
|
|
59
|
+
title: `Connect in Apex | ${G}`,
|
|
60
|
+
snippet:
|
|
61
|
+
"Connect in <b>Apex</b> | <b>Apex</b> Developer Guide\n\nConnect in <b>Apex</b> Use Connect in <b>Apex</b> to develop custom experiences in Salesforce."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
url: `${CLI}cli_reference_apex_run.html`,
|
|
65
|
+
title: "apex run | apex Commands",
|
|
66
|
+
description:
|
|
67
|
+
"Execute anonymous Apex code entered on the command line or from a local file.",
|
|
68
|
+
matchType: "lexical",
|
|
69
|
+
snippet:
|
|
70
|
+
"<b>apex</b> run | <b>apex</b> Commands\n\n<b>apex</b> run Execute anonymous <b>Apex</b> code entered on the command line or from a local file."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
url: `${DEV}docs/platform/salesforce-slack-sdk/guide/apex_ref.html`,
|
|
74
|
+
title: "Apex | Apex SDK for Slack (Beta)",
|
|
75
|
+
description: "Use Apex classes in the",
|
|
76
|
+
matchType: "lexical",
|
|
77
|
+
snippet:
|
|
78
|
+
"<b>Apex</b> | <b>Apex</b> SDK for Slack (Beta)\n\nk.ActionDispatcher Commands: Slack.SlashCommandDispatcher Events: Slack.EventDispatcher Shortcuts: Slack.ShortcutDispatcher To determine which classes and methods you"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
url: `${DEV}developer-centers/apex`,
|
|
82
|
+
title: "Apex",
|
|
83
|
+
description:
|
|
84
|
+
"Explore the developer resources for Apex to write server-side logic with classes, triggers, and services.",
|
|
85
|
+
contentType: "page",
|
|
86
|
+
lastmod: "2026-10-09T20:57:17.000Z",
|
|
87
|
+
matchType: "lexical",
|
|
88
|
+
snippet:
|
|
89
|
+
"Read more Developer Guide Debug, Test, and Deploy <b>Apex</b> Develop your <b>Apex</b> code in a sandbox, debug it, unit-test it"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
url: `${APEX}apex-dev-guide.html`,
|
|
93
|
+
title: `Apex Developer Guide | ${G}`,
|
|
94
|
+
snippet:
|
|
95
|
+
"<b>Apex</b> Developer Guide | <b>Apex</b> Developer Guide\n\nthe Salesforce Release Notes to learn about the most recent updates and changes to <b>Apex</b>."
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
url: APEX.slice(0, -1),
|
|
99
|
+
title: `Apex Developer Guide | ${G}`,
|
|
100
|
+
snippet:
|
|
101
|
+
"<b>Apex</b> Developer Guide | <b>Apex</b> Developer Guide\n\nthe Salesforce Release Notes to learn about the most recent updates and changes to <b>Apex</b>."
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
url: `${DEV}docs/platform/apex-dev`,
|
|
105
|
+
title: `Apex Developer Guide | ${G}`,
|
|
106
|
+
snippet:
|
|
107
|
+
"You can run <b>Apex</b> code using a variety of mechanisms. <b>Apex</b> code runs in atomic transactions."
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
url: `${CLI}cli_reference_apex_run_test.html`,
|
|
111
|
+
title: "apex run test | apex Commands",
|
|
112
|
+
description: "Invoke Apex tests in an org.",
|
|
113
|
+
matchType: "lexical",
|
|
114
|
+
sectionHash: "aliases-for-apex-run-test",
|
|
115
|
+
sectionTitle: "Aliases for apex run test",
|
|
116
|
+
snippet:
|
|
117
|
+
"<b>apex</b> run test | <b>apex</b> Commands — Aliases for <b>apex</b> run test\n\nd if the target-org configuration variable is already set."
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
url: `${APEX}apex-intro-learning-apex.html`,
|
|
121
|
+
title: `Learning Apex | ${G}`,
|
|
122
|
+
matchType: "lexical",
|
|
123
|
+
sectionHash: "in-this-guide-apex-developer-guide",
|
|
124
|
+
sectionTitle: "In This Guide (Apex Developer Guide)",
|
|
125
|
+
snippet:
|
|
126
|
+
"Learning <b>Apex</b> | <b>Apex</b> Developer Guide — In This Guide (<b>Apex</b> Developer Guide)\n\nIn This Guide (<b>Apex</b> Developer Guide) Beginning programmers can look at the following: Introducing <b>Apex</b> , and in particular:"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
url: `${APEX}apex-running.html`,
|
|
130
|
+
title: `Running Apex | ${G}`,
|
|
131
|
+
matchType: "lexical",
|
|
132
|
+
snippet:
|
|
133
|
+
"Running <b>Apex</b> | <b>Apex</b> Developer Guide\n\nRunning <b>Apex</b> You can access many features of the Salesforce user interface programmatically in <b>Apex</b>, and you can integrate with external SOAP and REST Web services."
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
url: `${APEX}apex-testing.html`,
|
|
137
|
+
title: `Testing Apex | ${G}`,
|
|
138
|
+
matchType: "lexical",
|
|
139
|
+
snippet:
|
|
140
|
+
"Testing <b>Apex</b> | <b>Apex</b> Developer Guide\n\ne tests. You can use it to test classes in isolation, which is important for unit testing."
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
url: `${APEX}apex-scheduler.html`,
|
|
144
|
+
title: `Apex Scheduler | ${G}`,
|
|
145
|
+
matchType: "lexical",
|
|
146
|
+
sectionHash: "implementing-the-schedulable-interface",
|
|
147
|
+
sectionTitle: "Implementing the Schedulable Interface",
|
|
148
|
+
snippet:
|
|
149
|
+
"<b>Apex</b> Scheduler | <b>Apex</b> Developer Guide — Implementing the Schedulable Interface\n\nImplementing the Schedulable Interface To schedule an <b>Apex</b> class to run at regular intervals, first write an <b>Apex</b> class that"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
url: `${DEV}docs/platform/apex-ref/references/apex-ref`,
|
|
153
|
+
title: "Apex Reference Guide",
|
|
154
|
+
description: "Apex Reference Guide",
|
|
155
|
+
lastmod: "2026-11-03T01:09:58.000Z",
|
|
156
|
+
matchType: "semantic",
|
|
157
|
+
snippet: "Apex Reference Guide",
|
|
158
|
+
snippetSource: "description"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
url: `${REF}/apex-ref/apex-ref-guide.html`,
|
|
162
|
+
title: "Apex Reference Guide",
|
|
163
|
+
description: "Apex Reference Guide",
|
|
164
|
+
lastmod: "2026-11-03T01:10:03.000Z",
|
|
165
|
+
matchType: "semantic",
|
|
166
|
+
snippet: "Apex Reference Guide",
|
|
167
|
+
snippetSource: "description"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
url: `${REF}/apex-ref/v68.0`,
|
|
171
|
+
title: "Apex Reference Guide",
|
|
172
|
+
description: "Apex Reference Guide",
|
|
173
|
+
lastmod: "2026-11-03T01:10:03.000Z",
|
|
174
|
+
matchType: "semantic",
|
|
175
|
+
snippet: "Apex Reference Guide",
|
|
176
|
+
snippetSource: "description"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
url: REF,
|
|
180
|
+
title: "Apex Reference Guide",
|
|
181
|
+
description: "Apex Reference Guide",
|
|
182
|
+
lastmod: "2026-11-03T01:10:03.000Z",
|
|
183
|
+
matchType: "semantic",
|
|
184
|
+
snippet: "Apex Reference Guide",
|
|
185
|
+
snippetSource: "description"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
url: `${DEV}docs/industries/industries-common-dev/guide/omnistudio-apex-reference.html`,
|
|
189
|
+
title: "Omnistudio Apex Reference | Industries Common Resources | Industries Common Resources Developer Guide",
|
|
190
|
+
description:
|
|
191
|
+
"Apex is a strongly typed, object-oriented programming language that allows developers to execute flow and transaction control statements on the Salesf",
|
|
192
|
+
matchType: "semantic",
|
|
193
|
+
snippet:
|
|
194
|
+
"Apex is a strongly typed, object-oriented programming language that allows developers to execute flow and transaction control statements on the Salesf",
|
|
195
|
+
snippetSource: "description"
|
|
196
|
+
},
|
|
197
|
+
// Invented sample rows so the "blog" filter has results to show.
|
|
198
|
+
{
|
|
199
|
+
url: `${DEV}blogs/2026/09/apex-cursors-in-practice`,
|
|
200
|
+
title: "Apex Cursors in Practice",
|
|
201
|
+
description: "How to process large result sets with Apex cursors.",
|
|
202
|
+
contentType: "blog",
|
|
203
|
+
lastmod: "2026-09-18T00:00:00.000Z",
|
|
204
|
+
snippet: "Process large result sets with <b>Apex</b> cursors."
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
url: `${DEV}blogs/2026/06/apex-testing-tips`,
|
|
208
|
+
title: "Five Apex Testing Tips",
|
|
209
|
+
description: "Write faster, more reliable Apex tests.",
|
|
210
|
+
contentType: "blog",
|
|
211
|
+
lastmod: "2026-06-02T00:00:00.000Z",
|
|
212
|
+
snippet: "Write faster, more reliable <b>Apex</b> tests."
|
|
213
|
+
}
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
const ALL = ROWS.map(row);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Builds the response the stub returns, honouring the `type` filter and `lang`
|
|
220
|
+
* query params so the sidebar filters work in Storybook. Facet counts always
|
|
221
|
+
* reflect the full result set (disjunctive facets), as the real API does.
|
|
222
|
+
*/
|
|
223
|
+
export function mockSearchResponse(params: URLSearchParams) {
|
|
224
|
+
const type = params.get("type");
|
|
225
|
+
const results = type ? ALL.filter((r) => r.contentType === type) : ALL;
|
|
226
|
+
return {
|
|
227
|
+
query: params.get("q") ?? "apex",
|
|
228
|
+
locale: params.get("lang") ?? "en-us",
|
|
229
|
+
site: null,
|
|
230
|
+
sort: params.get("sort") ?? "relevance",
|
|
231
|
+
limit: 20,
|
|
232
|
+
offset: 0,
|
|
233
|
+
total: type ? results.length : 59,
|
|
234
|
+
count: results.length,
|
|
235
|
+
facets: {
|
|
236
|
+
contentType: [
|
|
237
|
+
{ value: "docs", count: 56 },
|
|
238
|
+
{ value: "blog", count: 2 },
|
|
239
|
+
{ value: "page", count: 1 }
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
results
|
|
243
|
+
};
|
|
244
|
+
}
|
|
@@ -7,11 +7,8 @@ import type { LocaleOption } from "docUtils/searchLocale";
|
|
|
7
7
|
import {
|
|
8
8
|
decodeHtmlEntities,
|
|
9
9
|
highlightedSnippetHtml,
|
|
10
|
-
isSortOption,
|
|
11
10
|
resultHref,
|
|
12
|
-
|
|
13
|
-
type SearchResult,
|
|
14
|
-
type SortOption
|
|
11
|
+
type SearchResult
|
|
15
12
|
} from "docUtils/searchClient";
|
|
16
13
|
import { searchLocalePrefs } from "dxUtils/searchLocalePrefs";
|
|
17
14
|
import { track as trackGTM } from "dxUtils/analytics";
|
|
@@ -23,11 +20,19 @@ import { parseSupportedLocales } from "docUtils/searchLocale";
|
|
|
23
20
|
// are ingested under this site value).
|
|
24
21
|
const DX_SITE = "developer";
|
|
25
22
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
// The search backend labels developer docs "docs"; the badge and label
|
|
24
|
+
// constants know them as "documentation". Filtering still sends the raw value.
|
|
25
|
+
const CONTENT_TYPE_ALIASES: Record<string, string> = {
|
|
26
|
+
docs: "documentation",
|
|
27
|
+
page: "website"
|
|
29
28
|
};
|
|
30
29
|
|
|
30
|
+
function normalizeContentType(contentType: string | null): string | null {
|
|
31
|
+
return contentType != null
|
|
32
|
+
? CONTENT_TYPE_ALIASES[contentType] ?? contentType
|
|
33
|
+
: null;
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
interface DisplayResult {
|
|
32
37
|
key: string;
|
|
33
38
|
url: string;
|
|
@@ -42,6 +47,7 @@ interface DisplayResult {
|
|
|
42
47
|
// text path renders exactly as before.
|
|
43
48
|
snippetHtml: string | null;
|
|
44
49
|
hasSnippetHtml: boolean;
|
|
50
|
+
contentType: string | null;
|
|
45
51
|
contentTypeLabel: string | null;
|
|
46
52
|
hasBadge: boolean;
|
|
47
53
|
displayDate: string;
|
|
@@ -56,7 +62,7 @@ interface FacetChip {
|
|
|
56
62
|
cssClass: string;
|
|
57
63
|
}
|
|
58
64
|
|
|
59
|
-
interface
|
|
65
|
+
interface SelectOption {
|
|
60
66
|
value: string;
|
|
61
67
|
label: string;
|
|
62
68
|
}
|
|
@@ -162,7 +168,8 @@ export default class SearchHybrid extends LightningElement {
|
|
|
162
168
|
r.description != null && r.description !== ""
|
|
163
169
|
? decodeHtmlEntities(r.description)
|
|
164
170
|
: null;
|
|
165
|
-
const
|
|
171
|
+
const contentType = normalizeContentType(r.contentType);
|
|
172
|
+
const label = this.contentTypeLabel(contentType);
|
|
166
173
|
const displayDate = this.formatDate(r.lastmod);
|
|
167
174
|
// Prefer the highlighted snippet (headline source only); otherwise
|
|
168
175
|
// null → the description text path below renders unchanged.
|
|
@@ -176,6 +183,7 @@ export default class SearchHybrid extends LightningElement {
|
|
|
176
183
|
hasDescription: description !== null,
|
|
177
184
|
snippetHtml,
|
|
178
185
|
hasSnippetHtml: snippetHtml !== null,
|
|
186
|
+
contentType,
|
|
179
187
|
contentTypeLabel: label,
|
|
180
188
|
hasBadge: label !== null,
|
|
181
189
|
displayDate,
|
|
@@ -240,8 +248,9 @@ export default class SearchHybrid extends LightningElement {
|
|
|
240
248
|
if (contentType == null || contentType === "") {
|
|
241
249
|
return null;
|
|
242
250
|
}
|
|
251
|
+
const normalized = normalizeContentType(contentType) as string;
|
|
243
252
|
const labels = CONTENT_TYPE_LABELS as Record<string, string>;
|
|
244
|
-
return labels[
|
|
253
|
+
return labels[normalized] ?? contentType;
|
|
245
254
|
}
|
|
246
255
|
|
|
247
256
|
// ---- content-type facet chips (disjunctive) ---------------------------
|
|
@@ -269,24 +278,51 @@ export default class SearchHybrid extends LightningElement {
|
|
|
269
278
|
return this.facetChips.length > 0;
|
|
270
279
|
}
|
|
271
280
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
281
|
+
/** Options for the sidebar dx-filter-menu (single-select by content type, sent to the API as `type`). */
|
|
282
|
+
get typeFilterOptions(): Array<{
|
|
283
|
+
id: string;
|
|
284
|
+
name: string;
|
|
285
|
+
value: string;
|
|
286
|
+
}> {
|
|
287
|
+
return this.facetChips.map((chip) => ({
|
|
288
|
+
id: chip.value,
|
|
289
|
+
name: `${chip.label} (${chip.count})`,
|
|
290
|
+
value: chip.value
|
|
278
291
|
}));
|
|
279
292
|
}
|
|
280
293
|
|
|
281
|
-
get
|
|
282
|
-
return this.vm?.
|
|
294
|
+
get selectedTypeValue(): string {
|
|
295
|
+
return this.vm?.selectedType ?? "";
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
get hasActiveType(): boolean {
|
|
299
|
+
return !!this.vm?.selectedType;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
get noActiveFilters(): boolean {
|
|
303
|
+
return !this.hasActiveType && this.localeValue === this.defaultLanguage;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
get showRange(): boolean {
|
|
307
|
+
return this.hasResults && this.total > 0;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
get rangeStart(): number {
|
|
311
|
+
return ((this.vm?.page ?? 1) - 1) * (this.vm?.limit ?? 10) + 1;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
get rangeEnd(): number {
|
|
315
|
+
const limit = this.vm?.limit ?? 10;
|
|
316
|
+
return Math.min(this.rangeStart + limit - 1, this.total);
|
|
283
317
|
}
|
|
284
318
|
|
|
319
|
+
// ---- locale select options -------------------------------------
|
|
320
|
+
|
|
285
321
|
get showLocaleSelector(): boolean {
|
|
286
322
|
return this.controller?.showLocaleSelector ?? false;
|
|
287
323
|
}
|
|
288
324
|
|
|
289
|
-
get localeSelectOptions():
|
|
325
|
+
get localeSelectOptions(): SelectOption[] {
|
|
290
326
|
const options = this.controller?.localeOptions ?? [];
|
|
291
327
|
return options.map((l: LocaleOption) => ({
|
|
292
328
|
value: l.id,
|
|
@@ -294,6 +330,13 @@ export default class SearchHybrid extends LightningElement {
|
|
|
294
330
|
}));
|
|
295
331
|
}
|
|
296
332
|
|
|
333
|
+
get localeFilterOptions(): Array<{ id: string; name: string }> {
|
|
334
|
+
return this.localeSelectOptions.map((o) => ({
|
|
335
|
+
id: o.value,
|
|
336
|
+
name: o.label
|
|
337
|
+
}));
|
|
338
|
+
}
|
|
339
|
+
|
|
297
340
|
get localeValue(): string {
|
|
298
341
|
return this.vm?.locale ?? this.defaultLanguage;
|
|
299
342
|
}
|
|
@@ -314,17 +357,29 @@ export default class SearchHybrid extends LightningElement {
|
|
|
314
357
|
|
|
315
358
|
// ---- event handlers ---------------------------------------------------
|
|
316
359
|
|
|
317
|
-
|
|
318
|
-
const value = event.detail?.value;
|
|
319
|
-
if (
|
|
320
|
-
this.controller?.
|
|
360
|
+
handleLocaleChange(event: CustomEvent<{ value?: { id?: string } }>): void {
|
|
361
|
+
const value = event.detail?.value?.id;
|
|
362
|
+
if (value) {
|
|
363
|
+
this.controller?.setLanguage(value);
|
|
321
364
|
}
|
|
322
365
|
}
|
|
323
366
|
|
|
324
|
-
|
|
325
|
-
|
|
367
|
+
handleTypeFilterChange(
|
|
368
|
+
event: CustomEvent<{ value?: { value?: string } }>
|
|
369
|
+
): void {
|
|
370
|
+
const value = event.detail?.value?.value;
|
|
326
371
|
if (value) {
|
|
327
|
-
|
|
372
|
+
// Disjunctive toggle: the controller clears it if already active.
|
|
373
|
+
this.controller?.setType(value);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
handleClearFilters(): void {
|
|
378
|
+
if (this.hasActiveType) {
|
|
379
|
+
this.controller?.setType(null);
|
|
380
|
+
}
|
|
381
|
+
if (this.localeValue !== this.defaultLanguage) {
|
|
382
|
+
this.controller?.setLanguage(this.defaultLanguage);
|
|
328
383
|
}
|
|
329
384
|
}
|
|
330
385
|
|