blob: 57a918377f123240b20642f7df0592e9dd6c4ada [file] [log] [blame]
Dave Borowitz8cdc76b2018-03-26 10:04:27 -04001/**
2 * @license
3 * Copyright (C) 2017 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Becky Siegel6db432f2017-08-25 09:17:42 -070017(function() {
18 'use strict';
19
Becky Siegel9640eb22017-12-11 15:58:57 -080020 const Defs = {};
21
Becky Siegel148c7b22018-01-16 15:01:58 -080022 const NOTHING_TO_SAVE = 'No changes to save.';
23
brohlfs3e364262019-04-08 16:37:22 +020024 const MAX_AUTOCOMPLETE_RESULTS = 50;
Becky Siegel8d7b6272018-03-28 09:38:29 -070025
Becky Siegel148c7b22018-01-16 15:01:58 -080026 /**
27 * Fired when save is a no-op
28 *
29 * @event show-alert
30 */
31
Becky Siegel9640eb22017-12-11 15:58:57 -080032 /**
33 * @typedef {{
34 * value: !Object,
35 * }}
36 */
37 Defs.rule;
38
39 /**
40 * @typedef {{
41 * rules: !Object<string, Defs.rule>
42 * }}
43 */
44 Defs.permission;
45
46 /**
47 * Can be an empty object or consist of permissions.
48 *
49 * @typedef {{
50 * permissions: !Object<string, Defs.permission>
51 * }}
52 */
53 Defs.permissions;
54
55 /**
56 * Can be an empty object or consist of permissions.
57 *
Becky Siegel148c7b22018-01-16 15:01:58 -080058 * @typedef {!Object<string, Defs.permissions>}
Becky Siegel9640eb22017-12-11 15:58:57 -080059 */
60 Defs.sections;
61
62 /**
63 * @typedef {{
Becky Siegel148c7b22018-01-16 15:01:58 -080064 * remove: !Defs.sections,
65 * add: !Defs.sections,
Becky Siegel9640eb22017-12-11 15:58:57 -080066 * }}
67 */
68 Defs.projectAccessInput;
69
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +010070 /**
71 * @appliesMixin Gerrit.AccessMixin
72 * @appliesMixin Gerrit.BaseUrlMixin
73 * @appliesMixin Gerrit.FireMixin
74 * @appliesMixin Gerrit.URLEncodingMixin
75 */
76 class GrRepoAccess extends Polymer.mixinBehaviors( [
77 Gerrit.AccessBehavior,
78 Gerrit.BaseUrlBehavior,
79 Gerrit.FireBehavior,
80 Gerrit.URLEncodingBehavior,
81 ], Polymer.GestureEventListeners(
82 Polymer.LegacyElementMixin(
83 Polymer.Element))) {
84 static get is() { return 'gr-repo-access'; }
Becky Siegel6db432f2017-08-25 09:17:42 -070085
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +010086 static get properties() {
87 return {
88 repo: {
89 type: String,
90 observer: '_repoChanged',
Becky Siegel8d7b6272018-03-28 09:38:29 -070091 },
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +010092 // The current path
93 path: String,
Becky Siegel6db432f2017-08-25 09:17:42 -070094
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +010095 _canUpload: {
96 type: Boolean,
97 value: false,
98 },
99 _inheritFromFilter: String,
100 _query: {
101 type: Function,
102 value() {
103 return this._getInheritFromSuggestions.bind(this);
104 },
105 },
106 _ownerOf: Array,
107 _capabilities: Object,
108 _groups: Object,
109 /** @type {?} */
110 _inheritsFrom: Object,
111 _labels: Object,
112 _local: Object,
113 _editing: {
114 type: Boolean,
115 value: false,
116 observer: '_handleEditingChanged',
117 },
118 _modified: {
119 type: Boolean,
120 value: false,
121 },
122 _sections: Array,
123 _weblinks: Array,
124 _loading: {
125 type: Boolean,
126 value: true,
127 },
128 };
129 }
Becky Siegel6db432f2017-08-25 09:17:42 -0700130
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100131 created() {
132 super.created();
133 this.addEventListener('access-modified',
134 () =>
135 this._handleAccessModified());
136 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800137
Becky Siegel9640eb22017-12-11 15:58:57 -0800138 _handleAccessModified() {
139 this._modified = true;
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100140 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800141
Becky Siegeledd3f892017-08-31 10:52:20 -0700142 /**
Paladox none2bd5c212017-11-16 18:54:02 +0000143 * @param {string} repo
Becky Siegeledd3f892017-08-31 10:52:20 -0700144 * @return {!Promise}
145 */
Paladox none2bd5c212017-11-16 18:54:02 +0000146 _repoChanged(repo) {
Paladox none685117922018-03-17 20:05:21 +0000147 this._loading = true;
148
Paladox none2bd5c212017-11-16 18:54:02 +0000149 if (!repo) { return Promise.resolve(); }
Paladox none70cb10c2018-02-17 19:12:09 +0000150
Becky Siegel6af63252018-04-26 14:02:36 -0700151 return this._reload(repo);
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100152 }
Becky Siegel6af63252018-04-26 14:02:36 -0700153
154 _reload(repo) {
Becky Siegel6db432f2017-08-25 09:17:42 -0700155 const promises = [];
Paladox none70cb10c2018-02-17 19:12:09 +0000156
157 const errFn = response => {
158 this.fire('page-error', {response});
159 };
160
Becky Siegel6af63252018-04-26 14:02:36 -0700161 this._editing = false;
162
Becky Siegel4d039c82017-11-07 10:56:55 -0800163 // Always reset sections when a project changes.
164 this._sections = [];
Paladox none70cb10c2018-02-17 19:12:09 +0000165 promises.push(this.$.restAPI.getRepoAccessRights(repo, errFn)
166 .then(res => {
167 if (!res) { return Promise.resolve(); }
Becky Siegel6db432f2017-08-25 09:17:42 -0700168
Becky Siegel8d7b6272018-03-28 09:38:29 -0700169 // Keep a copy of the original inherit from values separate from
170 // the ones data bound to gr-autocomplete, so the original value
171 // can be restored if the user cancels.
172 this._inheritsFrom = res.inherits_from ? Object.assign({},
173 res.inherits_from) : null;
174 this._originalInheritsFrom = res.inherits_from ? Object.assign({},
175 res.inherits_from) : null;
176 // Initialize the filter value so when the user clicks edit, the
177 // current value appears. If there is no parent repo, it is
178 // initialized as an empty string.
179 this._inheritFromFilter = res.inherits_from ?
Dmitrii Filippovb82003c2019-11-05 17:02:59 +0100180 this._inheritsFrom.name : '';
Paladox none70cb10c2018-02-17 19:12:09 +0000181 this._local = res.local;
182 this._groups = res.groups;
183 this._weblinks = res.config_web_links || [];
184 this._canUpload = res.can_upload;
Becky Siegele42689c2018-04-26 11:29:28 -0700185 this._ownerOf = res.owner_of || [];
Paladox none70cb10c2018-02-17 19:12:09 +0000186 return this.toSortedArray(this._local);
187 }));
Becky Siegel6db432f2017-08-25 09:17:42 -0700188
Paladox none70cb10c2018-02-17 19:12:09 +0000189 promises.push(this.$.restAPI.getCapabilities(errFn)
190 .then(res => {
191 if (!res) { return Promise.resolve(); }
192
193 return res;
194 }));
195
196 promises.push(this.$.restAPI.getRepo(repo, errFn)
197 .then(res => {
198 if (!res) { return Promise.resolve(); }
199
200 return res.labels;
201 }));
Becky Siegel6db432f2017-08-25 09:17:42 -0700202
Becky Siegel4d039c82017-11-07 10:56:55 -0800203 return Promise.all(promises).then(([sections, capabilities, labels]) => {
204 this._capabilities = capabilities;
205 this._labels = labels;
206 this._sections = sections;
Paladox none3f3770e2018-03-11 22:36:08 +0000207 this._loading = false;
Becky Siegel6db432f2017-08-25 09:17:42 -0700208 });
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100209 }
Paladox none635ef522018-03-29 20:38:23 +0000210
Becky Siegel8d7b6272018-03-28 09:38:29 -0700211 _handleUpdateInheritFrom(e) {
Becky Siegel8d7b6272018-03-28 09:38:29 -0700212 if (!this._inheritsFrom) {
213 this._inheritsFrom = {};
214 }
Wyatt Allen292d0132018-07-30 17:14:49 -0700215 this._inheritsFrom.id = e.detail.value;
Becky Siegel8d7b6272018-03-28 09:38:29 -0700216 this._inheritsFrom.name = this._inheritFromFilter;
217 this._handleAccessModified();
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100218 }
Becky Siegel8d7b6272018-03-28 09:38:29 -0700219
220 _getInheritFromSuggestions() {
221 return this.$.restAPI.getRepos(
222 this._inheritFromFilter,
223 MAX_AUTOCOMPLETE_RESULTS)
224 .then(response => {
225 const projects = [];
226 for (const key in response) {
227 if (!response.hasOwnProperty(key)) { continue; }
228 projects.push({
Patrick Hiesela26ca7f2018-08-28 11:42:41 +0200229 name: response[key].name,
Becky Siegel8d7b6272018-03-28 09:38:29 -0700230 value: response[key].id,
231 });
232 }
233 return projects;
234 });
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100235 }
Becky Siegel6db432f2017-08-25 09:17:42 -0700236
Paladox none3f3770e2018-03-11 22:36:08 +0000237 _computeLoadingClass(loading) {
238 return loading ? 'loading' : '';
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100239 }
Paladox none3f3770e2018-03-11 22:36:08 +0000240
Becky Siegel9640eb22017-12-11 15:58:57 -0800241 _handleEdit() {
242 this._editing = !this._editing;
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100243 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800244
245 _editOrCancel(editing) {
246 return editing ? 'Cancel' : 'Edit';
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100247 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800248
Becky Siegelbdb70cf2018-02-05 16:16:59 -0800249 _computeWebLinkClass(weblinks) {
Paladox noneed2e2272019-07-28 13:03:10 +0000250 return weblinks && weblinks.length ? 'show' : '';
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100251 }
Becky Siegelbdb70cf2018-02-05 16:16:59 -0800252
Paladox none635ef522018-03-29 20:38:23 +0000253 _computeShowInherit(inheritsFrom) {
Becky Siegel8d7b6272018-03-28 09:38:29 -0700254 return inheritsFrom ? 'show' : '';
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100255 }
Becky Siegel8d7b6272018-03-28 09:38:29 -0700256
Becky Siegel7c57cf92018-04-23 14:44:32 -0700257 _handleAddedSectionRemoved(e) {
258 const index = e.model.index;
259 this._sections = this._sections.slice(0, index)
260 .concat(this._sections.slice(index + 1, this._sections.length));
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100261 }
Becky Siegel7c57cf92018-04-23 14:44:32 -0700262
Becky Siegele6f68d92018-01-30 15:52:18 -0800263 _handleEditingChanged(editing, editingOld) {
264 // Ignore when editing gets set initially.
265 if (!editingOld || editing) { return; }
266 // Remove any unsaved but added refs.
Becky Siegel8d7b6272018-03-28 09:38:29 -0700267 if (this._sections) {
268 this._sections = this._sections.filter(p => !p.value.added);
269 }
270 // Restore inheritFrom.
271 if (this._inheritsFrom) {
272 this._inheritsFrom = Object.assign({}, this._originalInheritsFrom);
273 this._inheritFromFilter = this._inheritsFrom.name;
274 }
Becky Siegele6f68d92018-01-30 15:52:18 -0800275 for (const key of Object.keys(this._local)) {
276 if (this._local[key].added) {
277 delete this._local[key];
278 }
279 }
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100280 }
Becky Siegele6f68d92018-01-30 15:52:18 -0800281
Becky Siegel9640eb22017-12-11 15:58:57 -0800282 /**
Becky Siegel9640eb22017-12-11 15:58:57 -0800283 * @param {!Defs.projectAccessInput} addRemoveObj
Becky Siegela3ade7a2018-01-03 20:10:23 -0800284 * @param {!Array} path
285 * @param {string} type add or remove
286 * @param {!Object=} opt_value value to add if the type is 'add'
Becky Siegel9640eb22017-12-11 15:58:57 -0800287 * @return {!Defs.projectAccessInput}
288 */
Becky Siegela3ade7a2018-01-03 20:10:23 -0800289 _updateAddRemoveObj(addRemoveObj, path, type, opt_value) {
290 let curPos = addRemoveObj[type];
291 for (const item of path) {
292 if (!curPos[item]) {
293 if (item === path[path.length - 1] && type === 'remove') {
Becky Siegel0a3be392018-01-03 16:05:33 -0800294 if (path[path.length - 2] === 'permissions') {
295 curPos[item] = {rules: {}};
Becky Siegel148c7b22018-01-16 15:01:58 -0800296 } else if (path.length === 1) {
297 curPos[item] = {permissions: {}};
Becky Siegel0a3be392018-01-03 16:05:33 -0800298 } else {
Becky Siegel148c7b22018-01-16 15:01:58 -0800299 curPos[item] = {};
Becky Siegel0a3be392018-01-03 16:05:33 -0800300 }
Becky Siegela3ade7a2018-01-03 20:10:23 -0800301 } else if (item === path[path.length - 1] && type === 'add') {
302 curPos[item] = opt_value;
303 } else {
304 curPos[item] = {};
305 }
306 }
307 curPos = curPos[item];
308 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800309 return addRemoveObj;
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100310 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800311
Becky Siegel148c7b22018-01-16 15:01:58 -0800312 /**
313 * Used to recursively remove any objects with a 'deleted' bit.
314 */
315 _recursivelyRemoveDeleted(obj) {
316 for (const k in obj) {
Kasper Nilsson42442242018-04-04 13:52:26 -0700317 if (!obj.hasOwnProperty(k)) { continue; }
318
Becky Siegel148c7b22018-01-16 15:01:58 -0800319 if (typeof obj[k] == 'object') {
320 if (obj[k].deleted) {
321 delete obj[k];
322 return;
323 }
324 this._recursivelyRemoveDeleted(obj[k]);
325 }
326 }
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100327 }
Becky Siegel148c7b22018-01-16 15:01:58 -0800328
Becky Siegela3ade7a2018-01-03 20:10:23 -0800329 _recursivelyUpdateAddRemoveObj(obj, addRemoveObj, path = []) {
330 for (const k in obj) {
Kasper Nilsson42442242018-04-04 13:52:26 -0700331 if (!obj.hasOwnProperty(k)) { continue; }
Becky Siegela3ade7a2018-01-03 20:10:23 -0800332 if (typeof obj[k] == 'object') {
Becky Siegele6f68d92018-01-30 15:52:18 -0800333 const updatedId = obj[k].updatedId;
334 const ref = updatedId ? updatedId : k;
Becky Siegela3ade7a2018-01-03 20:10:23 -0800335 if (obj[k].deleted) {
336 this._updateAddRemoveObj(addRemoveObj,
337 path.concat(k), 'remove');
338 continue;
339 } else if (obj[k].modified) {
340 this._updateAddRemoveObj(addRemoveObj,
341 path.concat(k), 'remove');
Becky Siegel148c7b22018-01-16 15:01:58 -0800342 this._updateAddRemoveObj(addRemoveObj, path.concat(ref), 'add',
343 obj[k]);
344 /* Special case for ref changes because they need to be added and
345 removed in a different way. The new ref needs to include all
346 changes but also the initial state. To do this, instead of
347 continuing with the same recursion, just remove anything that is
348 deleted in the current state. */
349 if (updatedId && updatedId !== k) {
350 this._recursivelyRemoveDeleted(addRemoveObj.add[updatedId]);
351 }
352 continue;
Becky Siegel86ff45c2018-01-04 16:41:49 -0800353 } else if (obj[k].added) {
354 this._updateAddRemoveObj(addRemoveObj,
Becky Siegele6f68d92018-01-30 15:52:18 -0800355 path.concat(ref), 'add', obj[k]);
Tao Zhou324adea2019-08-26 20:13:56 +0200356 /**
357 * As add / delete both can happen in the new section,
358 * so here to make sure it will remove the deleted ones.
359 * @see Issue 11339
360 */
361 this._recursivelyRemoveDeleted(addRemoveObj.add[k]);
Becky Siegel148c7b22018-01-16 15:01:58 -0800362 continue;
Becky Siegela3ade7a2018-01-03 20:10:23 -0800363 }
364 this._recursivelyUpdateAddRemoveObj(obj[k], addRemoveObj,
365 path.concat(k));
366 }
367 }
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100368 }
Becky Siegela3ade7a2018-01-03 20:10:23 -0800369
Becky Siegel9640eb22017-12-11 15:58:57 -0800370 /**
371 * Returns an object formatted for saving or submitting access changes for
372 * review
373 *
374 * @return {!Defs.projectAccessInput}
375 */
376 _computeAddAndRemove() {
Becky Siegela3ade7a2018-01-03 20:10:23 -0800377 const addRemoveObj = {
Becky Siegel9640eb22017-12-11 15:58:57 -0800378 add: {},
379 remove: {},
380 };
Becky Siegel9640eb22017-12-11 15:58:57 -0800381
Wyatt Allen292d0132018-07-30 17:14:49 -0700382 const originalInheritsFromId = this._originalInheritsFrom ?
Dmitrii Filippovb82003c2019-11-05 17:02:59 +0100383 this.singleDecodeURL(this._originalInheritsFrom.id) :
384 null;
Wyatt Allen292d0132018-07-30 17:14:49 -0700385 const inheritsFromId = this._inheritsFrom ?
Dmitrii Filippovb82003c2019-11-05 17:02:59 +0100386 this.singleDecodeURL(this._inheritsFrom.id) :
387 null;
Wyatt Allen292d0132018-07-30 17:14:49 -0700388
Becky Siegel8d7b6272018-03-28 09:38:29 -0700389 const inheritFromChanged =
390 // Inherit from changed
Wyatt Allen292d0132018-07-30 17:14:49 -0700391 (originalInheritsFromId
392 && originalInheritsFromId !== inheritsFromId) ||
393 // Inherit from added (did not have one initially);
394 (!originalInheritsFromId && inheritsFromId);
Becky Siegel8d7b6272018-03-28 09:38:29 -0700395
Becky Siegela3ade7a2018-01-03 20:10:23 -0800396 this._recursivelyUpdateAddRemoveObj(this._local, addRemoveObj);
Becky Siegel8d7b6272018-03-28 09:38:29 -0700397
398 if (inheritFromChanged) {
Wyatt Allen292d0132018-07-30 17:14:49 -0700399 addRemoveObj.parent = inheritsFromId;
Becky Siegel8d7b6272018-03-28 09:38:29 -0700400 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800401 return addRemoveObj;
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100402 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800403
Becky Siegele6f68d92018-01-30 15:52:18 -0800404 _handleCreateSection() {
405 let newRef = 'refs/for/*';
406 // Avoid using an already used key for the placeholder, since it
407 // immediately gets added to an object.
408 while (this._local[newRef]) {
409 newRef = `${newRef}*`;
410 }
411 const section = {permissions: {}, added: true};
412 this.push('_sections', {id: newRef, value: section});
413 this.set(['_local', newRef], section);
414 Polymer.dom.flush();
415 Polymer.dom(this.root).querySelector('gr-access-section:last-of-type')
416 .editReference();
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100417 }
Becky Siegele6f68d92018-01-30 15:52:18 -0800418
Becky Siegel6af63252018-04-26 14:02:36 -0700419 _getObjforSave() {
Becky Siegel9640eb22017-12-11 15:58:57 -0800420 const addRemoveObj = this._computeAddAndRemove();
Becky Siegel148c7b22018-01-16 15:01:58 -0800421 // If there are no changes, don't actually save.
422 if (!Object.keys(addRemoveObj.add).length &&
Becky Siegel8d7b6272018-03-28 09:38:29 -0700423 !Object.keys(addRemoveObj.remove).length &&
424 !addRemoveObj.parent) {
Ole Rehmsenc82baba2019-05-16 14:43:01 +0200425 this.dispatchEvent(new CustomEvent('show-alert', {
426 detail: {message: NOTHING_TO_SAVE},
427 bubbles: true,
428 composed: true,
429 }));
Becky Siegel148c7b22018-01-16 15:01:58 -0800430 return;
431 }
Becky Siegel8d7b6272018-03-28 09:38:29 -0700432 const obj = {
Becky Siegel9640eb22017-12-11 15:58:57 -0800433 add: addRemoveObj.add,
434 remove: addRemoveObj.remove,
Becky Siegel8d7b6272018-03-28 09:38:29 -0700435 };
436 if (addRemoveObj.parent) {
437 obj.parent = addRemoveObj.parent;
438 }
Becky Siegel6af63252018-04-26 14:02:36 -0700439 return obj;
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100440 }
Becky Siegel6af63252018-04-26 14:02:36 -0700441
442 _handleSave() {
443 const obj = this._getObjforSave();
444 if (!obj) { return; }
445 return this.$.restAPI.setRepoAccessRights(this.repo, obj)
446 .then(() => {
447 this._reload(this.repo);
448 });
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100449 }
Becky Siegel6af63252018-04-26 14:02:36 -0700450
451 _handleSaveForReview() {
452 const obj = this._getObjforSave();
453 if (!obj) { return; }
454 return this.$.restAPI.setRepoAccessRightsForReview(this.repo, obj)
Becky Siegel8d7b6272018-03-28 09:38:29 -0700455 .then(change => {
456 Gerrit.Nav.navigateToChange(change);
457 });
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100458 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800459
Becky Siegel6af63252018-04-26 14:02:36 -0700460 _computeSaveReviewBtnClass(canUpload) {
461 return !canUpload ? 'invisible' : '';
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100462 }
Becky Siegel9640eb22017-12-11 15:58:57 -0800463
Becky Siegel6af63252018-04-26 14:02:36 -0700464 _computeSaveBtnClass(ownerOf) {
Paladox noneed2e2272019-07-28 13:03:10 +0000465 return ownerOf && ownerOf.length === 0 ? 'invisible' : '';
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100466 }
Becky Siegel8d7b6272018-03-28 09:38:29 -0700467
Becky Siegele42689c2018-04-26 11:29:28 -0700468 _computeMainClass(ownerOf, canUpload, editing) {
Becky Siegel8d7b6272018-03-28 09:38:29 -0700469 const classList = [];
Paladox noneed2e2272019-07-28 13:03:10 +0000470 if (ownerOf && ownerOf.length > 0 || canUpload) {
Becky Siegel8d7b6272018-03-28 09:38:29 -0700471 classList.push('admin');
472 }
473 if (editing) {
474 classList.push('editing');
475 }
476 return classList.join(' ');
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100477 }
Becky Siegel27bbf7a2017-09-30 10:14:16 +0100478
Paladox none2bd5c212017-11-16 18:54:02 +0000479 _computeParentHref(repoName) {
Becky Siegel6db432f2017-08-25 09:17:42 -0700480 return this.getBaseUrl() +
Paladox none2bd5c212017-11-16 18:54:02 +0000481 `/admin/repos/${this.encodeURL(repoName, true)},access`;
Dmitrii Filippov3fd2b102019-11-15 16:16:46 +0100482 }
483 }
484
485 customElements.define(GrRepoAccess.is, GrRepoAccess);
Paladox none3f3770e2018-03-11 22:36:08 +0000486})();