/
recommendation-list.class.tsx
99 lines (86 loc) · 2.83 KB
/
recommendation-list.class.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import {
buildRecommendationList,
RecommendationList as HeadlessRecommendationList,
RecommendationListOptions,
RecommendationListState,
loadClickAnalyticsActions,
Result,
Unsubscribe,
} from '@coveo/headless/recommendation';
import {Component, ContextType} from 'react';
import {AppContext} from '../../context/engine';
import {filterProtocol} from '../../utils/filter-protocol';
export class RecommendationList extends Component<
RecommendationListOptions,
RecommendationListState
> {
static contextType = AppContext;
context!: ContextType<typeof AppContext>;
private controller!: HeadlessRecommendationList;
private unsubscribe: Unsubscribe = () => {};
componentDidMount() {
this.controller = buildRecommendationList(
this.context.recommendationEngine!,
{options: this.props}
);
this.updateState();
this.unsubscribe = this.controller.subscribe(() => this.updateState());
}
componentWillUnmount() {
this.unsubscribe();
}
private updateState() {
this.setState(this.controller.state);
}
private logClick(recommendation: Result) {
const engine = this.context.recommendationEngine;
if (!engine) {
return;
}
const {logRecommendationOpen} = loadClickAnalyticsActions(engine);
engine.dispatch(logRecommendationOpen(recommendation));
}
render() {
if (!this.state) {
return null;
}
if (this.state.error) {
return (
<div>
<div>Oops {this.state.error.message}</div>
<code>{JSON.stringify(this.state.error)}</code>
<button onClick={() => this.controller.refresh()}>Try again</button>
</div>
);
}
if (!this.state.recommendations.length) {
return <button onClick={() => this.controller.refresh()}>Refresh</button>;
}
return (
<div>
<button onClick={() => this.controller.refresh()}>Refresh</button>
<ul style={{textAlign: 'left'}}>
{this.state.recommendations.map((recommendation) => (
<li key={recommendation.uniqueId}>
<article>
<h2>
{/* Make sure to log analytics when the result link is clicked. */}
<a
href={filterProtocol(recommendation.clickUri)} // Filters out dangerous URIs that can create XSS attacks such as `javascript:`.
onClick={() => this.logClick(recommendation)}
onContextMenu={() => this.logClick(recommendation)}
onMouseDown={() => this.logClick(recommendation)}
onMouseUp={() => this.logClick(recommendation)}
>
{recommendation.title}
</a>
</h2>
<p>{recommendation.excerpt}</p>
</article>
</li>
))}
</ul>
</div>
);
}
}