-
Notifications
You must be signed in to change notification settings - Fork 595
Expand file tree
/
Copy pathpost-reaction-component.ts
More file actions
125 lines (112 loc) · 3.88 KB
/
post-reaction-component.ts
File metadata and controls
125 lines (112 loc) · 3.88 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import {
createIssue as createGitHubIssue,
Issue,
loadIssueByNumber,
ReactionID,
Reactions,
reactionTypes,
toggleReaction,
User
} from './github';
import { EmptyReactions, reactionEmoji, reactionNames } from './reactions';
import { pageAttributes as page } from './page-attributes';
export class PostReactionComponent {
public readonly element: HTMLElement;
private readonly countAnchor: HTMLAnchorElement;
private readonly reactionListContainer: HTMLFormElement;
private reactions: Reactions = new EmptyReactions();
private reactionsCount: number = 0;
private issueURL: string = '';
constructor(
private user: User | null,
private issue: Issue | null,
private createIssueCallback: (issue: Issue) => Promise<null>
) {
this.element = document.createElement('section');
this.element.classList.add('post-reactions');
this.element.innerHTML = `
<header>
<a class="text-link" target="_blank"></a>
</header>
<form class="post-reaction-list BtnGroup" action="javascript:">
</form>`;
this.countAnchor = this.element.querySelector('header a') as HTMLAnchorElement;
this.reactionListContainer = this.element.querySelector('.post-reaction-list') as HTMLFormElement;
this.setIssue(this.issue)
this.render();
}
public setIssue(issue: Issue | null) {
this.issue = issue;
if (issue) {
this.reactions = issue.reactions;
this.reactionsCount = issue.reactions.total_count;
this.issueURL = issue.html_url;
this.render();
}
}
private setupSubmitHandler() {
const buttons = this.reactionListContainer.querySelectorAll('button');
function toggleButtons(disabled: boolean) {
buttons.forEach(b => b.disabled = disabled);
}
const handler = async (event: Event) => {
event.preventDefault();
const button = event.target as HTMLButtonElement;
toggleButtons(true);
const id = button.value as ReactionID;
const issueExists = !!this.issue;
if (!issueExists) {
const newIssue = await createGitHubIssue(
page.issueTerm as string,
page.url,
page.title,
page.description || '',
page.label
);
const issue = await loadIssueByNumber(newIssue.number);
this.issue = issue;
this.reactions = issue.reactions;
await this.createIssueCallback(issue);
}
const url = this.reactions.url;
const {deleted} = await toggleReaction(url, id);
const delta = deleted ? -1 : 1;
this.reactions[id] += delta;
this.reactions.total_count += delta;
this.issue!.reactions = this.reactions;
toggleButtons(false);
this.setIssue(this.issue);
}
buttons.forEach(b => b.addEventListener('click', handler, true))
}
private getSubmitButtons(): string {
function buttonFor(url: string, reaction: ReactionID, disabled: boolean, count: number): string {
return `
<button
type="submit"
action="javascript:"
formaction="${url}"
class="btn BtnGroup-item btn-outline post-reaction-button"
value="${reaction}"
aria-label="Toggle ${reactionNames[reaction]} reaction"
reaction-count="${count}"
${disabled ? 'disabled' : ''}>
${reactionEmoji[reaction]}
</button>`;
}
const issueLocked = this.issue ? this.issue.locked : false;
return reactionTypes
.map(id => buttonFor(this.reactions.url, id, !this.user || issueLocked, this.reactions[id]))
.join('')
}
private render() {
if (this.issueURL !== '') {
this.countAnchor.href = this.issueURL;
} else {
this.countAnchor.removeAttribute('href');
}
this.countAnchor.textContent = `${this.reactionsCount} Reaction${this.reactionsCount === 1 ? '' : 's'}`;
this.reactionListContainer.innerHTML = this.getSubmitButtons();
this.setupSubmitHandler();
}
}