Merge "Add more commit message conditions"
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/CommentsUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/CommentsUtil.java
index 249ec7e..c51e33a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/CommentsUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/CommentsUtil.java
@@ -40,6 +40,7 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RobotComment;
import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -49,6 +50,7 @@
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
+import com.google.gerrit.server.update.BatchUpdateReviewDb;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
@@ -410,6 +412,12 @@
if (PrimaryStorage.of(update.getChange()).equals(PrimaryStorage.REVIEW_DB)) {
PatchLineComment.Key key =
new PatchLineComment.Key(new Patch.Key(psId, commentKey.filename), commentKey.uuid);
+
+ if (db instanceof BatchUpdateReviewDb) {
+ db = ((BatchUpdateReviewDb) db).unsafeGetDelegate();
+ }
+ db = ReviewDbUtil.unwrapDb(db);
+
PatchLineComment patchLineComment = db.patchComments().get(key);
if (!patchLineComment.getStatus().equals(PUBLISHED)) {
diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js
index d65f512..c1eabad 100644
--- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js
+++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor.js
@@ -14,7 +14,7 @@
(function() {
'use strict';
- var NOTIFICATION_TYPES = [
+ const NOTIFICATION_TYPES = [
{name: 'Changes', key: 'notify_new_changes'},
{name: 'Patches', key: 'notify_new_patch_sets'},
{name: 'Comments', key: 'notify_all_comments'},
@@ -35,24 +35,24 @@
_projects: Array,
_projectsToRemove: {
type: Array,
- value: function() { return []; },
+ value() { return []; },
},
_query: {
type: Function,
- value: function() {
+ value() {
return this._getProjectSuggestions.bind(this);
},
},
},
- loadData: function() {
- return this.$.restAPI.getWatchedProjects().then(function(projs) {
+ loadData() {
+ return this.$.restAPI.getWatchedProjects().then(projs => {
this._projects = projs;
- }.bind(this));
+ });
},
- save: function() {
- var deletePromise;
+ save() {
+ let deletePromise;
if (this._projectsToRemove.length) {
deletePromise = this.$.restAPI.deleteWatchedProjects(
this._projectsToRemove);
@@ -61,56 +61,57 @@
}
return deletePromise
- .then(function() {
+ .then(() => {
return this.$.restAPI.saveWatchedProjects(this._projects);
- }.bind(this))
- .then(function(projects) {
+ })
+ .then(projects => {
this._projects = projects;
this._projectsToRemove = [];
this.hasUnsavedChanges = false;
- }.bind(this));
+ });
},
- _getTypes: function() {
+ _getTypes() {
return NOTIFICATION_TYPES;
},
- _getTypeCount: function() {
+ _getTypeCount() {
return this._getTypes().length;
},
- _computeCheckboxChecked: function(project, key) {
+ _computeCheckboxChecked(project, key) {
return project.hasOwnProperty(key);
},
- _getProjectSuggestions: function(input) {
+ _getProjectSuggestions(input) {
return this.$.restAPI.getSuggestedProjects(input)
- .then(function(response) {
- var projects = [];
- for (var key in response) {
- projects.push({
- name: key,
- value: response[key],
- });
- }
- return projects;
- });
+ .then(response => {
+ const projects = [];
+ for (const key in response) {
+ if (!response.hasOwnProperty(key)) { continue; }
+ projects.push({
+ name: key,
+ value: response[key],
+ });
+ }
+ return projects;
+ });
},
- _handleRemoveProject: function(e) {
- var index = parseInt(e.target.getAttribute('data-index'), 10);
- var project = this._projects[index];
+ _handleRemoveProject(e) {
+ const index = parseInt(e.target.getAttribute('data-index'), 10);
+ const project = this._projects[index];
this.splice('_projects', index, 1);
this.push('_projectsToRemove', project);
this.hasUnsavedChanges = true;
},
- _canAddProject: function(project, filter) {
+ _canAddProject(project, filter) {
if (!project || !project.id) { return false; }
// Check if the project with filter is already in the list. Compare
// filters using == to coalesce null and undefined.
- for (var i = 0; i < this._projects.length; i++) {
+ for (let i = 0; i < this._projects.length; i++) {
if (this._projects[i].project === project.id &&
this._projects[i].filter == filter) {
return false;
@@ -120,8 +121,9 @@
return true;
},
- _getNewProjectIndex: function(name, filter) {
- for (var i = 0; i < this._projects.length; i++) {
+ _getNewProjectIndex(name, filter) {
+ let i;
+ for (i = 0; i < this._projects.length; i++) {
if (this._projects[i].project > name ||
(this._projects[i].project === name &&
this._projects[i].filter > filter)) {
@@ -131,18 +133,18 @@
return i;
},
- _handleAddProject: function() {
- var newProject = this.$.newProject.value;
- var newProjectName = this.$.newProject.text;
- var filter = this.$.newFilter.value || null;
+ _handleAddProject() {
+ const newProject = this.$.newProject.value;
+ const newProjectName = this.$.newProject.text;
+ const filter = this.$.newFilter.value || null;
if (!this._canAddProject(newProject, filter)) { return; }
- var insertIndex = this._getNewProjectIndex(newProjectName, filter);
+ const insertIndex = this._getNewProjectIndex(newProjectName, filter);
this.splice('_projects', insertIndex, 0, {
project: newProjectName,
- filter: filter,
+ filter,
_is_local: true,
});
@@ -151,16 +153,16 @@
this.hasUnsavedChanges = true;
},
- _handleCheckboxChange: function(e) {
- var index = parseInt(e.target.getAttribute('data-index'), 10);
- var key = e.target.getAttribute('data-key');
- var checked = e.target.checked;
+ _handleCheckboxChange(e) {
+ const index = parseInt(e.target.getAttribute('data-index'), 10);
+ const key = e.target.getAttribute('data-key');
+ const checked = e.target.checked;
this.set(['_projects', index, key], !!checked);
this.hasUnsavedChanges = true;
},
- _handleNotifCellTap: function(e) {
- var checkbox = Polymer.dom(e.target).querySelector('input');
+ _handleNotifCellTap(e) {
+ const checkbox = Polymer.dom(e.target).querySelector('input');
if (checkbox) { checkbox.click(); }
},
});
diff --git a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
index 59e87b0..1e6ed7a 100644
--- a/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
+++ b/polygerrit-ui/app/elements/settings/gr-watched-projects-editor/gr-watched-projects-editor_test.html
@@ -33,11 +33,12 @@
</test-fixture>
<script>
- suite('gr-watched-projects-editor tests', function() {
- var element;
+ suite('gr-watched-projects-editor tests', () => {
+ let element;
- setup(function(done) {
- var projects = [{
+ setup(done => {
+ const projects = [
+ {
project: 'project a',
notify_submitted_changes: true,
notify_abandoned_changes: true,
@@ -57,8 +58,8 @@
];
stub('gr-rest-api-interface', {
- getSuggestedProjects: function(input) {
- if (input.indexOf('the') === 0) {
+ getSuggestedProjects(input) {
+ if (input.startsWith('the')) {
return Promise.resolve({'the project': {
id: 'the project',
state: 'ACTIVE',
@@ -68,27 +69,27 @@
return Promise.resolve({});
}
},
- getWatchedProjects: function() {
+ getWatchedProjects() {
return Promise.resolve(projects);
},
});
element = fixture('basic');
- element.loadData().then(function() { flush(done); });
+ element.loadData().then(() => { flush(done); });
});
- test('renders', function() {
- var rows = element.$$('table').querySelectorAll('tbody tr');
+ test('renders', () => {
+ const rows = element.$$('table').querySelectorAll('tbody tr');
assert.equal(rows.length, 4);
function getKeysOfRow(row) {
- var boxes = rows[row].querySelectorAll('input[checked]');
+ const boxes = rows[row].querySelectorAll('input[checked]');
return Array.prototype.map.call(boxes,
- function(e) { return e.getAttribute('data-key'); });
+ e => { return e.getAttribute('data-key'); });
}
- var checkedKeys = getKeysOfRow(0);
+ let checkedKeys = getKeysOfRow(0);
assert.equal(checkedKeys.length, 2);
assert.equal(checkedKeys[0], 'notify_submitted_changes');
assert.equal(checkedKeys[1], 'notify_abandoned_changes');
@@ -107,22 +108,22 @@
assert.equal(checkedKeys[2], 'notify_all_comments');
});
- test('_getProjectSuggestions empty', function(done) {
- element._getProjectSuggestions('nonexistent').then(function(projects) {
+ test('_getProjectSuggestions empty', done => {
+ element._getProjectSuggestions('nonexistent').then(projects => {
assert.equal(projects.length, 0);
done();
});
});
- test('_getProjectSuggestions non-empty', function(done) {
- element._getProjectSuggestions('the project').then(function(projects) {
+ test('_getProjectSuggestions non-empty', done => {
+ element._getProjectSuggestions('the project').then(projects => {
assert.equal(projects.length, 1);
assert.equal(projects[0].name, 'the project');
done();
});
});
- test('_canAddProject', function() {
+ test('_canAddProject', () => {
assert.isFalse(element._canAddProject(null, null));
assert.isFalse(element._canAddProject({}, null));
@@ -144,7 +145,7 @@
assert.isTrue(element._canAddProject({id: 'project b'}, 'filter 3'));
});
- test('_getNewProjectIndex', function() {
+ test('_getNewProjectIndex', () => {
// Projects are sorted in ASCII order.
assert.equal(element._getNewProjectIndex('project A', 'filter'), 0);
assert.equal(element._getNewProjectIndex('project a', 'filter'), 1);
@@ -158,7 +159,7 @@
assert.equal(element._getNewProjectIndex('project c', 'filter'), 4);
});
- test('_handleAddProject', function() {
+ test('_handleAddProject', () => {
element.$.newProject.value = {id: 'project d'};
element.$.newProject.setText('project d');
element.$.newFilter.bindValue = '';
@@ -171,7 +172,7 @@
assert.isTrue(element._projects[4]._is_local);
});
- test('_handleAddProject with invalid inputs', function() {
+ test('_handleAddProject with invalid inputs', () => {
element.$.newProject.value = {id: 'project b'};
element.$.newProject.setText('project b');
element.$.newFilter.bindValue = 'filter 1';
@@ -181,14 +182,14 @@
assert.equal(element._projects.length, 4);
});
- test('_handleRemoveProject', function() {
+ test('_handleRemoveProject', () => {
assert.equal(element._projectsToRemove, 0);
- var button = element.$$('table tbody tr:nth-child(2) gr-button');
+ const button = element.$$('table tbody tr:nth-child(2) gr-button');
MockInteractions.tap(button);
flushAsynchronousOperations();
- var rows = element.$$('table tbody').querySelectorAll('tr');
+ const rows = element.$$('table tbody').querySelectorAll('tr');
assert.equal(rows.length, 3);
assert.equal(element._projectsToRemove.length, 1);
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
index d19afb7..81379af 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.html
@@ -16,6 +16,7 @@
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">
+<link rel="import" href="../../shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown.html">
<link rel="import" href="../../shared/gr-cursor-manager/gr-cursor-manager.html">
<dom-module id="gr-autocomplete">
@@ -31,25 +32,6 @@
border: none;
outline: none;
}
- #suggestions {
- background-color: #fff;
- box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
- position: absolute;
- z-index: 10;
- }
- ul {
- list-style: none;
- }
- li {
- cursor: pointer;
- padding: .5em .75em;
- }
- li:focus {
- outline: none;
- }
- li.selected {
- background-color: #eee;
- }
</style>
<input
id="input"
@@ -61,29 +43,13 @@
on-keydown="_handleKeydown"
on-focus="_onInputFocus"
autocomplete="off" />
- <div
- id="suggestions"
+ <gr-autocomplete-dropdown id="suggestions"
+ on-item-selected="_handleItemSelect"
+ suggestions="[[_suggestions]]"
role="listbox"
+ index="[[index]]"
hidden$="[[_computeSuggestionsHidden(_suggestions, _focused)]]">
- <ul>
- <template is="dom-repeat" items="[[_suggestions]]">
- <li
- data-index$="[[index]]"
- tabindex="-1"
- aria-label$="[[item.name]]"
- on-keydown="_handleKeydown"
- role="option"
- on-tap="_handleSuggestionTap">[[item.name]]</li>
- </template>
- </ul>
- </div>
- <gr-cursor-manager
- id="cursor"
- index="{{_index}}"
- cursor-target-class="selected"
- scroll-behavior="keep-visible"
- focus-on-move
- stops="[[_suggestionEls]]"></gr-cursor-manager>
+ </gr-autocomplete-dropdown>
</template>
<script src="gr-autocomplete.js"></script>
</dom-module>
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
index 9cf67b4..56a3c23 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete.js
@@ -116,17 +116,15 @@
},
_index: Number,
-
_disableSuggestions: {
type: Boolean,
value: false,
},
-
_focused: {
type: Boolean,
value: false,
},
-
+ _selected: Object,
},
attached() {
@@ -153,6 +151,18 @@
this.text = '';
},
+ _handleItemSelect(e) {
+ let silent = false;
+ if (e.detail.trigger === 'tab' && this.tabCompleteWithoutCommit) {
+ silent = true;
+ }
+ this._selected = e.detail.selected;
+ this._commit(silent);
+ if (e.detail.trigger === 'tap') {
+ this.focus();
+ }
+ },
+
/**
* Set the text of the input without triggering the suggestion dropdown.
* @param {String} text The new text for the input.
@@ -182,10 +192,11 @@
// Late response.
return;
}
+ for (const suggestion of suggestions) {
+ suggestion.text = suggestion.name;
+ }
this._suggestions = suggestions;
Polymer.dom.flush();
- this._suggestionEls = this.$.suggestions.querySelectorAll('li');
- this.$.cursor.moveToStart();
if (this._index === -1) {
this.value = null;
}
@@ -209,11 +220,11 @@
switch (e.keyCode) {
case 38: // Up
e.preventDefault();
- this.$.cursor.previous();
+ this.$.suggestions.cursorUp();
break;
case 40: // Down
e.preventDefault();
- this.$.cursor.next();
+ this.$.suggestions.cursorDown();
break;
case 27: // Escape
e.preventDefault();
@@ -222,12 +233,12 @@
case 9: // Tab
if (this._suggestions.length > 0) {
e.preventDefault();
- this._commit(this.tabCompleteWithoutCommit);
+ this._handleEnter(this.tabCompleteWithoutCommit);
}
break;
case 13: // Enter
e.preventDefault();
- this._commit();
+ this._handleEnter();
break;
default:
// For any normal keypress, return focus to the input to allow for
@@ -245,9 +256,15 @@
}
},
- _updateValue(suggestions, index) {
- if (!suggestions.length || index === -1) { return; }
- const completed = suggestions[index].value;
+ _handleEnter(opt_tabCompleteWithoutCommit) {
+ this._selected = this.$.suggestions.getCursorTarget();
+ this._commit(opt_tabCompleteWithoutCommit);
+ this.focus();
+ },
+
+ _updateValue(suggestion, suggestions) {
+ if (!suggestion) { return; }
+ const completed = suggestions[suggestion.dataset.index].value;
if (this.multi) {
// Append the completed text to the end of the string.
// Allow spaces within quoted terms.
@@ -286,7 +303,7 @@
_commit(silent) {
// Allow values that are not in suggestion list iff suggestions are empty.
if (this._suggestions.length > 0) {
- this._updateValue(this._suggestions, this._index);
+ this._updateValue(this._selected, this._suggestions);
} else {
this.value = this.text || '';
}
@@ -297,8 +314,8 @@
if (this.multi) {
this.setText(this.value);
} else {
- if (!this.clearOnCommit && this._suggestions[this._index]) {
- this.setText(this._suggestions[this._index].name);
+ if (!this.clearOnCommit && this._selected) {
+ this.setText(this._suggestions[this._selected.dataset.index].name);
} else {
this.clear();
}
diff --git a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html
index 6a3ae81..62d4079 100644
--- a/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-autocomplete/gr-autocomplete_test.html
@@ -58,9 +58,8 @@
]);
});
element.query = queryStub;
-
- assert.isTrue(element.$.suggestions.hasAttribute('hidden'));
- assert.equal(element.$.cursor.index, -1);
+ assert.isTrue(element.$.suggestions.hidden);
+ assert.equal(element.$.suggestions.$.cursor.index, -1);
element.text = 'blah';
@@ -69,15 +68,15 @@
promise.then(() => {
assert.isFalse(element.$.suggestions.hasAttribute('hidden'));
-
- const suggestions = element.$.suggestions.querySelectorAll('li');
+ const suggestions =
+ Polymer.dom(element.$.suggestions.root).querySelectorAll('li');
assert.equal(suggestions.length, 5);
for (let i = 0; i < 5; i++) {
assert.equal(suggestions[i].textContent, 'blah ' + i);
}
- assert.notEqual(element.$.cursor.index, -1);
+ assert.notEqual(element.$.suggestions.$.cursor.index, -1);
done();
});
});
@@ -91,20 +90,20 @@
});
element.query = queryStub;
- assert.isTrue(element.$.suggestions.hasAttribute('hidden'));
+ assert.isTrue(element.$.suggestions.hidden);
element._focused = true;
element.text = 'blah';
promise.then(() => {
- assert.isFalse(element.$.suggestions.hasAttribute('hidden'));
+ assert.isFalse(element.$.suggestions.hidden);
const cancelHandler = sandbox.spy();
element.addEventListener('cancel', cancelHandler);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 27, null, 'esc');
assert.isFalse(cancelHandler.called);
- assert.isTrue(element.$.suggestions.hasAttribute('hidden'));
+ assert.isTrue(element.$.suggestions.hidden);
assert.equal(element._suggestions.length, 0);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 27, null, 'esc');
@@ -126,32 +125,32 @@
});
element.query = queryStub;
- assert.isTrue(element.$.suggestions.hasAttribute('hidden'));
- assert.equal(element.$.cursor.index, -1);
+ assert.isTrue(element.$.suggestions.hidden);
+ assert.equal(element.$.suggestions.$.cursor.index, -1);
element._focused = true;
element.text = 'blah';
promise.then(() => {
- assert.isFalse(element.$.suggestions.hasAttribute('hidden'));
+ assert.isFalse(element.$.suggestions.hidden);
const commitHandler = sandbox.spy();
element.addEventListener('commit', commitHandler);
- assert.equal(element.$.cursor.index, 0);
+ assert.equal(element.$.suggestions.$.cursor.index, 0);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 40, null,
'down');
- assert.equal(element.$.cursor.index, 1);
+ assert.equal(element.$.suggestions.$.cursor.index, 1);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 40, null,
'down');
- assert.equal(element.$.cursor.index, 2);
+ assert.equal(element.$.suggestions.$.cursor.index, 2);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 38, null, 'up');
- assert.equal(element.$.cursor.index, 1);
+ assert.equal(element.$.suggestions.$.cursor.index, 1);
MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null,
'enter');
@@ -159,7 +158,7 @@
assert.equal(element.value, 1);
assert.isTrue(commitHandler.called);
assert.equal(commitHandler.getCall(0).args[0].detail.value, 1);
- assert.isTrue(element.$.suggestions.hasAttribute('hidden'));
+ assert.isTrue(element.$.suggestions.hidden);
done();
});
@@ -304,12 +303,12 @@
element._focused = true;
element._suggestions = [{name: 'first suggestion'}];
Polymer.dom.flush();
- assert.isFalse(element.$.suggestions.hasAttribute('hidden'));
- MockInteractions.tap(element.$$('#suggestions li:first-child'));
+ assert.isFalse(element.$.suggestions.hidden);
+ MockInteractions.tap(element.$.suggestions.$$('li:first-child'));
flushAsynchronousOperations();
assert.isTrue(focusSpy.called);
assert.isTrue(commitSpy.called);
- assert.isTrue(element.$.suggestions.hasAttribute('hidden'));
+ assert.isTrue(element.$.suggestions.hidden);
assert.isTrue(element._focused);
});
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
index 77d1c05..2e7f17c 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage.js
@@ -15,10 +15,10 @@
'use strict';
// Date cutoff is one day:
- var DRAFT_MAX_AGE = 24 * 60 * 60 * 1000;
+ const DRAFT_MAX_AGE = 24 * 60 * 60 * 1000;
// Clean up old entries no more frequently than one day.
- var CLEANUP_THROTTLE_INTERVAL = 24 * 60 * 60 * 1000;
+ const CLEANUP_THROTTLE_INTERVAL = 24 * 60 * 60 * 1000;
Polymer({
is: 'gr-storage',
@@ -27,7 +27,7 @@
_lastCleanup: Number,
_storage: {
type: Object,
- value: function() {
+ value() {
return window.localStorage;
},
},
@@ -37,42 +37,43 @@
},
},
- getDraftComment: function(location) {
+ getDraftComment(location) {
this._cleanupDrafts();
return this._getObject(this._getDraftKey(location));
},
- setDraftComment: function(location, message) {
- var key = this._getDraftKey(location);
- this._setObject(key, {message: message, updated: Date.now()});
+ setDraftComment(location, message) {
+ const key = this._getDraftKey(location);
+ this._setObject(key, {message, updated: Date.now()});
},
- eraseDraftComment: function(location) {
- var key = this._getDraftKey(location);
+ eraseDraftComment(location) {
+ const key = this._getDraftKey(location);
this._storage.removeItem(key);
},
- getPreferences: function() {
+ getPreferences() {
return this._getObject('localPrefs');
},
- savePreferences: function(localPrefs) {
+ savePreferences(localPrefs) {
this._setObject('localPrefs', localPrefs || null);
},
- _getDraftKey: function(location) {
- var range = location.range ? location.range.start_line + '-' +
- location.range.start_character + '-' + location.range.end_character +
- '-' + location.range.end_line : null;
- var key = ['draft', location.changeNum, location.patchNum, location.path,
- location.line || ''].join(':');
+ _getDraftKey(location) {
+ const range = location.range ?
+ `${location.range.start_line}-${location.range.start_character}` +
+ `-${location.range.end_character}-${location.range.end_line}` :
+ null;
+ let key = ['draft', location.changeNum, location.patchNum, location.path,
+ location.line || ''].join(':');
if (range) {
key = key + ':' + range;
}
return key;
},
- _cleanupDrafts: function() {
+ _cleanupDrafts() {
// Throttle cleanup to the throttle interval.
if (this._lastCleanup &&
Date.now() - this._lastCleanup < CLEANUP_THROTTLE_INTERVAL) {
@@ -80,9 +81,9 @@
}
this._lastCleanup = Date.now();
- var draft;
- for (var key in this._storage) {
- if (key.indexOf('draft:') === 0) {
+ let draft;
+ for (const key in this._storage) {
+ if (key.startsWith('draft:')) {
draft = this._getObject(key);
if (Date.now() - draft.updated > DRAFT_MAX_AGE) {
this._storage.removeItem(key);
@@ -91,13 +92,13 @@
}
},
- _getObject: function(key) {
- var serial = this._storage.getItem(key);
+ _getObject(key) {
+ const serial = this._storage.getItem(key);
if (!serial) { return null; }
return JSON.parse(serial);
},
- _setObject: function(key, obj) {
+ _setObject(key, obj) {
if (this._exceededQuota) { return; }
try {
this._storage.setItem(key, JSON.stringify(obj));
diff --git a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
index 6d77c55..4171939 100644
--- a/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-storage/gr-storage_test.html
@@ -31,43 +31,44 @@
</test-fixture>
<script>
- suite('gr-storage tests', function() {
- var element;
+ suite('gr-storage tests', () => {
+ let element;
function mockStorage(opt_quotaExceeded) {
return {
- getItem: function(key) { return this[key]; },
- removeItem: function(key) { delete this[key]; },
- setItem: function(key, value) {
+ getItem(key) { return this[key]; },
+ removeItem(key) { delete this[key]; },
+ setItem(key, value) {
+ // eslint-disable-next-line no-throw-literal
if (opt_quotaExceeded) { throw {code: 22}; /* Quota exceeded */ }
this[key] = value;
},
};
}
- setup(function() {
+ setup(() => {
element = fixture('basic');
element._storage = mockStorage();
});
- test('storing, retrieving and erasing drafts', function() {
- var changeNum = 1234;
- var patchNum = 5;
- var path = 'my_source_file.js';
- var line = 123;
- var location = {
- changeNum: changeNum,
- patchNum: patchNum,
- path: path,
- line: line,
+ test('storing, retrieving and erasing drafts', () => {
+ const changeNum = 1234;
+ const patchNum = 5;
+ const path = 'my_source_file.js';
+ const line = 123;
+ const location = {
+ changeNum,
+ patchNum,
+ path,
+ line,
};
// The key is in the expected format.
- var key = element._getDraftKey(location);
+ const key = element._getDraftKey(location);
assert.equal(key, ['draft', changeNum, patchNum, path, line].join(':'));
// There should be no draft initially.
- var draft = element.getDraftComment(location);
+ const draft = element.getDraftComment(location);
assert.isNotOk(draft);
// Setting the draft stores it under the expected key.
@@ -82,24 +83,24 @@
assert.isNotOk(element._storage.getItem(key));
});
- test('automatically removes old drafts', function() {
- var changeNum = 1234;
- var patchNum = 5;
- var path = 'my_source_file.js';
- var line = 123;
- var location = {
- changeNum: changeNum,
- patchNum: patchNum,
- path: path,
- line: line,
+ test('automatically removes old drafts', () => {
+ const changeNum = 1234;
+ const patchNum = 5;
+ const path = 'my_source_file.js';
+ const line = 123;
+ const location = {
+ changeNum,
+ patchNum,
+ path,
+ line,
};
- var key = element._getDraftKey(location);
+ const key = element._getDraftKey(location);
// Make sure that the call to cleanup doesn't get throttled.
element._lastCleanup = 0;
- var cleanupSpy = sinon.spy(element, '_cleanupDrafts');
+ const cleanupSpy = sinon.spy(element, '_cleanupDrafts');
// Create a message with a timestamp that is a second behind the max age.
element._storage.setItem(key, JSON.stringify({
@@ -108,7 +109,7 @@
}));
// Getting the draft should cause it to be removed.
- var draft = element.getDraftComment(location);
+ const draft = element.getDraftComment(location);
assert.isTrue(cleanupSpy.called);
assert.isNotOk(draft);
@@ -117,18 +118,18 @@
cleanupSpy.restore();
});
- test('_getDraftKey', function() {
- var changeNum = 1234;
- var patchNum = 5;
- var path = 'my_source_file.js';
- var line = 123;
- var location = {
- changeNum: changeNum,
- patchNum: patchNum,
- path: path,
- line: line,
+ test('_getDraftKey', () => {
+ const changeNum = 1234;
+ const patchNum = 5;
+ const path = 'my_source_file.js';
+ const line = 123;
+ const location = {
+ changeNum,
+ patchNum,
+ path,
+ line,
};
- var expectedResult = 'draft:1234:5:my_source_file.js:123';
+ let expectedResult = 'draft:1234:5:my_source_file.js:123';
assert.equal(element._getDraftKey(location), expectedResult);
location.range = {
start_character: 1,
@@ -140,21 +141,21 @@
assert.equal(element._getDraftKey(location), expectedResult);
});
- test('exceeded quota disables storage', function() {
+ test('exceeded quota disables storage', () => {
element._storage = mockStorage(true);
assert.isFalse(element._exceededQuota);
- var changeNum = 1234;
- var patchNum = 5;
- var path = 'my_source_file.js';
- var line = 123;
- var location = {
- changeNum: changeNum,
- patchNum: patchNum,
- path: path,
- line: line,
+ const changeNum = 1234;
+ const patchNum = 5;
+ const path = 'my_source_file.js';
+ const line = 123;
+ const location = {
+ changeNum,
+ patchNum,
+ path,
+ line,
};
- var key = element._getDraftKey(location);
+ const key = element._getDraftKey(location);
element.setDraftComment(location, 'my comment');
assert.isTrue(element._exceededQuota);
assert.isNotOk(element._storage.getItem(key));