blob: 14b2c73bb6e0e4a000ccb1e5355e5f2e2fa56ae8 [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4import {connectStore, store} from 'reducers/base.js';
5import * as users from 'reducers/users.js';
6import {stars} from 'reducers/stars.js';
7import {projectAndUserToStarName} from 'shared/converters.js';
8import {MrStar} from './mr-star.js';
9import 'shared/typedef.js';
10
11
12/**
13 * `<mr-project-star>`
14 *
15 * A button for starring a project.
16 *
17 */
18export class MrProjectStar extends connectStore(MrStar) {
19 /** @override */
20 static get properties() {
21 return {
22 /**
23 * Resource name of the project being starred.
24 */
25 name: {type: String},
26 /**
27 * List of all stars, indexed by star name.
28 */
29 _stars: {type: Object},
30 /**
31 * Whether project stars are currently being fetched.
32 */
33 _fetchingStars: {type: Boolean},
34 /**
35 * Request data for projects currently being starred.
36 */
37 _starringProjects: {type: Object},
38 /**
39 * Request data for projects currently being unstarred.
40 */
41 _unstarringProjects: {type: Object},
42 /**
43 * The currently logged in user. Required to determine if the user can
44 * star.
45 */
46 _currentUserName: {type: String},
47 };
48 }
49
50 /** @override */
51 constructor() {
52 super();
53 /** @type {string} */
54 this.name = undefined;
55
56 /** @type {boolean} */
57 this._fetchingStars = false;
58
59 /** @type {Object<ProjectStarName, ReduxRequestState>} */
60 this._starringProjects = {};
61
62 /** @type {Object<ProjectStarName, ReduxRequestState>} */
63 this._unstarringProjects = {};
64
65 /** @type {Object<StarName, Star>} */
66 this._stars = {};
67
68 /** @type {string} */
69 this._currentUserName = undefined;
70 }
71
72 /** @override */
73 stateChanged(state) {
74 this._currentUserName = users.currentUserName(state);
75
76 this._stars = stars.byName(state);
77
78 const requests = stars.requests(state);
79 this._fetchingStars = requests.listProjects.requesting;
80 this._starringProjects = requests.starProject;
81 this._unstarringProjects = requests.unstarProject;
82 }
83
84 /** @override */
85 get type() {
86 return 'project';
87 }
88
89 /**
90 * @return {string} The resource name of the ProjectStar.
91 */
92 get _starName() {
93 return projectAndUserToStarName(this.name, this._currentUserName);
94 }
95
96 /**
97 * @return {ProjectStar} The ProjectStar object for the referenced project,
98 * if one exists.
99 */
100 get _projectStar() {
101 const name = this._starName;
102 if (!(name in this._stars)) return {};
103 return this._stars[name];
104 }
105
106 /**
107 * @return {boolean} Whether there's an in-flight star request.
108 */
109 get _isStarring() {
110 const requestKey = this._starName;
111 if (requestKey in this._starringProjects &&
112 this._starringProjects[requestKey].requesting) {
113 return true;
114 }
115 if (requestKey in this._unstarringProjects &&
116 this._unstarringProjects[requestKey].requesting) {
117 return true;
118 }
119 return false;
120 }
121
122 /** @override */
123 get isLoggedIn() {
124 return !!this._currentUserName;
125 }
126
127 /** @override */
128 get requesting() {
129 return this._fetchingStars || this._isStarring;
130 }
131
132 /** @override */
133 get isStarred() {
134 return !!(this._projectStar && this._projectStar.name);
135 }
136
137 /** @override */
138 star() {
139 store.dispatch(stars.starProject(this.name, this._currentUserName));
140 }
141
142 /** @override */
143 unstar() {
144 store.dispatch(stars.unstarProject(this.name, this._currentUserName));
145 }
146}
147
148customElements.define('mr-project-star', MrProjectStar);