Allow deleting ref sections in project access

Also fixes an issue where the deleted bit was not removed from
permissions when editing was cancelled.

Bug: Issue 8035
Change-Id: I333fda2986117a82ed19bc5e55310469b17e451b
This commit is contained in:
Becky Siegel
2018-01-19 14:57:34 -08:00
parent 7b295b1d6c
commit 6e40fcbe7c
6 changed files with 64 additions and 13 deletions

View File

@@ -66,7 +66,7 @@ limitations under the License.
.deleted #mainContainer, .deleted #mainContainer,
.global, .global,
#addPermission, #addPermission,
#updateBtns, #deleteBtn,
.editingRef .header, .editingRef .header,
.editContainer { .editContainer {
display: none; display: none;
@@ -74,13 +74,19 @@ limitations under the License.
.editing #editBtn { .editing #editBtn {
display: flex; display: flex;
} }
/* TODO @beckysiegel add back when editing allowed */ .deleted #deletedContainer {
/* .deleted #deletedContainer, display: flex;
}
/* TODO @beckysiegel add back when adding permission allowed */
/* .editing #addPermission, */
#mainContainer, #mainContainer,
.editing #addPermission, .editing #deleteBtn {
.editing #updateBtns {
display: block; display: block;
} */ }
.editing #deleteBtn,
#undoRemoveBtn {
padding-right: .7em;
}
.editingRef .editContainer { .editingRef .editContainer {
display: flex; display: flex;
} }
@@ -100,11 +106,10 @@ limitations under the License.
<iron-icon id="icon" icon="gr-icons:create"></iron-icon> <iron-icon id="icon" icon="gr-icons:create"></iron-icon>
</gr-button> </gr-button>
</div> </div>
<div id="updateBtns">
<gr-button <gr-button
link
id="deleteBtn" id="deleteBtn"
on-tap="_handleRemoveReference">Remove</gr-button> on-tap="_handleRemoveReference">Remove</gr-button>
</div><!-- end updateBtns -->
</div><!-- end header --> </div><!-- end header -->
<div class="editContainer"> <div class="editContainer">
<input <input
@@ -145,8 +150,9 @@ limitations under the License.
</div><!-- end sectionContent --> </div><!-- end sectionContent -->
</div><!-- end mainContainer --> </div><!-- end mainContainer -->
<div id="deletedContainer"> <div id="deletedContainer">
[[_computeSectionName(section.id)]] was deleted <span>[[_computeSectionName(section.id)]] was deleted</span>
<gr-button <gr-button
link
id="undoRemoveBtn" id="undoRemoveBtn"
on-tap="_handleUndoRemove">Undo</gr-button> on-tap="_handleUndoRemove">Undo</gr-button>
</div><!-- end deletedContainer --> </div><!-- end deletedContainer -->

View File

@@ -14,6 +14,12 @@
(function() { (function() {
'use strict'; 'use strict';
/**
* Fired when the section has been modified or removed.
*
* @event access-modified
*/
const GLOBAL_NAME = 'GLOBAL_CAPABILITIES'; const GLOBAL_NAME = 'GLOBAL_CAPABILITIES';
// The name that gets automatically input when a new reference is added. // The name that gets automatically input when a new reference is added.
@@ -85,6 +91,8 @@
// Restore original values if no longer editing. // Restore original values if no longer editing.
if (!editing) { if (!editing) {
this._editingRef = false; this._editingRef = false;
this._deleted = false;
delete this.section.value.deleted;
// Restore section ref. // Restore section ref.
this.set(['section', 'id'], this._originalId); this.set(['section', 'id'], this._originalId);
} }
@@ -159,7 +167,8 @@
_handleRemoveReference() { _handleRemoveReference() {
this._deleted = true; this._deleted = true;
this.set('section.value.deleted', true); this.section.value.deleted = true;
this.dispatchEvent(new CustomEvent('access-modified', {bubbles: true}));
}, },
_handleUndoRemove() { _handleUndoRemove() {

View File

@@ -462,9 +462,11 @@ limitations under the License.
test('remove section', () => { test('remove section', () => {
element.editing = true; element.editing = true;
assert.isFalse(element._deleted); assert.isFalse(element._deleted);
assert.isNotOk(element.section.value.deleted);
MockInteractions.tap(element.$.deleteBtn); MockInteractions.tap(element.$.deleteBtn);
flushAsynchronousOperations(); flushAsynchronousOperations();
assert.isTrue(element._deleted); assert.isTrue(element._deleted);
assert.isTrue(element.section.value.deleted);
assert.isTrue(element.$.section.classList.contains('deleted')); assert.isTrue(element.$.section.classList.contains('deleted'));
assert.isTrue(element.section.value.deleted); assert.isTrue(element.section.value.deleted);
@@ -472,6 +474,13 @@ limitations under the License.
flushAsynchronousOperations(); flushAsynchronousOperations();
assert.isFalse(element._deleted); assert.isFalse(element._deleted);
assert.isNotOk(element.section.value.deleted); assert.isNotOk(element.section.value.deleted);
MockInteractions.tap(element.$.deleteBtn);
assert.isTrue(element._deleted);
assert.isTrue(element.section.value.deleted);
element.editing = false;
assert.isFalse(element._deleted);
assert.isNotOk(element.section.value.deleted);
}); });
}); });
}); });

View File

@@ -99,6 +99,7 @@
// Restore original values if no longer editing. // Restore original values if no longer editing.
if (!editing) { if (!editing) {
this._deleted = false; this._deleted = false;
delete this.permission.value.deleted;
this._groupFilter = ''; this._groupFilter = '';
this._rules = this._rules.filter(rule => !rule.value.added); this._rules = this._rules.filter(rule => !rule.value.added);

View File

@@ -237,10 +237,15 @@ limitations under the License.
}); });
test('_handleRemovePermission', () => { test('_handleRemovePermission', () => {
element.editing = true;
element.permission = {value: {rules: {}}}; element.permission = {value: {rules: {}}};
element._handleRemovePermission(); element._handleRemovePermission();
assert.isTrue(element._deleted); assert.isTrue(element._deleted);
assert.isTrue(element.permission.value.deleted); assert.isTrue(element.permission.value.deleted);
element.editing = false;
assert.isFalse(element._deleted);
assert.isNotOk(element.permission.value.deleted);
}); });
test('_handleUndoRemove', () => { test('_handleUndoRemove', () => {

View File

@@ -367,7 +367,7 @@ limitations under the License.
assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}}); assert.deepEqual(element._computeAddAndRemove(), {add: {}, remove: {}});
element._local['refs/*'].updatedId = 'refs/for/bar'; element._local['refs/*'].updatedId = 'refs/for/bar';
element._local['refs/*'].modified = true; element._local['refs/*'].modified = true;
const expectedInput = { let expectedInput = {
add: { add: {
'refs/for/bar': { 'refs/for/bar': {
modified: true, modified: true,
@@ -394,6 +394,16 @@ limitations under the License.
}, },
}; };
assert.deepEqual(element._computeAddAndRemove(), expectedInput); assert.deepEqual(element._computeAddAndRemove(), expectedInput);
element._local['refs/*'].deleted = true;
expectedInput = {
add: {},
remove: {
'refs/*': {
permissions: {},
},
},
};
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
}); });
test('_computeAddAndRemove combinations', () => { test('_computeAddAndRemove combinations', () => {
@@ -500,6 +510,17 @@ limitations under the License.
}, },
}; };
assert.deepEqual(element._computeAddAndRemove(), expectedInput); assert.deepEqual(element._computeAddAndRemove(), expectedInput);
expectedInput = {
add: {},
remove: {
'refs/*': {
permissions: {},
},
},
};
element._local['refs/*'].deleted = true;
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
}); });
test('_handleSaveForReview', done => { test('_handleSaveForReview', done => {