Merge branch 'stable-3.0' into stable-3.1
* stable-3.0: Bump Bazel version to 2.0.0 Set version in package.json to 3.0.7-SNAPSHOT Set version in package.json to 2.16.16-SNAPSHOT Use gerritCheck API for posting checker result Update git submodules Downport "Replace deprecated `require-jsdoc`, `valid-jsdoc` with jsdoc plugin for eslint" Downport "Add a shared pre-commit to run eslintfix for frontend code changes" Downport "Remove `|| exit 0` as eslint already supported correct exit code" Downport "Update eslint version and eslint rules" Downport "Simplify installing / running polylint" Downport "Make `npm start` run run-server.sh" Downport "Simplify installing / running template tests" Downport "Simplify installing and running eslint" Downport "Simplify running frontend tests via package.json" Change-Id: Ic08aecefc55b0434a32c6d6836fd4019e26ace72
This commit is contained in:
@@ -1 +1 @@
|
||||
1.2.0
|
||||
2.0.0
|
||||
|
||||
26
Jenkinsfile
vendored
26
Jenkinsfile
vendored
@@ -53,15 +53,11 @@ class Builds {
|
||||
|
||||
class GerritCheck {
|
||||
String uuid
|
||||
String changeNum
|
||||
String sha1
|
||||
Build build
|
||||
|
||||
GerritCheck(name, changeNum, sha1, build) {
|
||||
GerritCheck(name, build) {
|
||||
this.uuid = "gerritforge:" + name.replaceAll("(bazel/)", "") +
|
||||
Globals.gerritRepositoryNameSha1Suffix
|
||||
this.changeNum = changeNum
|
||||
this.sha1 = sha1
|
||||
this.build = build
|
||||
}
|
||||
|
||||
@@ -93,21 +89,7 @@ def hasChangeNumber() {
|
||||
}
|
||||
|
||||
def postCheck(check) {
|
||||
def gerritPostUrl = Globals.gerritUrl +
|
||||
"a/changes/${check.changeNum}/revisions/${check.sha1}/checks"
|
||||
|
||||
try {
|
||||
def json = check.createCheckPayload()
|
||||
httpRequest(httpMode: 'POST', authentication: Globals.gerritCredentialsId,
|
||||
contentType: 'APPLICATION_JSON', requestBody: json,
|
||||
validResponseCodes: '200', url: gerritPostUrl)
|
||||
echo "----------------------------------------------------------------------------"
|
||||
echo "Gerrit Check: ${check.uuid}=" + check.build.result + " to change " +
|
||||
check.changeNum + "/" + check.sha1
|
||||
echo "----------------------------------------------------------------------------"
|
||||
} catch(Exception e) {
|
||||
echo "ERROR> Failed to post check results to Gerrit: ${e}"
|
||||
}
|
||||
gerritCheck(checks: [ "${check.uuid}" : "${check.getCheckResultFromBuild()}" ])
|
||||
}
|
||||
|
||||
def queryChangedFiles(url, changeNum, sha1) {
|
||||
@@ -313,7 +295,7 @@ node ('master') {
|
||||
gerritReview(
|
||||
labels: ['Code-Style': resCodeStyle],
|
||||
message: createCodeStyleMsgBody(Builds.codeStyle, resCodeStyle))
|
||||
postCheck(new GerritCheck("codestyle", Change.number, Change.sha1, Builds.codeStyle))
|
||||
postCheck(new GerritCheck("codestyle", Builds.codeStyle))
|
||||
|
||||
def verificationResults = Builds.verification.collect { k, v -> v }
|
||||
def resVerify = verificationResults.inject(1) {
|
||||
@@ -324,7 +306,7 @@ node ('master') {
|
||||
message: createVerifyMsgBody(Builds.verification))
|
||||
|
||||
Builds.verification.each { type, build -> postCheck(
|
||||
new GerritCheck(type, Change.number, Change.sha1, build)
|
||||
new GerritCheck(type, build)
|
||||
)}
|
||||
|
||||
setResult(resVerify, resCodeStyle)
|
||||
|
||||
@@ -4,9 +4,10 @@
|
||||
"description": "Gerrit Code Review",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"eslint": "^5.16.0",
|
||||
"eslint": "^6.6.0",
|
||||
"eslint-config-google": "^0.13.0",
|
||||
"eslint-plugin-html": "^5.0.5",
|
||||
"eslint-plugin-html": "^6.0.0",
|
||||
"eslint-plugin-jsdoc": "^18.4.3",
|
||||
"fried-twinkie": "^0.2.2",
|
||||
"polylint": "^2.10.4",
|
||||
"typescript": "^2.x.x",
|
||||
@@ -15,7 +16,8 @@
|
||||
"scripts": {
|
||||
"start": "polygerrit-ui/run-server.sh",
|
||||
"test": "WCT_HEADLESS_MODE=1 WCT_ARGS='--verbose -l chrome' ./polygerrit-ui/app/run_test.sh",
|
||||
"eslint": "./node_modules/eslint/bin/eslint.js --ignore-pattern 'bower_components/' --ignore-pattern 'gr-linked-text' --ignore-pattern 'scripts/vendor' --ext .html,.js polygerrit-ui/app || exit 0",
|
||||
"eslint": "./node_modules/eslint/bin/eslint.js --ext .html,.js polygerrit-ui/app",
|
||||
"eslintfix": "npm run eslint -- --fix",
|
||||
"test-template": "./polygerrit-ui/app/run_template_test.sh",
|
||||
"polylint": "bazel test polygerrit-ui/app:polylint_test"
|
||||
},
|
||||
|
||||
@@ -48,7 +48,13 @@ simply execute:
|
||||
./polygerrit-ui/run-server.sh
|
||||
```
|
||||
|
||||
Then visit <http://localhost:8081>.
|
||||
Then visit http://localhost:8081
|
||||
|
||||
## Local UI, Test Data
|
||||
|
||||
```sh
|
||||
./polygerrit-ui/run-server.sh --plugins=plugins/my_plugin/static/my_plugin.js,plugins/my_plugin/static/my_plugin.html
|
||||
```
|
||||
|
||||
This method is based on a
|
||||
[simple hand-written Go webserver](https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/server.go).
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
"functions": "never"
|
||||
}],
|
||||
"eol-last": "off",
|
||||
"indent": "off",
|
||||
"indent-legacy": ["error", 2, {
|
||||
"indent": ["error", 2, {
|
||||
"MemberExpression": 2,
|
||||
"FunctionDeclaration": {"body": 1, "parameters": 2},
|
||||
"FunctionExpression": {"body": 1, "parameters": 2},
|
||||
@@ -44,13 +43,14 @@
|
||||
"SwitchCase": 1
|
||||
}],
|
||||
"keyword-spacing": ["error", { "after": true, "before": true }],
|
||||
"lines-between-class-members": ["error", "always"],
|
||||
"max-len": [
|
||||
"error",
|
||||
80,
|
||||
2,
|
||||
{"ignoreComments": true}
|
||||
],
|
||||
"new-cap": ["error", { "capIsNewExceptions": ["Polymer"] }],
|
||||
"new-cap": ["error", { "capIsNewExceptions": ["Polymer", "LegacyElementMixin", "GestureEventListeners", "LegacyDataMixin"] }],
|
||||
"no-console": "off",
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
@@ -70,17 +70,58 @@
|
||||
"no-redeclare": "off",
|
||||
"operator-linebreak": "off",
|
||||
"object-shorthand": ["error", "always"],
|
||||
"padding-line-between-statements": [
|
||||
"error",
|
||||
{
|
||||
"blankLine": "always",
|
||||
"prev": "class",
|
||||
"next": "*"
|
||||
},
|
||||
{
|
||||
"blankLine": "always",
|
||||
"prev": "*",
|
||||
"next": "class"
|
||||
}
|
||||
],
|
||||
"prefer-arrow-callback": "error",
|
||||
"prefer-const": "error",
|
||||
"prefer-spread": "error",
|
||||
"quote-props": ["error", "consistent-as-needed"],
|
||||
"require-jsdoc": "off",
|
||||
"semi": [2, "always"],
|
||||
"template-curly-spacing": "error",
|
||||
"valid-jsdoc": "off"
|
||||
|
||||
"require-jsdoc": 0,
|
||||
"valid-jsdoc": 0,
|
||||
"jsdoc/check-alignment": 2,
|
||||
"jsdoc/check-examples": 0,
|
||||
"jsdoc/check-indentation": 0,
|
||||
"jsdoc/check-param-names": 0,
|
||||
"jsdoc/check-syntax": 0,
|
||||
"jsdoc/check-tag-names": 0,
|
||||
"jsdoc/check-types": 0,
|
||||
"jsdoc/implements-on-classes": 2,
|
||||
"jsdoc/match-description": 0,
|
||||
"jsdoc/newline-after-description": 2,
|
||||
"jsdoc/no-types": 0,
|
||||
"jsdoc/no-undefined-types": 0,
|
||||
"jsdoc/require-description": 0,
|
||||
"jsdoc/require-description-complete-sentence": 0,
|
||||
"jsdoc/require-example": 0,
|
||||
"jsdoc/require-hyphen-before-param-description": 0,
|
||||
"jsdoc/require-jsdoc": 0,
|
||||
"jsdoc/require-param": 0,
|
||||
"jsdoc/require-param-description": 0,
|
||||
"jsdoc/require-param-name": 2,
|
||||
"jsdoc/require-param-type": 2,
|
||||
"jsdoc/require-returns": 0,
|
||||
"jsdoc/require-returns-check": 0,
|
||||
"jsdoc/require-returns-description": 0,
|
||||
"jsdoc/require-returns-type": 2,
|
||||
"jsdoc/valid-types": 2
|
||||
},
|
||||
"plugins": [
|
||||
"html"
|
||||
"html",
|
||||
"jsdoc"
|
||||
],
|
||||
"settings": {
|
||||
"html/report-bad-indent": "error"
|
||||
|
||||
@@ -31,6 +31,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Get the docs base URL from either the server config or by probing.
|
||||
*
|
||||
* @param {Object} config The server config.
|
||||
* @param {!Object} restApi A REST API instance
|
||||
* @return {!Promise<string>} A promise that resolves with the docs base
|
||||
@@ -56,7 +57,7 @@ limitations under the License.
|
||||
cachedPromise = undefined;
|
||||
},
|
||||
},
|
||||
Gerrit.BaseUrlBehavior,
|
||||
Gerrit.BaseUrlBehavior,
|
||||
];
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -25,6 +25,7 @@ limitations under the License.
|
||||
/**
|
||||
* Are any ancestors of the element (or the element itself) members of the
|
||||
* given class.
|
||||
*
|
||||
* @param {!Element} element
|
||||
* @param {string} className
|
||||
* @param {Element=} opt_stopElement If provided, stop traversing the
|
||||
|
||||
@@ -41,6 +41,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Returns the complement to the given column array
|
||||
*
|
||||
* @param {Array} columns
|
||||
* @return {!Array}
|
||||
*/
|
||||
@@ -63,6 +64,7 @@ limitations under the License.
|
||||
* The Project column was renamed to Repo, but some users may have
|
||||
* preferences that use its old name. If that column is found, rename it
|
||||
* before use.
|
||||
*
|
||||
* @param {!Array<string>} columns
|
||||
* @return {!Array<string>} If the column was renamed, returns a new array
|
||||
* with the corrected name. Otherwise, it returns the original param.
|
||||
|
||||
@@ -56,8 +56,8 @@ limitations under the License.
|
||||
return 0;
|
||||
},
|
||||
},
|
||||
Gerrit.BaseUrlBehavior,
|
||||
Gerrit.URLEncodingBehavior,
|
||||
Gerrit.BaseUrlBehavior,
|
||||
Gerrit.URLEncodingBehavior,
|
||||
];
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -52,6 +52,7 @@ limitations under the License.
|
||||
/**
|
||||
* Whether the given patch is a numbered parent of a merge (i.e. a negative
|
||||
* number).
|
||||
*
|
||||
* @param {string|number} n
|
||||
* @return {Boolean}
|
||||
*/
|
||||
@@ -124,8 +125,8 @@ limitations under the License.
|
||||
// 2 -> 3, 3 -> 5, etc.
|
||||
// Map an edit to the patchNum of parent*2... I.e. edit on 2 -> 4.
|
||||
const num = r => r._number === Gerrit.PatchSetBehavior.EDIT_NAME ?
|
||||
2 * editParent :
|
||||
2 * (r._number - 1) + 1;
|
||||
2 * editParent :
|
||||
2 * (r._number - 1) + 1;
|
||||
return revisions.sort((a, b) => num(b) - num(a));
|
||||
},
|
||||
|
||||
@@ -265,6 +266,7 @@ limitations under the License.
|
||||
/**
|
||||
* Convert parent indexes from patch range expressions to numbers.
|
||||
* For example, in a patch range expression `"-3"` becomes `3`.
|
||||
*
|
||||
* @param {number|string} rangeBase
|
||||
* @return {number}
|
||||
*/
|
||||
|
||||
@@ -25,6 +25,7 @@ limitations under the License.
|
||||
/**
|
||||
* Pretty-encodes a URL. Double-encodes the string, and then replaces
|
||||
* benevolent characters for legibility.
|
||||
*
|
||||
* @param {string} url
|
||||
* @param {boolean=} replaceSlashes
|
||||
* @return {string}
|
||||
@@ -45,6 +46,7 @@ limitations under the License.
|
||||
* Single decode for URL components. Will decode plus signs ('+') to spaces.
|
||||
* Note: because this function decodes once, it is not the inverse of
|
||||
* encodeURL.
|
||||
*
|
||||
* @param {string} url
|
||||
* @return {string}
|
||||
*/
|
||||
|
||||
@@ -240,8 +240,8 @@ limitations under the License.
|
||||
|
||||
test('directory view', () => {
|
||||
const {
|
||||
NEXT_FILE, NEXT_LINE, GO_TO_OPENED_CHANGES, SEARCH,
|
||||
SAVE_COMMENT,
|
||||
NEXT_FILE, NEXT_LINE, GO_TO_OPENED_CHANGES, SEARCH,
|
||||
SAVE_COMMENT,
|
||||
} = kb.Shortcut;
|
||||
const {DIFFS, EVERYWHERE, NAVIGATION} = kb.ShortcutSection;
|
||||
const {GO_KEY, ShortcutManager} = kb;
|
||||
|
||||
@@ -175,7 +175,7 @@ limitations under the License.
|
||||
return this.changeStatuses(change).join(', ');
|
||||
},
|
||||
},
|
||||
Gerrit.BaseUrlBehavior,
|
||||
Gerrit.BaseUrlBehavior,
|
||||
];
|
||||
})(window);
|
||||
</script>
|
||||
|
||||
@@ -28,6 +28,7 @@ limitations under the License.
|
||||
/**
|
||||
* Wraps a string to be used as a URL. An error is thrown if the string cannot
|
||||
* be considered safe.
|
||||
*
|
||||
* @constructor
|
||||
* @param {string} url the unwrapped, potentially unsafe URL.
|
||||
*/
|
||||
@@ -40,6 +41,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Get the string representation of the safe URL.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
Gerrit.SafeTypes.SafeUrl.prototype.asString = function() {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
/**
|
||||
* Fired when a section that was previously added was removed.
|
||||
*
|
||||
* @event added-section-removed
|
||||
*/
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ limitations under the License.
|
||||
};
|
||||
assert.equal(element._computePermissionName(name, permission,
|
||||
element.permissionValues, element.capabilities),
|
||||
element.capabilities[permission.id].name);
|
||||
element.capabilities[permission.id].name);
|
||||
|
||||
name = 'refs/for/*';
|
||||
permission = {
|
||||
@@ -218,7 +218,7 @@ limitations under the License.
|
||||
|
||||
assert.equal(element._computePermissionName(
|
||||
name, permission, element.permissionValues, element.capabilities),
|
||||
element.permissionValues[permission.id].name);
|
||||
element.permissionValues[permission.id].name);
|
||||
|
||||
name = 'refs/for/*';
|
||||
permission = {
|
||||
@@ -230,7 +230,7 @@ limitations under the License.
|
||||
|
||||
assert.equal(element._computePermissionName(name, permission,
|
||||
element.permissionValues, element.capabilities),
|
||||
'Label Code-Review');
|
||||
'Label Code-Review');
|
||||
|
||||
permission = {
|
||||
id: 'labelAs-Code-Review',
|
||||
@@ -241,7 +241,7 @@ limitations under the License.
|
||||
|
||||
assert.equal(element._computePermissionName(name, permission,
|
||||
element.permissionValues, element.capabilities),
|
||||
'Label Code-Review(On Behalf Of)');
|
||||
'Label Code-Review(On Behalf Of)');
|
||||
});
|
||||
|
||||
test('_computeSectionName', () => {
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
|
||||
/**
|
||||
* Opens the create overlay if the route has a hash 'create'
|
||||
*
|
||||
* @param {!Object} params
|
||||
*/
|
||||
_maybeOpenCreateOverlay(params) {
|
||||
@@ -120,11 +121,11 @@
|
||||
return;
|
||||
}
|
||||
this._groups = Object.keys(groups)
|
||||
.map(key => {
|
||||
const group = groups[key];
|
||||
group.name = key;
|
||||
return group;
|
||||
});
|
||||
.map(key => {
|
||||
const group = groups[key];
|
||||
group.name = key;
|
||||
return group;
|
||||
});
|
||||
this._loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -105,23 +105,23 @@
|
||||
.then(res => {
|
||||
this._filteredLinks = res.links;
|
||||
this._breadcrumbParentName = res.expandedSection ?
|
||||
res.expandedSection.name : '';
|
||||
res.expandedSection.name : '';
|
||||
|
||||
if (!res.expandedSection) {
|
||||
this._subsectionLinks = [];
|
||||
return;
|
||||
}
|
||||
this._subsectionLinks = [res.expandedSection]
|
||||
.concat(res.expandedSection.children).map(section => {
|
||||
return {
|
||||
text: !section.detailType ? 'Home' : section.name,
|
||||
value: section.view + (section.detailType || ''),
|
||||
view: section.view,
|
||||
url: section.url,
|
||||
detailType: section.detailType,
|
||||
parent: this._groupId || this._repoName || '',
|
||||
};
|
||||
});
|
||||
.concat(res.expandedSection.children).map(section => {
|
||||
return {
|
||||
text: !section.detailType ? 'Home' : section.name,
|
||||
value: section.view + (section.detailType || ''),
|
||||
view: section.view,
|
||||
url: section.url,
|
||||
detailType: section.detailType,
|
||||
parent: this._groupId || this._repoName || '',
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -107,21 +107,21 @@
|
||||
}
|
||||
return this.$.restAPI.getRepoBranches(
|
||||
input, this.repoName, SUGGESTIONS_LIMIT).then(response => {
|
||||
const branches = [];
|
||||
let branch;
|
||||
for (const key in response) {
|
||||
if (!response.hasOwnProperty(key)) { continue; }
|
||||
if (response[key].ref.startsWith('refs/heads/')) {
|
||||
branch = response[key].ref.substring('refs/heads/'.length);
|
||||
} else {
|
||||
branch = response[key].ref;
|
||||
}
|
||||
branches.push({
|
||||
name: branch,
|
||||
});
|
||||
}
|
||||
return branches;
|
||||
const branches = [];
|
||||
let branch;
|
||||
for (const key in response) {
|
||||
if (!response.hasOwnProperty(key)) { continue; }
|
||||
if (response[key].ref.startsWith('refs/heads/')) {
|
||||
branch = response[key].ref.substring('refs/heads/'.length);
|
||||
} else {
|
||||
branch = response[key].ref;
|
||||
}
|
||||
branches.push({
|
||||
name: branch,
|
||||
});
|
||||
}
|
||||
return branches;
|
||||
});
|
||||
},
|
||||
|
||||
_formatBooleanString(config) {
|
||||
|
||||
@@ -141,15 +141,15 @@
|
||||
_handleSavingGroupMember() {
|
||||
return this.$.restAPI.saveGroupMembers(this._groupName,
|
||||
this._groupMemberSearchId).then(config => {
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
this.$.restAPI.getGroupMembers(this._groupName).then(members => {
|
||||
this._groupMembers = members;
|
||||
});
|
||||
this._groupMemberSearchName = '';
|
||||
this._groupMemberSearchId = '';
|
||||
});
|
||||
if (!config) {
|
||||
return;
|
||||
}
|
||||
this.$.restAPI.getGroupMembers(this._groupName).then(members => {
|
||||
this._groupMembers = members;
|
||||
});
|
||||
this._groupMemberSearchName = '';
|
||||
this._groupMemberSearchId = '';
|
||||
});
|
||||
},
|
||||
|
||||
_handleDeleteConfirm() {
|
||||
@@ -239,24 +239,24 @@
|
||||
if (input.length === 0) { return Promise.resolve([]); }
|
||||
return this.$.restAPI.getSuggestedAccounts(
|
||||
input, SUGGESTIONS_LIMIT).then(accounts => {
|
||||
const accountSuggestions = [];
|
||||
let nameAndEmail;
|
||||
if (!accounts) { return []; }
|
||||
for (const key in accounts) {
|
||||
if (!accounts.hasOwnProperty(key)) { continue; }
|
||||
if (accounts[key].email !== undefined) {
|
||||
nameAndEmail = accounts[key].name +
|
||||
const accountSuggestions = [];
|
||||
let nameAndEmail;
|
||||
if (!accounts) { return []; }
|
||||
for (const key in accounts) {
|
||||
if (!accounts.hasOwnProperty(key)) { continue; }
|
||||
if (accounts[key].email !== undefined) {
|
||||
nameAndEmail = accounts[key].name +
|
||||
' <' + accounts[key].email + '>';
|
||||
} else {
|
||||
nameAndEmail = accounts[key].name;
|
||||
}
|
||||
accountSuggestions.push({
|
||||
name: nameAndEmail,
|
||||
value: accounts[key]._account_id,
|
||||
});
|
||||
}
|
||||
return accountSuggestions;
|
||||
} else {
|
||||
nameAndEmail = accounts[key].name;
|
||||
}
|
||||
accountSuggestions.push({
|
||||
name: nameAndEmail,
|
||||
value: accounts[key]._account_id,
|
||||
});
|
||||
}
|
||||
return accountSuggestions;
|
||||
});
|
||||
},
|
||||
|
||||
_getGroupSuggestions(input) {
|
||||
|
||||
@@ -169,10 +169,10 @@ limitations under the License.
|
||||
.querySelectorAll('.nameColumn a')[0].href, includedGroups[0].url);
|
||||
assert.equal(Polymer.dom(element.root)
|
||||
.querySelectorAll('.nameColumn a')[1].href,
|
||||
'https://test/site/group/url');
|
||||
'https://test/site/group/url');
|
||||
assert.equal(Polymer.dom(element.root)
|
||||
.querySelectorAll('.nameColumn a')[2].href,
|
||||
'https://test/site/group/url');
|
||||
'https://test/site/group/url');
|
||||
});
|
||||
|
||||
test('save members correctly', () => {
|
||||
|
||||
@@ -172,15 +172,15 @@
|
||||
}
|
||||
return this.$.restAPI.saveGroupOwner(this.groupId,
|
||||
owner).then(config => {
|
||||
this._owner = false;
|
||||
});
|
||||
this._owner = false;
|
||||
});
|
||||
},
|
||||
|
||||
_handleSaveDescription() {
|
||||
return this.$.restAPI.saveGroupDescription(this.groupId,
|
||||
this._groupConfig.description).then(config => {
|
||||
this._description = false;
|
||||
});
|
||||
this._description = false;
|
||||
});
|
||||
},
|
||||
|
||||
_handleSaveOptions() {
|
||||
@@ -190,8 +190,8 @@
|
||||
|
||||
return this.$.restAPI.saveGroupOptions(this.groupId,
|
||||
options).then(config => {
|
||||
this._options = false;
|
||||
});
|
||||
this._options = false;
|
||||
});
|
||||
},
|
||||
|
||||
_handleConfigName() {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
/**
|
||||
* Fired when a permission that was previously added was removed.
|
||||
*
|
||||
* @event added-permission-removed
|
||||
*/
|
||||
|
||||
@@ -228,7 +229,7 @@
|
||||
|
||||
_computeGroupName(groups, groupId) {
|
||||
return groups && groups[groupId] && groups[groupId].name ?
|
||||
groups[groupId].name : groupId;
|
||||
groups[groupId].name : groupId;
|
||||
},
|
||||
|
||||
_getGroupSuggestions() {
|
||||
|
||||
@@ -92,11 +92,11 @@
|
||||
return;
|
||||
}
|
||||
this._plugins = Object.keys(plugins)
|
||||
.map(key => {
|
||||
const plugin = plugins[key];
|
||||
plugin.name = key;
|
||||
return plugin;
|
||||
});
|
||||
.map(key => {
|
||||
const plugin = plugins[key];
|
||||
plugin.name = key;
|
||||
return plugin;
|
||||
});
|
||||
this._loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
// current value appears. If there is no parent repo, it is
|
||||
// initialized as an empty string.
|
||||
this._inheritFromFilter = res.inherits_from ?
|
||||
this._inheritsFrom.name : '';
|
||||
this._inheritsFrom.name : '';
|
||||
this._local = res.local;
|
||||
this._groups = res.groups;
|
||||
this._weblinks = res.config_web_links || [];
|
||||
@@ -346,6 +346,7 @@
|
||||
/**
|
||||
* As add / delete both can happen in the new section,
|
||||
* so here to make sure it will remove the deleted ones.
|
||||
*
|
||||
* @see Issue 11339
|
||||
*/
|
||||
this._recursivelyRemoveDeleted(addRemoveObj.add[k]);
|
||||
@@ -370,11 +371,11 @@
|
||||
};
|
||||
|
||||
const originalInheritsFromId = this._originalInheritsFrom ?
|
||||
this.singleDecodeURL(this._originalInheritsFrom.id) :
|
||||
null;
|
||||
this.singleDecodeURL(this._originalInheritsFrom.id) :
|
||||
null;
|
||||
const inheritsFromId = this._inheritsFrom ?
|
||||
this.singleDecodeURL(this._inheritsFrom.id) :
|
||||
null;
|
||||
this.singleDecodeURL(this._inheritsFrom.id) :
|
||||
null;
|
||||
|
||||
const inheritFromChanged =
|
||||
// Inherit from changed
|
||||
|
||||
@@ -676,7 +676,7 @@ limitations under the License.
|
||||
Polymer.dom(element.$$('gr-access-section').root).querySelectorAll(
|
||||
'gr-permission')[2];
|
||||
newPermission._handleAddRuleItem(
|
||||
{detail: {value: {id: 'Maintainers'}}});
|
||||
{detail: {value: {id: 'Maintainers'}}});
|
||||
assert.deepEqual(element._computeAddAndRemove(), expectedInput);
|
||||
|
||||
// Modify a section reference.
|
||||
@@ -909,7 +909,7 @@ limitations under the License.
|
||||
Polymer.dom(element.$$('gr-access-section').root).querySelectorAll(
|
||||
'gr-permission')[1];
|
||||
readPermission._handleAddRuleItem(
|
||||
{detail: {value: {id: 'Maintainers'}}});
|
||||
{detail: {value: {id: 'Maintainers'}}});
|
||||
|
||||
expectedInput = {
|
||||
add: {
|
||||
|
||||
@@ -101,17 +101,16 @@
|
||||
_handleEditRepoConfig() {
|
||||
return this.$.restAPI.createChange(this.repo, CONFIG_BRANCH,
|
||||
EDIT_CONFIG_SUBJECT, undefined, false, true).then(change => {
|
||||
const message = change ?
|
||||
CREATE_CHANGE_SUCCEEDED_MESSAGE :
|
||||
CREATE_CHANGE_FAILED_MESSAGE;
|
||||
this.dispatchEvent(new CustomEvent(
|
||||
'show-alert',
|
||||
{detail: {message}, bubbles: true, composed: true}));
|
||||
if (!change) { return; }
|
||||
const message = change ?
|
||||
CREATE_CHANGE_SUCCEEDED_MESSAGE :
|
||||
CREATE_CHANGE_FAILED_MESSAGE;
|
||||
this.dispatchEvent(new CustomEvent('show-alert',
|
||||
{detail: {message}, bubbles: true, composed: true}));
|
||||
if (!change) { return; }
|
||||
|
||||
Gerrit.Nav.navigateToRelativeUrl(Gerrit.Nav.getEditUrlForDiff(
|
||||
change, CONFIG_PATH, INITIAL_PATCHSET));
|
||||
});
|
||||
Gerrit.Nav.navigateToRelativeUrl(Gerrit.Nav.getEditUrlForDiff(
|
||||
change, CONFIG_PATH, INITIAL_PATCHSET));
|
||||
});
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
// Group by ref and sort by id.
|
||||
const dashboards = res.concat.apply([], res).sort((a, b) =>
|
||||
a.id < b.id ? -1 : 1);
|
||||
a.id < b.id ? -1 : 1);
|
||||
const dashboardsByRef = {};
|
||||
dashboards.forEach(d => {
|
||||
if (!dashboardsByRef[d.ref]) {
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
_determineIfOwner(repo) {
|
||||
return this.$.restAPI.getRepoAccess(repo)
|
||||
.then(access =>
|
||||
this._isOwner = access && !!access[repo].is_owner);
|
||||
this._isOwner = access && !!access[repo].is_owner);
|
||||
},
|
||||
|
||||
_paramsChanged(params) {
|
||||
@@ -125,17 +125,17 @@
|
||||
if (detailType === DETAIL_TYPES.BRANCHES) {
|
||||
return this.$.restAPI.getRepoBranches(
|
||||
filter, repo, itemsPerPage, offset, errFn).then(items => {
|
||||
if (!items) { return; }
|
||||
this._items = items;
|
||||
this._loading = false;
|
||||
});
|
||||
if (!items) { return; }
|
||||
this._items = items;
|
||||
this._loading = false;
|
||||
});
|
||||
} else if (detailType === DETAIL_TYPES.TAGS) {
|
||||
return this.$.restAPI.getRepoTags(
|
||||
filter, repo, itemsPerPage, offset, errFn).then(items => {
|
||||
if (!items) { return; }
|
||||
this._items = items;
|
||||
this._loading = false;
|
||||
});
|
||||
if (!items) { return; }
|
||||
this._items = items;
|
||||
this._loading = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
_computeCanEditClass(ref, detailType, isOwner) {
|
||||
return isOwner && this._stripRefs(ref, detailType) === 'HEAD' ?
|
||||
'canEdit' : '';
|
||||
'canEdit' : '';
|
||||
},
|
||||
|
||||
_handleEditRevision(e) {
|
||||
|
||||
@@ -155,9 +155,9 @@ limitations under the License.
|
||||
const cancelBtn = Polymer.dom(element.root).querySelector('.cancelBtn');
|
||||
const editBtn = Polymer.dom(element.root).querySelector('.editBtn');
|
||||
const revisionNoEditing = Polymer.dom(element.root)
|
||||
.querySelector('.revisionNoEditing');
|
||||
.querySelector('.revisionNoEditing');
|
||||
const revisionWithEditing = Polymer.dom(element.root)
|
||||
.querySelector('.revisionWithEditing');
|
||||
.querySelector('.revisionWithEditing');
|
||||
|
||||
sandbox.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
|
||||
sandbox.stub(element.$.restAPI, 'getRepoAccess').returns(
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
|
||||
/**
|
||||
* Opens the create overlay if the route has a hash 'create'
|
||||
*
|
||||
* @param {!Object} params
|
||||
*/
|
||||
_maybeOpenCreateOverlay(params) {
|
||||
|
||||
@@ -54,7 +54,7 @@ limitations under the License.
|
||||
{base: {config: {}}}), []);
|
||||
assert.deepEqual(element._computePluginConfigOptions(
|
||||
{base: {config: {testKey: 'testInfo'}}}),
|
||||
[{_key: 'testKey', info: 'testInfo'}]);
|
||||
[{_key: 'testKey', info: 'testInfo'}]);
|
||||
});
|
||||
|
||||
test('_computeDisabled', () => {
|
||||
|
||||
@@ -283,8 +283,8 @@
|
||||
_handleSaveRepoConfig() {
|
||||
return this.$.restAPI.saveRepoConfig(this.repo,
|
||||
this._formatRepoConfigForSave(this._repoConfig)).then(() => {
|
||||
this._configChanged = false;
|
||||
});
|
||||
this._configChanged = false;
|
||||
});
|
||||
},
|
||||
|
||||
_handleConfigChanged() {
|
||||
@@ -327,7 +327,7 @@
|
||||
command: commandObj[title]
|
||||
.replace(/\$\{project\}/gi, encodeURI(repo))
|
||||
.replace(/\$\{project-base-name\}/gi,
|
||||
encodeURI(repo.substring(repo.lastIndexOf('/') + 1))),
|
||||
encodeURI(repo.substring(repo.lastIndexOf('/') + 1))),
|
||||
});
|
||||
}
|
||||
return commands;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
/**
|
||||
* Fired when a rule that was previously added was removed.
|
||||
*
|
||||
* @event added-rule-removed
|
||||
*/
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ limitations under the License.
|
||||
let permission = 'priority';
|
||||
let label;
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'BATCH'});
|
||||
{action: 'BATCH'});
|
||||
permission = 'label-Code-Review';
|
||||
label = {values: [
|
||||
{value: -2, text: 'This shall not be merged'},
|
||||
@@ -139,7 +139,7 @@ limitations under the License.
|
||||
permission = 'push';
|
||||
label = undefined;
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'ALLOW', force: false});
|
||||
{action: 'ALLOW', force: false});
|
||||
permission = 'submit';
|
||||
assert.deepEqual(element._getDefaultRuleValues(permission, label),
|
||||
{action: 'ALLOW'});
|
||||
|
||||
@@ -59,31 +59,31 @@ limitations under the License.
|
||||
{labels: {}}, 'Verified'), 'cell label u-gray-background');
|
||||
assert.equal(element._computeLabelClass(
|
||||
{labels: {Verified: {approved: true, value: 1}}}, 'Verified'),
|
||||
'cell label u-green u-monospace');
|
||||
'cell label u-green u-monospace');
|
||||
assert.equal(element._computeLabelClass(
|
||||
{labels: {Verified: {rejected: true, value: -1}}}, 'Verified'),
|
||||
'cell label u-monospace u-red');
|
||||
'cell label u-monospace u-red');
|
||||
assert.equal(element._computeLabelClass(
|
||||
{labels: {'Code-Review': {value: 1}}}, 'Code-Review'),
|
||||
'cell label u-green u-monospace');
|
||||
'cell label u-green u-monospace');
|
||||
assert.equal(element._computeLabelClass(
|
||||
{labels: {'Code-Review': {value: -1}}}, 'Code-Review'),
|
||||
'cell label u-monospace u-red');
|
||||
'cell label u-monospace u-red');
|
||||
assert.equal(element._computeLabelClass(
|
||||
{labels: {'Code-Review': {value: -1}}}, 'Verified'),
|
||||
'cell label u-gray-background');
|
||||
'cell label u-gray-background');
|
||||
|
||||
assert.equal(element._computeLabelTitle({labels: {}}, 'Verified'),
|
||||
'Label not applicable');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {Verified: {approved: {name: 'Diffy'}}}}, 'Verified'),
|
||||
'Verified\nby Diffy');
|
||||
'Verified\nby Diffy');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {Verified: {approved: {name: 'Diffy'}}}}, 'Code-Review'),
|
||||
'Label not applicable');
|
||||
'Label not applicable');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {Verified: {rejected: {name: 'Diffy'}}}}, 'Verified'),
|
||||
'Verified\nby Diffy');
|
||||
'Verified\nby Diffy');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {'Code-Review': {disliked: {name: 'Diffy'}, value: -1}}},
|
||||
'Code-Review'), 'Code-Review\nby Diffy');
|
||||
@@ -93,19 +93,19 @@ limitations under the License.
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {'Code-Review': {recommended: {name: 'Diffy'},
|
||||
rejected: {name: 'Admin'}}}}, 'Code-Review'),
|
||||
'Code-Review\nby Admin');
|
||||
'Code-Review\nby Admin');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {'Code-Review': {approved: {name: 'Diffy'},
|
||||
rejected: {name: 'Admin'}}}}, 'Code-Review'),
|
||||
'Code-Review\nby Admin');
|
||||
'Code-Review\nby Admin');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {'Code-Review': {recommended: {name: 'Diffy'},
|
||||
disliked: {name: 'Admin'}, value: -1}}}, 'Code-Review'),
|
||||
'Code-Review\nby Admin');
|
||||
'Code-Review\nby Admin');
|
||||
assert.equal(element._computeLabelTitle(
|
||||
{labels: {'Code-Review': {approved: {name: 'Diffy'},
|
||||
disliked: {name: 'Admin'}, value: -1}}}, 'Code-Review'),
|
||||
'Code-Review\nby Diffy');
|
||||
'Code-Review\nby Diffy');
|
||||
|
||||
assert.equal(element._computeLabelValue({labels: {}}), '');
|
||||
assert.equal(element._computeLabelValue({labels: {}}, 'Verified'), '');
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
*
|
||||
* Need sub-property declaration since it is used in template before
|
||||
* assignment.
|
||||
*
|
||||
* @type {{ selectedChangeIndex: (number|undefined) }}
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
this.showNumber = !!(preferences &&
|
||||
preferences.legacycid_in_change_table);
|
||||
this.visibleChangeTableColumns = preferences.change_table.length > 0 ?
|
||||
this.getVisibleColumns(preferences.change_table) : this.columnNames;
|
||||
this.getVisibleColumns(preferences.change_table) : this.columnNames;
|
||||
} else {
|
||||
// Not logged in.
|
||||
this.showNumber = false;
|
||||
|
||||
@@ -113,7 +113,7 @@ limitations under the License.
|
||||
|
||||
test('computed fields', () => {
|
||||
assert.equal(element._computeLabelNames(
|
||||
[{results: [{_number: 0, labels: {}}]}]).length, 0);
|
||||
[{results: [{_number: 0, labels: {}}]}]).length, 0);
|
||||
assert.equal(element._computeLabelNames([
|
||||
{results: [
|
||||
{_number: 0, labels: {Verified: {approved: {}}}},
|
||||
|
||||
@@ -109,21 +109,21 @@
|
||||
};
|
||||
return this.$.restAPI.getDashboard(
|
||||
project, dashboard, errFn).then(response => {
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
if (!response) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
title: response.title,
|
||||
sections: response.sections.map(section => {
|
||||
const suffix = response.foreach ? ' ' + response.foreach : '';
|
||||
return {
|
||||
title: response.title,
|
||||
sections: response.sections.map(section => {
|
||||
const suffix = response.foreach ? ' ' + response.foreach : '';
|
||||
return {
|
||||
name: section.name,
|
||||
query: (section.query + suffix).replace(
|
||||
PROJECT_PLACEHOLDER_PATTERN, project),
|
||||
};
|
||||
}),
|
||||
name: section.name,
|
||||
query: (section.query + suffix).replace(
|
||||
PROJECT_PLACEHOLDER_PATTERN, project),
|
||||
};
|
||||
});
|
||||
}),
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
_computeTitle(user) {
|
||||
@@ -156,11 +156,11 @@
|
||||
this._loading = true;
|
||||
const {project, dashboard, title, user, sections} = this.params;
|
||||
const dashboardPromise = project ?
|
||||
this._getProjectDashboard(project, dashboard) :
|
||||
Promise.resolve(Gerrit.Nav.getUserDashboard(
|
||||
user,
|
||||
sections,
|
||||
title || this._computeTitle(user)));
|
||||
this._getProjectDashboard(project, dashboard) :
|
||||
Promise.resolve(Gerrit.Nav.getUserDashboard(
|
||||
user,
|
||||
sections,
|
||||
title || this._computeTitle(user)));
|
||||
|
||||
const checkForNewUser = !project && user === 'self';
|
||||
return dashboardPromise
|
||||
@@ -194,8 +194,8 @@
|
||||
|
||||
const queries = res.sections
|
||||
.map(section => section.suffixForDashboard ?
|
||||
section.query + ' ' + section.suffixForDashboard :
|
||||
section.query);
|
||||
section.query + ' ' + section.suffixForDashboard :
|
||||
section.query);
|
||||
|
||||
if (checkForNewUser) {
|
||||
queries.push('owner:self limit:1');
|
||||
@@ -215,7 +215,7 @@
|
||||
results,
|
||||
isOutgoing: res.sections[i].isOutgoing,
|
||||
})).filter((section, i) => i < res.sections.length && (
|
||||
!res.sections[i].hideIfEmpty ||
|
||||
!res.sections[i].hideIfEmpty ||
|
||||
section.results.length));
|
||||
});
|
||||
},
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
_computeDashboardLinkClass(showDashboardLink, loggedIn) {
|
||||
return showDashboardLink && loggedIn ?
|
||||
'dashboardLink' : 'dashboardLink hide';
|
||||
'dashboardLink' : 'dashboardLink hide';
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
/**
|
||||
* Fired when an action is tapped.
|
||||
*
|
||||
* @event <action key>-tap
|
||||
* @event custom-tap - naming pattern: <action key>-tap
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -625,9 +625,9 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string=} actionName
|
||||
*/
|
||||
/**
|
||||
* @param {string=} actionName
|
||||
*/
|
||||
_deleteAndNotify(actionName) {
|
||||
if (this.actions && this.actions[actionName]) {
|
||||
delete this.actions[actionName];
|
||||
@@ -868,6 +868,7 @@
|
||||
|
||||
/**
|
||||
* Capitalize the first letter and lowecase all others.
|
||||
*
|
||||
* @param {string} s
|
||||
* @return {string}
|
||||
*/
|
||||
@@ -1362,6 +1363,7 @@
|
||||
/**
|
||||
* Merge sources of change actions into a single ordered array of action
|
||||
* values.
|
||||
*
|
||||
* @param {!Array} changeActionsRecord
|
||||
* @param {!Array} revisionActionsRecord
|
||||
* @param {!Array} primariesRecord
|
||||
@@ -1448,9 +1450,9 @@
|
||||
|
||||
_filterPrimaryActions(_topLevelActions) {
|
||||
this._topLevelPrimaryActions = _topLevelActions.filter(action =>
|
||||
action.__primary);
|
||||
action.__primary);
|
||||
this._topLevelSecondaryActions = _topLevelActions.filter(action =>
|
||||
!action.__primary);
|
||||
!action.__primary);
|
||||
},
|
||||
|
||||
_computeMenuActions(actionRecord, hiddenActionsRecord) {
|
||||
|
||||
@@ -378,7 +378,7 @@ limitations under the License.
|
||||
element._handleRebaseConfirm({detail: {base: '1234'}});
|
||||
rebaseAction.rebaseOnCurrent = true;
|
||||
assert.deepEqual(fireActionStub.lastCall.args,
|
||||
['/rebase', rebaseAction, true, {base: '1234'}]);
|
||||
['/rebase', rebaseAction, true, {base: '1234'}]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -114,7 +114,7 @@ limitations under the License.
|
||||
js_resource_paths: [],
|
||||
html_resource_paths: [
|
||||
new URL('test/plugin.html?' + Math.random(),
|
||||
window.location.href).toString(),
|
||||
window.location.href).toString(),
|
||||
],
|
||||
},
|
||||
};
|
||||
@@ -140,7 +140,7 @@ limitations under the License.
|
||||
setup(() => {
|
||||
Gerrit.install(p => plugin = p, '0.1',
|
||||
new URL('test/plugin.html?' + Math.random(),
|
||||
window.location.href).toString());
|
||||
window.location.href).toString());
|
||||
sandbox.stub(Gerrit, '_arePluginsLoaded').returns(true);
|
||||
Gerrit._loadPlugins([]);
|
||||
element = createElement();
|
||||
|
||||
@@ -228,12 +228,13 @@
|
||||
this._newHashtag = '';
|
||||
this.$.restAPI.setChangeHashtag(
|
||||
this.change._number, {add: [newHashtag]}).then(newHashtag => {
|
||||
this.set(['change', 'hashtags'], newHashtag);
|
||||
if (newHashtag !== lastHashtag) {
|
||||
this.dispatchEvent(new CustomEvent(
|
||||
'hashtag-changed', {bubbles: true, composed: true}));
|
||||
}
|
||||
});
|
||||
this.set(['change', 'hashtags'], newHashtag);
|
||||
if (newHashtag !== lastHashtag) {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('hashtag-changed', {
|
||||
bubbles: true, composed: true}));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_computeTopicReadOnly(mutable, change) {
|
||||
@@ -344,7 +345,7 @@
|
||||
if (!this.change || !this.change.status) return '';
|
||||
return Gerrit.Nav.getUrlForBranch(branch, project,
|
||||
this.change.status == this.ChangeStatus.NEW ? 'open' :
|
||||
this.change.status.toLowerCase());
|
||||
this.change.status.toLowerCase());
|
||||
},
|
||||
|
||||
_computeTopicURL(topic) {
|
||||
@@ -395,6 +396,7 @@
|
||||
/**
|
||||
* Get the user with the specified role on the change. Returns null if the
|
||||
* user with that role is the same as the owner.
|
||||
*
|
||||
* @param {!Object} change
|
||||
* @param {string} role One of the values from _CHANGE_ROLE
|
||||
* @return {Object|null} either an accound or null.
|
||||
|
||||
@@ -426,7 +426,7 @@ limitations under the License.
|
||||
{current_revision: '789', revisions: {456: {commit: {parents}}}}));
|
||||
assert.equal(element._computeParents(
|
||||
{current_revision: '456', revisions: {456: {commit: {parents}}}}),
|
||||
parents);
|
||||
parents);
|
||||
});
|
||||
|
||||
test('_computeParentsLabel', () => {
|
||||
|
||||
@@ -135,8 +135,8 @@
|
||||
|
||||
_computeShowHideIcon(showOptionalLabels) {
|
||||
return showOptionalLabels ?
|
||||
'gr-icons:expand-less' :
|
||||
'gr-icons:expand-more';
|
||||
'gr-icons:expand-less' :
|
||||
'gr-icons:expand-more';
|
||||
},
|
||||
|
||||
_computeSectionClass(show) {
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
computed:
|
||||
'_computeChangeIdCommitMessageError(_latestCommitMessage, _change)',
|
||||
},
|
||||
/** @type {?} */
|
||||
/** @type {?} */
|
||||
_patchRange: {
|
||||
type: Object,
|
||||
},
|
||||
@@ -456,16 +456,16 @@
|
||||
this.$.commitMessageEditor.disabled = true;
|
||||
this.$.restAPI.putChangeCommitMessage(
|
||||
this._changeNum, message).then(resp => {
|
||||
this.$.commitMessageEditor.disabled = false;
|
||||
if (!resp.ok) { return; }
|
||||
this.$.commitMessageEditor.disabled = false;
|
||||
if (!resp.ok) { return; }
|
||||
|
||||
this._latestCommitMessage = this._prepareCommitMsgForLinkify(
|
||||
message);
|
||||
this._editingCommitMessage = false;
|
||||
this._reloadWindow();
|
||||
}).catch(err => {
|
||||
this.$.commitMessageEditor.disabled = false;
|
||||
});
|
||||
this._latestCommitMessage = this._prepareCommitMsgForLinkify(
|
||||
message);
|
||||
this._editingCommitMessage = false;
|
||||
this._reloadWindow();
|
||||
}).catch(err => {
|
||||
this.$.commitMessageEditor.disabled = false;
|
||||
});
|
||||
},
|
||||
|
||||
_reloadWindow() {
|
||||
@@ -819,7 +819,7 @@
|
||||
|
||||
_viewStateChanged(viewState) {
|
||||
this._numFilesShown = viewState.numFilesShown ?
|
||||
viewState.numFilesShown : DEFAULT_NUM_FILES_SHOWN;
|
||||
viewState.numFilesShown : DEFAULT_NUM_FILES_SHOWN;
|
||||
},
|
||||
|
||||
_numFilesShownChanged(numFilesShown) {
|
||||
@@ -920,6 +920,7 @@
|
||||
/**
|
||||
* Gets base patch number, if it is a parent try and decide from
|
||||
* preference whether to default to `auto merge`, `Parent 1` or `PARENT`.
|
||||
*
|
||||
* @param {Object} change
|
||||
* @param {Object} patchRange
|
||||
* @return {number|string}
|
||||
@@ -937,7 +938,7 @@
|
||||
// check that there is at least 2 parents otherwise fall back to 1,
|
||||
// which means there is only one parent.
|
||||
const parentCount = parentCounts.hasOwnProperty(1) ?
|
||||
parentCounts[1] : 1;
|
||||
parentCounts[1] : 1;
|
||||
|
||||
const preferFirst = this._prefs &&
|
||||
this._prefs.default_base_for_merges === 'FIRST_PARENT';
|
||||
@@ -1327,10 +1328,10 @@
|
||||
_getLatestCommitMessage() {
|
||||
return this.$.restAPI.getChangeCommitInfo(this._changeNum,
|
||||
this.computeLatestPatchNum(this._allPatchSets)).then(commitInfo => {
|
||||
if (!commitInfo) return Promise.resolve();
|
||||
this._latestCommitMessage =
|
||||
if (!commitInfo) return Promise.resolve();
|
||||
this._latestCommitMessage =
|
||||
this._prepareCommitMsgForLinkify(commitInfo.message);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_getLatestRevisionSHA(change) {
|
||||
@@ -1376,7 +1377,7 @@
|
||||
this._changeComments = comments;
|
||||
this._diffDrafts = Object.assign({}, this._changeComments.drafts);
|
||||
this._commentThreads = this._changeComments.getAllThreadsForChange()
|
||||
.map(c => Object.assign({}, c));
|
||||
.map(c => Object.assign({}, c));
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1394,6 +1395,7 @@
|
||||
|
||||
/**
|
||||
* Reload the change.
|
||||
*
|
||||
* @param {boolean=} opt_isLocationChange Reloads the related changes
|
||||
* when true and ends reporting events that started on location change.
|
||||
* @return {Promise} A promise that resolves when the core data has loaded.
|
||||
@@ -1800,7 +1802,7 @@
|
||||
*/
|
||||
_handleEditTap() {
|
||||
const editInfo = Object.values(this._change.revisions).find(info =>
|
||||
info._number === this.EDIT_NAME);
|
||||
info._number === this.EDIT_NAME);
|
||||
|
||||
if (editInfo) {
|
||||
Gerrit.Nav.navigateToChange(this._change, this.EDIT_NAME);
|
||||
|
||||
@@ -176,7 +176,7 @@ limitations under the License.
|
||||
assert.isFalse(element.$.replyOverlay.opened);
|
||||
assert(openSpy.lastCall.calledWithExactly(
|
||||
element.$.replyDialog.FocusTarget.ANY),
|
||||
'_openReplyDialog should have been passed ANY');
|
||||
'_openReplyDialog should have been passed ANY');
|
||||
assert.equal(openSpy.callCount, 1);
|
||||
done();
|
||||
});
|
||||
@@ -1046,7 +1046,7 @@ limitations under the License.
|
||||
MockInteractions.tap(element.$.replyBtn);
|
||||
assert(openStub.lastCall.calledWithExactly(
|
||||
element.$.replyDialog.FocusTarget.ANY),
|
||||
'_openReplyDialog should have been passed ANY');
|
||||
'_openReplyDialog should have been passed ANY');
|
||||
assert.equal(openStub.callCount, 1);
|
||||
});
|
||||
|
||||
@@ -1058,7 +1058,7 @@ limitations under the License.
|
||||
{message: {message: 'text'}});
|
||||
assert(openStub.lastCall.calledWithExactly(
|
||||
element.$.replyDialog.FocusTarget.BODY),
|
||||
'_openReplyDialog should have been passed BODY');
|
||||
'_openReplyDialog should have been passed BODY');
|
||||
assert.equal(openStub.callCount, 1);
|
||||
done();
|
||||
});
|
||||
@@ -1483,7 +1483,7 @@ limitations under the License.
|
||||
|
||||
test('_computeEditMode', () => {
|
||||
const callCompute = (range, params) =>
|
||||
element._computeEditMode({base: range}, {base: params});
|
||||
element._computeEditMode({base: range}, {base: params});
|
||||
assert.isFalse(callCompute({}, {}));
|
||||
assert.isTrue(callCompute({}, {edit: true}));
|
||||
assert.isFalse(callCompute({basePatchNum: 'PARENT', patchNum: 1}, {}));
|
||||
@@ -1703,7 +1703,7 @@ limitations under the License.
|
||||
|
||||
element._patchRange = {patchNum: 1};
|
||||
element.$.actions.dispatchEvent(new CustomEvent('stop-edit-tap',
|
||||
{bubbles: false}));
|
||||
{bubbles: false}));
|
||||
});
|
||||
|
||||
suite('plugin endpoints', () => {
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
_computeDiffLineURL(file, changeNum, patchNum, comment) {
|
||||
const basePatchNum = comment.hasOwnProperty('parent') ?
|
||||
-comment.parent : null;
|
||||
-comment.parent : null;
|
||||
return Gerrit.Nav.getUrlForDiffById(this.changeNum, this.projectName,
|
||||
file, patchNum, basePatchNum, comment.line,
|
||||
this._isOnParent(comment));
|
||||
|
||||
@@ -98,21 +98,21 @@
|
||||
}
|
||||
return this.$.restAPI.getRepoBranches(
|
||||
input, this.project, SUGGESTIONS_LIMIT).then(response => {
|
||||
const branches = [];
|
||||
let branch;
|
||||
for (const key in response) {
|
||||
if (!response.hasOwnProperty(key)) { continue; }
|
||||
if (response[key].ref.startsWith('refs/heads/')) {
|
||||
branch = response[key].ref.substring('refs/heads/'.length);
|
||||
} else {
|
||||
branch = response[key].ref;
|
||||
}
|
||||
branches.push({
|
||||
name: branch,
|
||||
});
|
||||
}
|
||||
return branches;
|
||||
const branches = [];
|
||||
let branch;
|
||||
for (const key in response) {
|
||||
if (!response.hasOwnProperty(key)) { continue; }
|
||||
if (response[key].ref.startsWith('refs/heads/')) {
|
||||
branch = response[key].ref.substring('refs/heads/'.length);
|
||||
} else {
|
||||
branch = response[key].ref;
|
||||
}
|
||||
branches.push({
|
||||
name: branch,
|
||||
});
|
||||
}
|
||||
return branches;
|
||||
});
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -68,21 +68,21 @@
|
||||
}
|
||||
return this.$.restAPI.getRepoBranches(
|
||||
input, this.project, SUGGESTIONS_LIMIT).then(response => {
|
||||
const branches = [];
|
||||
let branch;
|
||||
for (const key in response) {
|
||||
if (!response.hasOwnProperty(key)) { continue; }
|
||||
if (response[key].ref.startsWith('refs/heads/')) {
|
||||
branch = response[key].ref.substring('refs/heads/'.length);
|
||||
} else {
|
||||
branch = response[key].ref;
|
||||
}
|
||||
branches.push({
|
||||
name: branch,
|
||||
});
|
||||
}
|
||||
return branches;
|
||||
const branches = [];
|
||||
let branch;
|
||||
for (const key in response) {
|
||||
if (!response.hasOwnProperty(key)) { continue; }
|
||||
if (response[key].ref.startsWith('refs/heads/')) {
|
||||
branch = response[key].ref.substring('refs/heads/'.length);
|
||||
} else {
|
||||
branch = response[key].ref;
|
||||
}
|
||||
branches.push({
|
||||
name: branch,
|
||||
});
|
||||
}
|
||||
return branches;
|
||||
});
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
|
||||
_getChangeSuggestions(input) {
|
||||
return this._getRecentChanges().then(changes =>
|
||||
this._filterChanges(input, changes));
|
||||
this._filterChanges(input, changes));
|
||||
},
|
||||
|
||||
_filterChanges(input, changes) {
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
for (const rev of Object.values(change.revisions || {})) {
|
||||
if (this.patchNumEquals(rev._number, patchNum)) {
|
||||
const parentLength = rev.commit && rev.commit.parents ?
|
||||
rev.commit.parents.length : 0;
|
||||
rev.commit.parents.length : 0;
|
||||
return parentLength == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ limitations under the License.
|
||||
test('computed fields', () => {
|
||||
assert.equal(element._computeArchiveDownloadLink(
|
||||
{project: 'test/project', _number: 123}, 2, 'tgz'),
|
||||
'/changes/test%2Fproject~123/revisions/2/archive?format=tgz');
|
||||
'/changes/test%2Fproject~123/revisions/2/archive?format=tgz');
|
||||
});
|
||||
|
||||
test('close event', done => {
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
|
||||
const rev = this.getRevisionByPatchNum(change.revisions, patchNum);
|
||||
this._patchsetDescription = (rev && rev.description) ?
|
||||
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
||||
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
||||
},
|
||||
|
||||
_handleDescriptionRemoved(e) {
|
||||
@@ -176,6 +176,7 @@
|
||||
|
||||
/**
|
||||
* Update the patchset description with the rest API.
|
||||
*
|
||||
* @param {string} desc
|
||||
* @param {?(Event|Node)} e
|
||||
* @return {!Promise}
|
||||
@@ -257,7 +258,7 @@
|
||||
_computeUploadHelpContainerClass(change, account) {
|
||||
const changeIsMerged = change && change.status === MERGED_STATUS;
|
||||
const ownerId = change && change.owner && change.owner._account_id ?
|
||||
change.owner._account_id : null;
|
||||
change.owner._account_id : null;
|
||||
const userId = account && account._account_id;
|
||||
const userIsOwner = ownerId && userId && ownerId === userId;
|
||||
const hideContainer = !userIsOwner || changeIsMerged;
|
||||
|
||||
@@ -520,6 +520,7 @@
|
||||
/**
|
||||
* The closure compiler doesn't realize this.specialFilePathCompare is
|
||||
* valid.
|
||||
*
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
_normalizeChangeFilesResponse(response) {
|
||||
@@ -839,7 +840,7 @@
|
||||
|
||||
_computeShowHideIcon(path, expandedFilesRecord) {
|
||||
return this._isFileExpanded(path, expandedFilesRecord) ?
|
||||
'gr-icons:expand-less' : 'gr-icons:expand-more';
|
||||
'gr-icons:expand-less' : 'gr-icons:expand-more';
|
||||
},
|
||||
|
||||
_computeFiles(filesByPath, changeComments, patchRange, reviewed, loading) {
|
||||
@@ -879,7 +880,7 @@
|
||||
}
|
||||
|
||||
const previousNumFilesShown = this._shownFiles ?
|
||||
this._shownFiles.length : 0;
|
||||
this._shownFiles.length : 0;
|
||||
|
||||
const filesShown = files.slice(0, numFilesShown);
|
||||
this.fire('files-shown-changed', {length: filesShown.length});
|
||||
@@ -954,19 +955,20 @@
|
||||
|
||||
const rev = this.getRevisionByPatchNum(revisions, patchNum);
|
||||
return (rev && rev.description) ?
|
||||
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
||||
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a descriptive label for use in the status indicator's tooltip and
|
||||
* ARIA label.
|
||||
*
|
||||
* @param {string} status
|
||||
* @return {string}
|
||||
*/
|
||||
_computeFileStatusLabel(status) {
|
||||
const statusCode = this._computeFileStatus(status);
|
||||
return FileStatus.hasOwnProperty(statusCode) ?
|
||||
FileStatus[statusCode] : 'Status Unknown';
|
||||
FileStatus[statusCode] : 'Status Unknown';
|
||||
},
|
||||
|
||||
_isFileExpanded(path, expandedFilesRecord) {
|
||||
@@ -992,13 +994,14 @@
|
||||
* entries in the expanded list, then render each diff corresponding in
|
||||
* order by waiting for the previous diff to finish before starting the next
|
||||
* one.
|
||||
*
|
||||
* @param {!Array} record The splice record in the expanded paths list.
|
||||
*/
|
||||
_expandedPathsChanged(record) {
|
||||
// Clear content for any diffs that are not open so if they get re-opened
|
||||
// the stale content does not flash before it is cleared and reloaded.
|
||||
const collapsedDiffs = this.diffs.filter(diff =>
|
||||
this._expandedFilePaths.indexOf(diff.path) === -1);
|
||||
this._expandedFilePaths.indexOf(diff.path) === -1);
|
||||
this._clearCollapsedDiffs(collapsedDiffs);
|
||||
|
||||
if (!record) { return; } // Happens after "Collapse all" clicked.
|
||||
@@ -1008,9 +1011,9 @@
|
||||
|
||||
// Find the paths introduced by the new index splices:
|
||||
const newPaths = record.indexSplices
|
||||
.map(splice => splice.object.slice(
|
||||
splice.index, splice.index + splice.addedCount))
|
||||
.reduce((acc, paths) => acc.concat(paths), []);
|
||||
.map(splice => splice.object.slice(
|
||||
splice.index, splice.index + splice.addedCount))
|
||||
.reduce((acc, paths) => acc.concat(paths), []);
|
||||
|
||||
// Required so that the newly created diff view is included in this.diffs.
|
||||
Polymer.dom.flush();
|
||||
@@ -1036,6 +1039,7 @@
|
||||
* Given an array of paths and a NodeList of diff elements, render the diff
|
||||
* for each path in order, awaiting the previous render to complete before
|
||||
* continung.
|
||||
*
|
||||
* @param {!Array<string>} paths
|
||||
* @param {!NodeList<!Object>} diffElements (GrDiffHostElement)
|
||||
* @param {number} initialCount The total number of paths in the pass. This
|
||||
@@ -1081,6 +1085,7 @@
|
||||
|
||||
/**
|
||||
* In the given NodeList of diff elements, find the diff for the given path.
|
||||
*
|
||||
* @param {string} path
|
||||
* @param {!NodeList<!Object>} diffElements (GrDiffElement)
|
||||
* @return {!Object|undefined} (GrDiffElement)
|
||||
@@ -1095,6 +1100,7 @@
|
||||
|
||||
/**
|
||||
* Reset the comments of a modified thread
|
||||
*
|
||||
* @param {string} rootId
|
||||
* @param {string} path
|
||||
*/
|
||||
@@ -1141,6 +1147,7 @@
|
||||
* Update the loading class for the file list rows. The update is inside a
|
||||
* debouncer so that the file list doesn't flash gray when the API requests
|
||||
* are reasonably fast.
|
||||
*
|
||||
* @param {boolean} loading
|
||||
*/
|
||||
_loadingChanged(loading) {
|
||||
@@ -1166,6 +1173,7 @@
|
||||
/**
|
||||
* Given a file path, return whether that path should have visible size bars
|
||||
* and be included in the size bars calculation.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {boolean}
|
||||
*/
|
||||
@@ -1175,7 +1183,9 @@
|
||||
|
||||
/**
|
||||
* Compute size bar layout values from the file list.
|
||||
*
|
||||
* @return {Gerrit.LayoutStats|undefined}
|
||||
*
|
||||
*/
|
||||
_computeSizeBarLayout(shownFilesRecord) {
|
||||
if (!shownFilesRecord || !shownFilesRecord.base) { return undefined; }
|
||||
@@ -1209,6 +1219,7 @@
|
||||
|
||||
/**
|
||||
* Get the width of the addition bar for a file.
|
||||
*
|
||||
* @param {Object} file
|
||||
* @param {Gerrit.LayoutStats} stats
|
||||
* @return {number}
|
||||
@@ -1226,6 +1237,7 @@
|
||||
|
||||
/**
|
||||
* Get the x-offset of the addition bar for a file.
|
||||
*
|
||||
* @param {Object} file
|
||||
* @param {Gerrit.LayoutStats} stats
|
||||
* @return {number}
|
||||
@@ -1237,6 +1249,7 @@
|
||||
|
||||
/**
|
||||
* Get the width of the deletion bar for a file.
|
||||
*
|
||||
* @param {Object} file
|
||||
* @param {Gerrit.LayoutStats} stats
|
||||
* @return {number}
|
||||
@@ -1254,7 +1267,9 @@
|
||||
|
||||
/**
|
||||
* Get the x-offset of the deletion bar for a file.
|
||||
*
|
||||
* @param {Gerrit.LayoutStats} stats
|
||||
*
|
||||
* @return {number}
|
||||
*/
|
||||
_computeBarDeletionX(stats) {
|
||||
@@ -1290,6 +1305,7 @@
|
||||
|
||||
/**
|
||||
* Returns true if none of the inline diffs have been expanded.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
_noDiffsExpanded() {
|
||||
@@ -1300,6 +1316,7 @@
|
||||
* Method to call via binding when each file list row is rendered. This
|
||||
* allows approximate detection of when the dom-repeat has completed
|
||||
* rendering.
|
||||
*
|
||||
* @param {number} index The index of the row being rendered.
|
||||
* @return {string} an empty string.
|
||||
*/
|
||||
|
||||
@@ -440,10 +440,10 @@ limitations under the License.
|
||||
'/COMMIT_MSG', 'comment'), '3 comments (1 unresolved)');
|
||||
assert.equal(
|
||||
element._computeCommentsStringMobile(element.changeComments, parentTo1
|
||||
, '/COMMIT_MSG'), '2c');
|
||||
, '/COMMIT_MSG'), '2c');
|
||||
assert.equal(
|
||||
element._computeCommentsStringMobile(element.changeComments, _1To2
|
||||
, '/COMMIT_MSG'), '3c');
|
||||
, '/COMMIT_MSG'), '3c');
|
||||
assert.equal(
|
||||
element._computeDraftsString(element.changeComments, parentTo1,
|
||||
'unresolved.file'), '1 draft');
|
||||
@@ -639,7 +639,7 @@ limitations under the License.
|
||||
|
||||
assert(navStub.lastCall.calledWith(element.change,
|
||||
'file_added_in_rev2.txt', '2'),
|
||||
'Should navigate to /c/42/2/file_added_in_rev2.txt');
|
||||
'Should navigate to /c/42/2/file_added_in_rev2.txt');
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75, null, 'k');
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 75, null, 'k');
|
||||
@@ -1639,7 +1639,7 @@ limitations under the License.
|
||||
|
||||
element.set('_filesByPath', _filesByPath);
|
||||
flushAsynchronousOperations();
|
||||
// Navigates when a file is selected.
|
||||
// Navigates when a file is selected.
|
||||
element._openSelectedFile();
|
||||
assert.isTrue(navStub.called);
|
||||
});
|
||||
@@ -1701,7 +1701,7 @@ limitations under the License.
|
||||
const editControls =
|
||||
Array.from(
|
||||
Polymer.dom(element.root)
|
||||
.querySelectorAll('.row:not(.header-row)'))
|
||||
.querySelectorAll('.row:not(.header-row)'))
|
||||
.map(row => row.querySelector('gr-edit-file-controls'));
|
||||
assert.isTrue(editControls[0].classList.contains('invisible'));
|
||||
});
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
if (!labels[label.name]) { return null; }
|
||||
const labelValue = this._getLabelValue(labels, permittedLabels, label);
|
||||
const len = permittedLabels[label.name] != null ?
|
||||
permittedLabels[label.name].length : 0;
|
||||
permittedLabels[label.name].length : 0;
|
||||
for (let i = 0; i < len; i++) {
|
||||
const val = permittedLabels[label.name][i];
|
||||
if (val === labelValue) {
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
_computeHiddenClass(permittedLabels, label) {
|
||||
return !this._computeAnyPermittedLabelValues(permittedLabels, label) ?
|
||||
'hidden' : '';
|
||||
'hidden' : '';
|
||||
},
|
||||
|
||||
_computePermittedLabelValues(permittedLabels, label) {
|
||||
|
||||
@@ -123,7 +123,7 @@ limitations under the License.
|
||||
const labelName = 'Code-Review';
|
||||
assert.strictEqual(element._getVoteForAccount(
|
||||
element.change.labels, labelName, element.account),
|
||||
'+1');
|
||||
'+1');
|
||||
});
|
||||
|
||||
test('_computeColumns', () => {
|
||||
@@ -187,10 +187,10 @@ limitations under the License.
|
||||
{name: 'Verified', value: null}
|
||||
]);
|
||||
element.set(['change', 'labels', 'Verified', 'all'],
|
||||
[{_account_id: 123, value: 1}]);
|
||||
[{_account_id: 123, value: 1}]);
|
||||
assert.deepEqual(element._labels, [
|
||||
{name: 'Code-Review', value: null},
|
||||
{name: 'Verified', value: '+1'},
|
||||
{name: 'Code-Review', value: null},
|
||||
{name: 'Verified', value: '+1'},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
el.set('message.expanded', true);
|
||||
let top = el.offsetTop;
|
||||
for (let offsetParent = el.offsetParent;
|
||||
offsetParent;
|
||||
offsetParent = offsetParent.offsetParent) {
|
||||
offsetParent;
|
||||
offsetParent = offsetParent.offsetParent) {
|
||||
top += offsetParent.offsetTop;
|
||||
}
|
||||
window.scrollTo(0, top);
|
||||
@@ -219,6 +219,7 @@
|
||||
* Computes message author's file comments for change's message.
|
||||
* Method uses this.messages to find next message and relies on messages
|
||||
* to be sorted by date field descending.
|
||||
*
|
||||
* @param {!Object} changeComments changeComment object, which includes
|
||||
* a method to get all published comments (including robot comments),
|
||||
* which returns a Hash of arrays of comments, filename as key.
|
||||
|
||||
@@ -158,6 +158,7 @@
|
||||
* Determines whether or not the given change has a parent change. If there
|
||||
* is a relation chain, and the change id is not the last item of the
|
||||
* relation chain, there is a parent.
|
||||
*
|
||||
* @param {number} currentChangeId
|
||||
* @param {!Array} relatedChanges
|
||||
* @return {boolean}
|
||||
@@ -219,6 +220,7 @@
|
||||
/**
|
||||
* Do the given objects describe the same change? Compares the changes by
|
||||
* their numbers.
|
||||
*
|
||||
* @see /Documentation/rest-api-changes.html#change-info
|
||||
* @see /Documentation/rest-api-changes.html#related-change-and-commit-info
|
||||
* @param {!Object} a Either ChangeInfo or RelatedChangeAndCommitInfo
|
||||
@@ -236,6 +238,7 @@
|
||||
* SubmittedTogetherInfo responses) or get the change number from a
|
||||
* RelatedChangeAndCommitInfo (such as those included in a
|
||||
* RelatedChangesInfo response).
|
||||
*
|
||||
* @see /Documentation/rest-api-changes.html#change-info
|
||||
* @see /Documentation/rest-api-changes.html#related-change-and-commit-info
|
||||
*
|
||||
@@ -368,7 +371,7 @@
|
||||
|
||||
_computeSubmittedTogetherClass(submittedTogether) {
|
||||
if (!submittedTogether || (
|
||||
submittedTogether.changes.length === 0 &&
|
||||
submittedTogether.changes.length === 0 &&
|
||||
!submittedTogether.non_visible_changes)) {
|
||||
return 'hidden';
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ limitations under the License.
|
||||
sandbox.stub(element, '_getCherryPicks')
|
||||
.returns(Promise.resolve());
|
||||
conflictsStub = sandbox.stub(element, '_getConflicts')
|
||||
.returns(Promise.resolve());
|
||||
.returns(Promise.resolve());
|
||||
});
|
||||
|
||||
test('request conflicts if open and mergeable', () => {
|
||||
|
||||
@@ -87,11 +87,11 @@
|
||||
* @event comment-refresh
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fires when the state of the send button (enabled/disabled) changes.
|
||||
*
|
||||
* @event send-disabled-changed
|
||||
*/
|
||||
/**
|
||||
* Fires when the state of the send button (enabled/disabled) changes.
|
||||
*
|
||||
* @event send-disabled-changed
|
||||
*/
|
||||
|
||||
properties: {
|
||||
/**
|
||||
@@ -249,7 +249,7 @@
|
||||
this.fetchChangeUpdates(this.change, this.$.restAPI)
|
||||
.then(result => {
|
||||
this.knownLatestState = result.isLatest ?
|
||||
LatestPatchState.LATEST : LatestPatchState.NOT_LATEST;
|
||||
LatestPatchState.LATEST : LatestPatchState.NOT_LATEST;
|
||||
});
|
||||
|
||||
this._focusOn(opt_focusTarget);
|
||||
@@ -394,16 +394,16 @@
|
||||
|
||||
return this.$.restAPI.removeChangeReviewer(this.change._number,
|
||||
account._account_id).then(response => {
|
||||
if (!response.ok) { return response; }
|
||||
if (!response.ok) { return response; }
|
||||
|
||||
const reviewers = this.change.reviewers[type] || [];
|
||||
for (let i = 0; i < reviewers.length; i++) {
|
||||
if (reviewers[i]._account_id == account._account_id) {
|
||||
this.splice(`change.reviewers.${type}`, i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
const reviewers = this.change.reviewers[type] || [];
|
||||
for (let i = 0; i < reviewers.length; i++) {
|
||||
if (reviewers[i]._account_id == account._account_id) {
|
||||
this.splice(`change.reviewers.${type}`, i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_mapReviewer(reviewer) {
|
||||
@@ -624,6 +624,7 @@
|
||||
* Generates a function to filter out reviewer/CC entries. When isCCs is
|
||||
* truthy, the function filters out entries that already exist in this._ccs.
|
||||
* When falsy, the function filters entries that exist in this._reviewers.
|
||||
*
|
||||
* @param {boolean} isCCs
|
||||
* @return {!Function}
|
||||
*/
|
||||
|
||||
@@ -414,8 +414,8 @@ limitations under the License.
|
||||
}).then(() => {
|
||||
assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));
|
||||
const additions = cc ?
|
||||
element.$.ccs.additions() :
|
||||
element.$.reviewers.additions();
|
||||
element.$.ccs.additions() :
|
||||
element.$.reviewers.additions();
|
||||
assert.deepEqual(
|
||||
additions,
|
||||
[
|
||||
@@ -843,7 +843,7 @@ limitations under the License.
|
||||
// Send and purge and verify moves, delete cc3.
|
||||
element.send()
|
||||
.then(keepReviewers =>
|
||||
element._purgeReviewersPendingRemove(false, keepReviewers))
|
||||
element._purgeReviewersPendingRemove(false, keepReviewers))
|
||||
.then(() => {
|
||||
assert.deepEqual(
|
||||
mutations, [
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
|
||||
/**
|
||||
* Returns hash of labels to max permitted score.
|
||||
*
|
||||
* @param {!Object} change
|
||||
* @returns {!Object} labels to max permitted scores hash
|
||||
*/
|
||||
@@ -119,6 +120,7 @@
|
||||
|
||||
/**
|
||||
* Returns max permitted score for reviewer.
|
||||
*
|
||||
* @param {!Object} reviewer
|
||||
* @param {!Object} change
|
||||
* @param {string} label
|
||||
|
||||
@@ -196,7 +196,7 @@ limitations under the License.
|
||||
element.maxReviewersDisplayed = 5;
|
||||
for (let i = 0; i < 6; i++) {
|
||||
reviewers.push(
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
}
|
||||
element.ccsOnly = true;
|
||||
|
||||
@@ -219,7 +219,7 @@ limitations under the License.
|
||||
element.maxReviewersDisplayed = 5;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
reviewers.push(
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
}
|
||||
element.ccsOnly = true;
|
||||
|
||||
@@ -242,7 +242,7 @@ limitations under the License.
|
||||
const reviewers = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
reviewers.push(
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
}
|
||||
element.ccsOnly = true;
|
||||
|
||||
@@ -265,7 +265,7 @@ limitations under the License.
|
||||
element.maxReviewersDisplayed = 5;
|
||||
for (let i = 0; i < 100; i++) {
|
||||
reviewers.push(
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
{email: i+'reviewer@google.com', name: 'reviewer-' + i});
|
||||
}
|
||||
element.ccsOnly = true;
|
||||
|
||||
@@ -298,7 +298,7 @@ limitations under the License.
|
||||
},
|
||||
Bar: {
|
||||
all: [{_account_id: 1, permitted_voting_range: {max: 1}},
|
||||
{_account_id: 7, permitted_voting_range: {max: 1}}],
|
||||
{_account_id: 7, permitted_voting_range: {max: 1}}],
|
||||
},
|
||||
FooBar: {
|
||||
all: [{_account_id: 7, value: 0}],
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
* - Unresolved threads without drafts (reverse chronological)
|
||||
* - Resolved threads with drafts (reverse chronological)
|
||||
* - Resolved threads without drafts (reverse chronological)
|
||||
*
|
||||
* @param {!Object} changeRecord
|
||||
*/
|
||||
_computeSortedThreads(changeRecord) {
|
||||
@@ -132,8 +133,8 @@
|
||||
|
||||
const lastNonDraftComment =
|
||||
(lastComment.__draft && thread.comments.length > 1) ?
|
||||
thread.comments[thread.comments.length - 2] :
|
||||
lastComment;
|
||||
thread.comments[thread.comments.length - 2] :
|
||||
lastComment;
|
||||
|
||||
return {
|
||||
thread,
|
||||
|
||||
@@ -78,7 +78,7 @@ limitations under the License.
|
||||
'none');
|
||||
assert.notEqual(getComputedStyle(element.$$('gr-account-dropdown'))
|
||||
.display,
|
||||
'none');
|
||||
'none');
|
||||
assert.notEqual(getComputedStyle(element.$$('.settingsButton')).display,
|
||||
'none');
|
||||
});
|
||||
|
||||
@@ -224,6 +224,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Setup router implementation.
|
||||
*
|
||||
* @param {function(!string)} navigate the router-abstracted equivalent of
|
||||
* `window.location.href = ...`. Takes a string.
|
||||
* @param {function(!Object): string} generateUrl generates a URL given
|
||||
@@ -260,6 +261,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Generate a URL for the given route parameters.
|
||||
*
|
||||
* @param {Object} params
|
||||
* @return {string}
|
||||
*/
|
||||
@@ -336,6 +338,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Navigate to a search for changes with the given status.
|
||||
*
|
||||
* @param {string} status
|
||||
*/
|
||||
navigateToStatusSearch(status) {
|
||||
@@ -347,6 +350,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Navigate to a search query
|
||||
*
|
||||
* @param {string} query
|
||||
* @param {number=} opt_offset
|
||||
*/
|
||||
@@ -548,6 +552,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Navigate to an arbitrary relative URL.
|
||||
*
|
||||
* @param {string} relativeUrl
|
||||
*/
|
||||
navigateToRelativeUrl(relativeUrl) {
|
||||
@@ -570,6 +575,7 @@ limitations under the License.
|
||||
|
||||
/**
|
||||
* Navigate to a repo settings page.
|
||||
*
|
||||
* @param {string} repoName
|
||||
*/
|
||||
navigateToRepo(repoName) {
|
||||
@@ -732,11 +738,11 @@ limitations under the License.
|
||||
getUserDashboard(user = 'self', sections = DEFAULT_SECTIONS,
|
||||
title = '') {
|
||||
sections = sections
|
||||
.filter(section => (user === 'self' || !section.selfOnly))
|
||||
.map(section => Object.assign({}, section, {
|
||||
name: section.name,
|
||||
query: section.query.replace(USER_PLACEHOLDER_PATTERN, user),
|
||||
}));
|
||||
.filter(section => (user === 'self' || !section.selfOnly))
|
||||
.map(section => Object.assign({}, section, {
|
||||
name: section.name,
|
||||
query: section.query.replace(USER_PLACEHOLDER_PATTERN, user),
|
||||
}));
|
||||
return {title, sections};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -194,6 +194,7 @@
|
||||
|
||||
/**
|
||||
* The default reporter reports events immediately.
|
||||
*
|
||||
* @param {string} type
|
||||
* @param {string} category
|
||||
* @param {string} eventName
|
||||
@@ -231,6 +232,7 @@
|
||||
/**
|
||||
* The caching reporter will queue reports until plugins have loaded, and
|
||||
* log events immediately if they're reported after plugins have loaded.
|
||||
*
|
||||
* @param {string} type
|
||||
* @param {string} category
|
||||
* @param {string} eventName
|
||||
@@ -406,6 +408,7 @@
|
||||
/**
|
||||
* Reports just line timeEnd, but additionally reports an average given a
|
||||
* denominator and a separate reporiting name for the average.
|
||||
*
|
||||
* @param {string} name Timing name.
|
||||
* @param {string} averageName Average timing name.
|
||||
* @param {number} denominator Number by which to divide the total to
|
||||
@@ -424,6 +427,7 @@
|
||||
|
||||
/**
|
||||
* Send a timing report with an arbitrary time value.
|
||||
*
|
||||
* @param {string} name Timing name.
|
||||
* @param {number} time The time to report as an integer of milliseconds.
|
||||
*/
|
||||
@@ -436,6 +440,7 @@
|
||||
* Get a timer object to for reporing a user timing. The start time will be
|
||||
* the time that the object has been created, and the end time will be the
|
||||
* time that the "end" method is called on the object.
|
||||
*
|
||||
* @param {string} name Timing name.
|
||||
* @returns {!Object} The timer object.
|
||||
*/
|
||||
@@ -482,6 +487,7 @@
|
||||
|
||||
/**
|
||||
* Log timing information for an RPC.
|
||||
*
|
||||
* @param {string} anonymizedUrl The URL of the RPC with tokens obfuscated.
|
||||
* @param {number} elapsed The time elapsed of the RPC.
|
||||
*/
|
||||
|
||||
@@ -68,11 +68,11 @@ limitations under the License.
|
||||
assert.isTrue(
|
||||
element.reporter.calledWithExactly(
|
||||
'timing-report', 'UI Latency', 'App Started', 42
|
||||
));
|
||||
));
|
||||
assert.isTrue(
|
||||
element.reporter.calledWithExactly(
|
||||
'lifecycle', 'Page Visibility', 'hidden'
|
||||
));
|
||||
));
|
||||
});
|
||||
|
||||
test('WebComponentsReady', () => {
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
|
||||
/**
|
||||
* Support vestigial params from GWT UI.
|
||||
*
|
||||
* @see Issue 7673.
|
||||
* @type {!RegExp}
|
||||
*/
|
||||
@@ -162,6 +163,7 @@
|
||||
* the hash of diff URLs. In this format, a number on its own indicates that
|
||||
* line number in the revision of the diff. A number prefixed by either an 'a'
|
||||
* or a 'b' indicates that line number of the base of the diff.
|
||||
*
|
||||
* @type {RegExp}
|
||||
*/
|
||||
const LINE_ADDRESS_PATTERN = /^([ab]?)(\d+)$/;
|
||||
@@ -461,8 +463,8 @@
|
||||
// If there is a repo name provided, make sure to substitute it into the
|
||||
// ${repo} (or legacy ${project}) query tokens.
|
||||
const query = opt_repoName ?
|
||||
section.query.replace(REPO_TOKEN_PATTERN, opt_repoName) :
|
||||
section.query;
|
||||
section.query.replace(REPO_TOKEN_PATTERN, opt_repoName) :
|
||||
section.query;
|
||||
return encodeURIComponent(section.name) + '=' +
|
||||
encodeURIComponent(query);
|
||||
});
|
||||
@@ -540,6 +542,7 @@
|
||||
* Given an object of parameters, potentially including a `patchNum` or a
|
||||
* `basePatchNum` or both, return a string representation of that range. If
|
||||
* no range is indicated in the params, the empty string is returned.
|
||||
*
|
||||
* @param {!Object} params
|
||||
* @return {string}
|
||||
*/
|
||||
@@ -606,6 +609,7 @@
|
||||
/**
|
||||
* Redirect the user to login using the given return-URL for redirection
|
||||
* after authentication success.
|
||||
*
|
||||
* @param {string} returnUrl
|
||||
*/
|
||||
_redirectToLogin(returnUrl) {
|
||||
@@ -618,6 +622,7 @@
|
||||
* Hashes parsed by page.js exclude "inner" hashes, so a URL like "/a#b#c"
|
||||
* is parsed to have a hash of "b" rather than "b#c". Instead, this method
|
||||
* parses hashes correctly. Will return an empty string if there is no hash.
|
||||
*
|
||||
* @param {!string} canonicalPath
|
||||
* @return {!string} Everything after the first '#' ("a#b#c" -> "b#c").
|
||||
*/
|
||||
@@ -638,6 +643,7 @@
|
||||
* Check to see if the user is logged in and return a promise that only
|
||||
* resolves if the user is logged in. If the user us not logged in, the
|
||||
* promise is rejected and the page is redirected to the login flow.
|
||||
*
|
||||
* @param {!Object} data The parsed route data.
|
||||
* @return {!Promise<!Object>} A promise yielding the original route data
|
||||
* (if it resolves).
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
/**
|
||||
* Determine what array of possible suggestions should be provided
|
||||
* to _getSearchSuggestions.
|
||||
*
|
||||
* @param {string} input - The full search term, in lowercase.
|
||||
* @return {!Promise} This returns a promise that resolves to an array of
|
||||
* suggestion objects.
|
||||
@@ -250,6 +251,7 @@
|
||||
|
||||
/**
|
||||
* Get the sorted, pruned list of suggestions for the current search query.
|
||||
*
|
||||
* @param {string} input - The complete search query.
|
||||
* @return {!Promise} This returns a promise that resolves to an array of
|
||||
* suggestions.
|
||||
|
||||
@@ -61,8 +61,8 @@ limitations under the License.
|
||||
|
||||
getActiveElement = () => {
|
||||
return document.activeElement.shadowRoot ?
|
||||
document.activeElement.shadowRoot.activeElement :
|
||||
document.activeElement;
|
||||
document.activeElement.shadowRoot.activeElement :
|
||||
document.activeElement;
|
||||
};
|
||||
|
||||
test('enter in search input fires event', done => {
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
|
||||
/**
|
||||
* Fetch from the API the predicted projects.
|
||||
*
|
||||
* @param {string} predicate - The first part of the search term, e.g.
|
||||
* 'project'
|
||||
* @param {string} expression - The second part of the search term, e.g.
|
||||
@@ -90,6 +91,7 @@
|
||||
|
||||
/**
|
||||
* Fetch from the API the predicted groups.
|
||||
*
|
||||
* @param {string} predicate - The first part of the search term, e.g.
|
||||
* 'ownerin'
|
||||
* @param {string} expression - The second part of the search term, e.g.
|
||||
@@ -111,6 +113,7 @@
|
||||
|
||||
/**
|
||||
* Fetch from the API the predicted accounts.
|
||||
*
|
||||
* @param {string} predicate - The first part of the search term, e.g.
|
||||
* 'owner'
|
||||
* @param {string} expression - The second part of the search term, e.g.
|
||||
@@ -144,8 +147,8 @@
|
||||
return accounts.map(account => ({
|
||||
label: account.name || '',
|
||||
text: account.email ?
|
||||
`${predicate}:${account.email}` :
|
||||
`${predicate}:"${this._accountOrAnon(account)}"`,
|
||||
`${predicate}:${account.email}` :
|
||||
`${predicate}:"${this._accountOrAnon(account)}"`,
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -248,9 +248,9 @@
|
||||
const all = comments.concat(drafts).concat(robotComments);
|
||||
|
||||
const baseComments = all.filter(c =>
|
||||
this._isInBaseOfPatchRange(c, patchRange));
|
||||
this._isInBaseOfPatchRange(c, patchRange));
|
||||
const revisionComments = all.filter(c =>
|
||||
this._isInRevisionOfPatchRange(c, patchRange));
|
||||
this._isInRevisionOfPatchRange(c, patchRange));
|
||||
|
||||
return {
|
||||
meta: {
|
||||
@@ -348,7 +348,7 @@
|
||||
const threads = this.getCommentThreads(this._sortComments(comments));
|
||||
|
||||
const unresolvedThreads = threads
|
||||
.filter(thread =>
|
||||
.filter(thread =>
|
||||
thread.comments.length &&
|
||||
thread.comments[thread.comments.length - 1].unresolved);
|
||||
|
||||
@@ -406,12 +406,13 @@
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether the given comment should be included in the base side of the
|
||||
* given patch range.
|
||||
* @param {!Object} comment
|
||||
* @param {!Gerrit.PatchRange} range
|
||||
* @return {boolean}
|
||||
*/
|
||||
* Whether the given comment should be included in the base side of the
|
||||
* given patch range.
|
||||
*
|
||||
* @param {!Object} comment
|
||||
* @param {!Gerrit.PatchRange} range
|
||||
* @return {boolean}
|
||||
*/
|
||||
ChangeComments.prototype._isInBaseOfPatchRange = function(comment, range) {
|
||||
// If the base of the patch range is a parent of a merge, and the comment
|
||||
// appears on a specific parent then only show the comment if the parent
|
||||
@@ -439,6 +440,7 @@
|
||||
/**
|
||||
* Whether the given comment should be included in the revision side of the
|
||||
* given patch range.
|
||||
*
|
||||
* @param {!Object} comment
|
||||
* @param {!Gerrit.PatchRange} range
|
||||
* @return {boolean}
|
||||
@@ -451,6 +453,7 @@
|
||||
|
||||
/**
|
||||
* Whether the given comment should be included in the given patch range.
|
||||
*
|
||||
* @param {!Object} comment
|
||||
* @param {!Gerrit.PatchRange} range
|
||||
* @return {boolean|undefined}
|
||||
@@ -491,7 +494,7 @@
|
||||
|
||||
return Promise.all(promises).then(([comments, robotComments, drafts]) => {
|
||||
this._changeComments = new ChangeComments(comments,
|
||||
robotComments, drafts, changeNum);
|
||||
robotComments, drafts, changeNum);
|
||||
return this._changeComments;
|
||||
});
|
||||
},
|
||||
|
||||
@@ -109,7 +109,7 @@ limitations under the License.
|
||||
let draftStub;
|
||||
setup(() => {
|
||||
commentStub = sandbox.stub(element.$.restAPI, 'getDiffComments')
|
||||
.returns(Promise.resolve({}));
|
||||
.returns(Promise.resolve({}));
|
||||
robotCommentStub = sandbox.stub(element.$.restAPI,
|
||||
'getDiffRobotComments').returns(Promise.resolve({}));
|
||||
draftStub = sandbox.stub(element.$.restAPI, 'getDiffDrafts')
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
let tr = content.parentElement.parentElement;
|
||||
while (tr = tr.nextSibling) {
|
||||
if (tr.classList.contains('both') || (
|
||||
(side === 'left' && tr.classList.contains('remove')) ||
|
||||
(side === 'left' && tr.classList.contains('remove')) ||
|
||||
(side === 'right' && tr.classList.contains('add')))) {
|
||||
return tr.querySelector('.contentText');
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ limitations under the License.
|
||||
* The promise last returned from `render()` while the asynchronous
|
||||
* rendering is running - `null` otherwise. Provides a `cancel()`
|
||||
* method that rejects it with `{isCancelled: true}`.
|
||||
*
|
||||
* @type {?Object}
|
||||
*/
|
||||
_cancelableRenderPromise: Object,
|
||||
@@ -219,8 +220,8 @@ limitations under the License.
|
||||
getLineNumberByChild(node) {
|
||||
const lineEl = this.getLineElByChild(node);
|
||||
return lineEl ?
|
||||
parseInt(lineEl.getAttribute('data-value'), 10) :
|
||||
null;
|
||||
parseInt(lineEl.getAttribute('data-value'), 10) :
|
||||
null;
|
||||
},
|
||||
|
||||
getContentByLine(lineNumber, opt_side, opt_root) {
|
||||
@@ -249,7 +250,7 @@ limitations under the License.
|
||||
|
||||
getSideByLineEl(lineEl) {
|
||||
return lineEl.classList.contains(GrDiffBuilder.Side.RIGHT) ?
|
||||
GrDiffBuilder.Side.RIGHT : GrDiffBuilder.Side.LEFT;
|
||||
GrDiffBuilder.Side.RIGHT : GrDiffBuilder.Side.LEFT;
|
||||
},
|
||||
|
||||
emitGroup(group, sectionEl) {
|
||||
@@ -304,7 +305,7 @@ limitations under the License.
|
||||
let builder = null;
|
||||
if (this.isImageDiff) {
|
||||
builder = new GrDiffBuilderImage(diff, prefs, this.diffElement,
|
||||
this.baseImage, this.revisionImage);
|
||||
this.baseImage, this.revisionImage);
|
||||
} else if (diff.binary) {
|
||||
// If the diff is binary, but not an image.
|
||||
return new GrDiffBuilderBinary(diff, prefs, this.diffElement);
|
||||
@@ -352,8 +353,8 @@ limitations under the License.
|
||||
|
||||
// If endIndex isn't present, continue to the end of the line.
|
||||
const endIndex = highlight.endIndex === undefined ?
|
||||
line.text.length :
|
||||
highlight.endIndex;
|
||||
line.text.length :
|
||||
highlight.endIndex;
|
||||
|
||||
GrAnnotation.annotateElement(
|
||||
contentEl,
|
||||
|
||||
@@ -92,6 +92,7 @@
|
||||
|
||||
/**
|
||||
* Abstract method
|
||||
*
|
||||
* @param {string} outputEl
|
||||
* @param {number} fontSize
|
||||
*/
|
||||
@@ -101,6 +102,7 @@
|
||||
|
||||
/**
|
||||
* Abstract method
|
||||
*
|
||||
* @param {Object} group
|
||||
*/
|
||||
GrDiffBuilder.prototype.buildSectionElement = function() {
|
||||
@@ -183,7 +185,7 @@
|
||||
continue;
|
||||
}
|
||||
const lineNumber = opt_side === 'left' ?
|
||||
line.beforeNumber : line.afterNumber;
|
||||
line.beforeNumber : line.afterNumber;
|
||||
if (lineNumber < start || lineNumber > end) { continue; }
|
||||
|
||||
if (out_lines) { out_lines.push(line); }
|
||||
@@ -462,6 +464,7 @@
|
||||
/**
|
||||
* Finds the next DIV.contentText element following the given element, and on
|
||||
* the same side. Will only search within a group.
|
||||
*
|
||||
* @param {HTMLElement} content
|
||||
* @param {string} side Either 'left' or 'right'
|
||||
* @return {HTMLElement}
|
||||
@@ -473,6 +476,7 @@
|
||||
/**
|
||||
* Determines whether the given group is either totally an addition or totally
|
||||
* a removal.
|
||||
*
|
||||
* @param {!Object} group (GrDiffGroup)
|
||||
* @return {boolean}
|
||||
*/
|
||||
@@ -485,6 +489,7 @@
|
||||
/**
|
||||
* Set the blame information for the diff. For any already-rendered line,
|
||||
* re-render its blame cell content.
|
||||
*
|
||||
* @param {Object} blame
|
||||
*/
|
||||
GrDiffBuilder.prototype.setBlame = function(blame) {
|
||||
@@ -512,6 +517,7 @@
|
||||
|
||||
/**
|
||||
* Find the blame cell for a given line number.
|
||||
*
|
||||
* @param {number} lineNum
|
||||
* @return {HTMLTableDataCellElement}
|
||||
*/
|
||||
@@ -524,6 +530,7 @@
|
||||
* Given a base line number, return the commit containing that line in the
|
||||
* current set of blame information. If no blame information has been
|
||||
* provided, null is returned.
|
||||
*
|
||||
* @param {number} lineNum
|
||||
* @return {Object} The commit information.
|
||||
*/
|
||||
@@ -543,6 +550,7 @@
|
||||
/**
|
||||
* Given the number of a base line, get the content for the blame cell of that
|
||||
* line. If there is no blame information for that line, returns null.
|
||||
*
|
||||
* @param {number} lineNum
|
||||
* @param {Object=} opt_commit Optionally provide the commit object, so that
|
||||
* it does not need to be searched.
|
||||
@@ -567,6 +575,7 @@
|
||||
/**
|
||||
* Create a blame cell for the given base line. Blame information will be
|
||||
* included in the cell if available.
|
||||
*
|
||||
* @param {GrDiffLine} line
|
||||
* @return {HTMLTableDataCellElement}
|
||||
*/
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
* to that position. This parameter should be set at most for one gr-diff
|
||||
* element in the page.
|
||||
*
|
||||
* @type (?number)
|
||||
* @type {?number}
|
||||
*/
|
||||
initialLineNumber: {
|
||||
type: Number,
|
||||
@@ -176,6 +176,7 @@
|
||||
|
||||
/**
|
||||
* Get the line number element targeted by the cursor row and side.
|
||||
*
|
||||
* @return {?Element|undefined}
|
||||
*/
|
||||
getTargetLineElement() {
|
||||
@@ -251,6 +252,7 @@
|
||||
* {leftSide: false, number: 123} for line 123 of the revision, or
|
||||
* {leftSide: true, number: 321} for line 321 of the base patch.
|
||||
* Returns null if an address is not available.
|
||||
*
|
||||
* @return {?Object}
|
||||
*/
|
||||
getAddress() {
|
||||
@@ -315,7 +317,7 @@
|
||||
if (this._getViewMode() === DiffViewMode.SIDE_BY_SIDE &&
|
||||
this._isTargetBlank()) {
|
||||
this.side = this.side === DiffSides.LEFT ?
|
||||
DiffSides.RIGHT : DiffSides.LEFT;
|
||||
DiffSides.RIGHT : DiffSides.LEFT;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -375,6 +377,7 @@
|
||||
/**
|
||||
* Setup and tear down on-render listeners for any diffs that are added or
|
||||
* removed from the cursor.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_diffsChanged(changeRecord) {
|
||||
@@ -391,15 +394,15 @@
|
||||
splice = changeRecord.indexSplices[spliceIdx];
|
||||
|
||||
for (i = splice.index;
|
||||
i < splice.index + splice.addedCount;
|
||||
i++) {
|
||||
i < splice.index + splice.addedCount;
|
||||
i++) {
|
||||
this.listen(this.diffs[i], 'render-start', '_handleDiffRenderStart');
|
||||
this.listen(this.diffs[i], 'render-content', 'handleDiffUpdate');
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
i < splice.removed && splice.removed.length;
|
||||
i++) {
|
||||
i < splice.removed && splice.removed.length;
|
||||
i++) {
|
||||
this.unlisten(splice.removed[i],
|
||||
'render-start', '_handleDiffRenderStart');
|
||||
this.unlisten(splice.removed[i],
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
/**
|
||||
* The DOM API textContent.length calculation is broken when the text
|
||||
* contains Unicode. See https://mathiasbynens.be/notes/javascript-unicode .
|
||||
*
|
||||
* @param {!Text} node text node.
|
||||
* @return {number} The length of the text.
|
||||
*/
|
||||
|
||||
@@ -168,7 +168,7 @@ limitations under the License.
|
||||
assert.equal(layer4[0].textContent +
|
||||
layer4[1].textContent +
|
||||
layer4[2].textContent,
|
||||
layers[3]);
|
||||
layers[3]);
|
||||
});
|
||||
|
||||
test('splitTextNode', () => {
|
||||
|
||||
@@ -137,7 +137,7 @@
|
||||
}
|
||||
|
||||
return this.commentRanges.findIndex(commentRange =>
|
||||
commentRange.side === side && rangesEqual(commentRange.range, range));
|
||||
commentRange.side === side && rangesEqual(commentRange.range, range));
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -145,6 +145,7 @@
|
||||
* Merges multiple ranges, accounts for triple click, accounts for
|
||||
* syntax highligh, convert native DOM Range objects to Gerrit concepts
|
||||
* (line, side, etc).
|
||||
*
|
||||
* @param {Selection} selection
|
||||
* @return {({
|
||||
* start: {
|
||||
@@ -180,6 +181,7 @@
|
||||
|
||||
/**
|
||||
* Normalize a specific DOM Range.
|
||||
*
|
||||
* @return {!Object} fixed normalized range
|
||||
*/
|
||||
_normalizeRange(domRange) {
|
||||
|
||||
@@ -272,12 +272,12 @@ limitations under the License.
|
||||
};
|
||||
|
||||
const getActionRange = () =>
|
||||
Polymer.dom(element.root).querySelector(
|
||||
'gr-selection-action-box').range;
|
||||
Polymer.dom(element.root).querySelector(
|
||||
'gr-selection-action-box').range;
|
||||
|
||||
const getActionSide = () =>
|
||||
Polymer.dom(element.root).querySelector(
|
||||
'gr-selection-action-box').side;
|
||||
Polymer.dom(element.root).querySelector(
|
||||
'gr-selection-action-box').side;
|
||||
|
||||
const getLineElByChild = node => {
|
||||
const stubs = contentStubs.find(stub => stub.contentTd.contains(node));
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
/**
|
||||
* The DOM API textContent.length calculation is broken when the text
|
||||
* contains Unicode. See https://mathiasbynens.be/notes/javascript-unicode .
|
||||
*
|
||||
* @param {text} node A text node.
|
||||
* @return {number} The length of the text.
|
||||
*/
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
|
||||
/**
|
||||
* Fired when the user selects a line.
|
||||
*
|
||||
* @event line-selected
|
||||
*/
|
||||
|
||||
@@ -147,6 +148,7 @@
|
||||
|
||||
/**
|
||||
* Special line number which should not be collapsed into a shared region.
|
||||
*
|
||||
* @type {{
|
||||
* number: number,
|
||||
* leftSide: {boolean}
|
||||
@@ -395,6 +397,7 @@
|
||||
|
||||
/**
|
||||
* Load and display blame information for the base of the diff.
|
||||
*
|
||||
* @return {Promise} A promise that resolves when blame finishes rendering.
|
||||
*/
|
||||
loadBlame() {
|
||||
@@ -417,6 +420,7 @@
|
||||
|
||||
/**
|
||||
* The thread elements in this diff, in no particular order.
|
||||
*
|
||||
* @return {!Array<!HTMLElement>}
|
||||
*/
|
||||
getThreadEls() {
|
||||
@@ -511,7 +515,7 @@
|
||||
// digits. Diffs with no delta are considered 0%.
|
||||
const totalDelta = rebaseDelta + nonRebaseDelta;
|
||||
const percentRebaseDelta = !totalDelta ? 0 :
|
||||
Math.round(100 * rebaseDelta / totalDelta);
|
||||
Math.round(100 * rebaseDelta / totalDelta);
|
||||
|
||||
// Report the due_to_rebase percentage in the "diff" category when
|
||||
// applicable.
|
||||
@@ -588,7 +592,7 @@
|
||||
// thread and append to it.
|
||||
if (comment.in_reply_to) {
|
||||
const thread = threads.find(thread =>
|
||||
thread.comments.some(c => c.id === comment.in_reply_to));
|
||||
thread.comments.some(c => c.id === comment.in_reply_to));
|
||||
if (thread) {
|
||||
thread.comments.push(comment);
|
||||
continue;
|
||||
@@ -729,7 +733,7 @@
|
||||
}
|
||||
function matchesRange(threadEl) {
|
||||
const threadRange = /** @type {!Gerrit.Range} */(
|
||||
JSON.parse(threadEl.getAttribute('range')));
|
||||
JSON.parse(threadEl.getAttribute('range')));
|
||||
return Gerrit.rangesEqual(threadRange, range);
|
||||
}
|
||||
|
||||
@@ -780,7 +784,7 @@
|
||||
matchers.push(matchesFileComment);
|
||||
}
|
||||
return threadEls.filter(threadEl =>
|
||||
matchers.some(matcher => matcher(threadEl)));
|
||||
matchers.some(matcher => matcher(threadEl)));
|
||||
},
|
||||
|
||||
_getIgnoreWhitespace() {
|
||||
@@ -832,7 +836,7 @@
|
||||
*/
|
||||
_computeParentIndex(patchRangeRecord) {
|
||||
return this.isMergeParent(patchRangeRecord.base.basePatchNum) ?
|
||||
this.getParentIndex(patchRangeRecord.base.basePatchNum) : null;
|
||||
this.getParentIndex(patchRangeRecord.base.basePatchNum) : null;
|
||||
},
|
||||
|
||||
_handleCommentSave(e) {
|
||||
@@ -926,8 +930,8 @@
|
||||
if (!diff) return false;
|
||||
return diff.content.some(section => {
|
||||
const lines = section.ab ?
|
||||
section.ab :
|
||||
(section.a || []).concat(section.b || []);
|
||||
section.ab :
|
||||
(section.a || []).concat(section.b || []);
|
||||
return lines.some(line => line.length >= SYNTAX_MAX_LINE_LENGTH);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -509,7 +509,7 @@ limitations under the License.
|
||||
'getB64FileContents',
|
||||
(changeId, patchNum, path, opt_parentIndex) => {
|
||||
return Promise.resolve(opt_parentIndex === 1 ? mockFile1 :
|
||||
mockFile2);
|
||||
mockFile2);
|
||||
});
|
||||
|
||||
element.patchRange = {basePatchNum: 'PARENT', patchNum: 1};
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
* The promise last returned from `process()` while the asynchronous
|
||||
* processing is running - `null` otherwise. Provides a `cancel()`
|
||||
* method that rejects it with `{isCancelled: true}`.
|
||||
*
|
||||
* @type {?Object}
|
||||
*/
|
||||
_processPromise: {
|
||||
@@ -133,8 +134,10 @@
|
||||
/**
|
||||
* Asynchronously process the diff chunks into groups. As it processes, it
|
||||
* will splice groups into the `groups` property of the component.
|
||||
*
|
||||
* @param {!Array<!Gerrit.DiffChunk>} chunks
|
||||
* @param {boolean} isBinary
|
||||
*
|
||||
* @return {!Promise<!Array<!Object>>} A promise that resolves with an
|
||||
* array of GrDiffGroups when the diff is completely processed.
|
||||
*/
|
||||
@@ -290,7 +293,7 @@
|
||||
if (this.context !== WHOLE_FILE) {
|
||||
const hiddenStart = state.chunkIndex === 0 ? 0 : this.context;
|
||||
const hiddenEnd = lineCount - (
|
||||
firstUncollapsibleChunkIndex === chunks.length ?
|
||||
firstUncollapsibleChunkIndex === chunks.length ?
|
||||
0 : this.context);
|
||||
groups = GrDiffGroup.hideInContextControl(
|
||||
groups, hiddenStart, hiddenEnd);
|
||||
@@ -460,6 +463,7 @@
|
||||
* In order to show key locations, such as comments, out of the bounds of
|
||||
* the selected context, treat them as separate chunks within the model so
|
||||
* that the content (and context surrounding it) renders correctly.
|
||||
*
|
||||
* @param {!Array<!Object>} chunks DiffContents as returned from server.
|
||||
* @return {!Array<!Object>} Finer grained DiffContents.
|
||||
*/
|
||||
@@ -483,7 +487,7 @@
|
||||
|
||||
if (chunk.common && chunk.a.length != chunk.b.length) {
|
||||
throw new Error(
|
||||
'DiffContent with common=true must always have equal length');
|
||||
'DiffContent with common=true must always have equal length');
|
||||
}
|
||||
const numLines = this._commonChunkLength(chunk);
|
||||
const chunkEnds = this._findChunkEndsAtKeyLocations(
|
||||
@@ -494,7 +498,7 @@
|
||||
if (chunk.ab) {
|
||||
result.push(...this._splitAtChunkEnds(chunk.ab, chunkEnds)
|
||||
.map(({lines, keyLocation}) =>
|
||||
Object.assign({}, chunk, {ab: lines, keyLocation})));
|
||||
Object.assign({}, chunk, {ab: lines, keyLocation})));
|
||||
} else if (chunk.common) {
|
||||
const aChunks = this._splitAtChunkEnds(chunk.a, chunkEnds);
|
||||
const bChunks = this._splitAtChunkEnds(chunk.b, chunkEnds);
|
||||
@@ -603,6 +607,7 @@
|
||||
* If a group is an addition or a removal, break it down into smaller groups
|
||||
* of that type using the MAX_GROUP_SIZE. If the group is a shared chunk
|
||||
* or a delta it is returned as the single element of the result array.
|
||||
*
|
||||
* @param {!Gerrit.DiffChunk} chunk A raw chunk from a diff response.
|
||||
* @return {!Array<!Array<!Object>>}
|
||||
*/
|
||||
@@ -632,6 +637,7 @@
|
||||
/**
|
||||
* Given an array and a size, return an array of arrays where no inner array
|
||||
* is larger than that size, preserving the original order.
|
||||
*
|
||||
* @param {!Array<T>} array
|
||||
* @param {number} size
|
||||
* @return {!Array<!Array<T>>}
|
||||
|
||||
@@ -106,8 +106,8 @@
|
||||
const side = this.diffBuilder.getSideByLineEl(lineEl);
|
||||
|
||||
targetClasses.push(side === 'left' ?
|
||||
SelectionClass.LEFT :
|
||||
SelectionClass.RIGHT);
|
||||
SelectionClass.LEFT :
|
||||
SelectionClass.RIGHT);
|
||||
|
||||
if (commentSelected) {
|
||||
targetClasses.push(SelectionClass.COMMENT);
|
||||
@@ -120,6 +120,7 @@
|
||||
/**
|
||||
* Set the provided list of classes on the element, to the exclusion of all
|
||||
* other SelectionClass values.
|
||||
*
|
||||
* @param {!Array<!string>} targetClasses
|
||||
*/
|
||||
_setClasses(targetClasses) {
|
||||
|
||||
@@ -272,8 +272,8 @@
|
||||
const patchRange = patchRangeRecord.base;
|
||||
return this.$.restAPI.getChangeFilePathsAsSpeciallySortedArray(
|
||||
changeNum, patchRange).then(files => {
|
||||
this._fileList = files;
|
||||
});
|
||||
this._fileList = files;
|
||||
});
|
||||
},
|
||||
|
||||
_getDiffPreferences() {
|
||||
@@ -566,8 +566,8 @@
|
||||
let idx = fileList.indexOf(path);
|
||||
if (idx === -1) {
|
||||
const file = direction > 0 ?
|
||||
fileList[0] :
|
||||
fileList[fileList.length - 1];
|
||||
fileList[0] :
|
||||
fileList[fileList.length - 1];
|
||||
return {path: file};
|
||||
}
|
||||
|
||||
@@ -706,8 +706,8 @@
|
||||
// is specified.
|
||||
this._getReviewedStatus(this.editMode, this._changeNum,
|
||||
this._patchRange.patchNum, this._path).then(status => {
|
||||
this.$.reviewed.checked = status;
|
||||
});
|
||||
this.$.reviewed.checked = status;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1138,7 +1138,7 @@
|
||||
// so we resolve the right "next" file.
|
||||
const unreviewedFiles = this._fileList
|
||||
.filter(file =>
|
||||
(file === this._path || !this._reviewedFiles.has(file)));
|
||||
(file === this._path || !this._reviewedFiles.has(file)));
|
||||
this._navToFile(this._path, unreviewedFiles, 1);
|
||||
},
|
||||
|
||||
|
||||
@@ -269,28 +269,28 @@ limitations under the License.
|
||||
assert.isTrue(element._loading);
|
||||
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
||||
'wheatley.md', '10', '5'),
|
||||
'Should navigate to /c/42/5..10/wheatley.md');
|
||||
'Should navigate to /c/42/5..10/wheatley.md');
|
||||
element._path = 'wheatley.md';
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
||||
assert.isTrue(element._loading);
|
||||
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
||||
'glados.txt', '10', '5'),
|
||||
'Should navigate to /c/42/5..10/glados.txt');
|
||||
'Should navigate to /c/42/5..10/glados.txt');
|
||||
element._path = 'glados.txt';
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
||||
assert.isTrue(element._loading);
|
||||
assert(diffNavStub.lastCall.calledWithExactly(element._change, 'chell.go',
|
||||
'10', '5'),
|
||||
'Should navigate to /c/42/5..10/chell.go');
|
||||
'Should navigate to /c/42/5..10/chell.go');
|
||||
element._path = 'chell.go';
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
||||
assert.isTrue(element._loading);
|
||||
assert(changeNavStub.lastCall.calledWithExactly(element._change, '10',
|
||||
'5'),
|
||||
'Should navigate to /c/42/5..10');
|
||||
'Should navigate to /c/42/5..10');
|
||||
});
|
||||
|
||||
test('keyboard shortcuts with old patch number', () => {
|
||||
@@ -332,13 +332,13 @@ limitations under the License.
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 221, null, ']');
|
||||
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
||||
'wheatley.md', '1', PARENT),
|
||||
'Should navigate to /c/42/1/wheatley.md');
|
||||
'Should navigate to /c/42/1/wheatley.md');
|
||||
element._path = 'wheatley.md';
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
||||
assert(diffNavStub.lastCall.calledWithExactly(element._change,
|
||||
'glados.txt', '1', PARENT),
|
||||
'Should navigate to /c/42/1/glados.txt');
|
||||
'Should navigate to /c/42/1/glados.txt');
|
||||
element._path = 'glados.txt';
|
||||
|
||||
MockInteractions.pressAndReleaseKeyOn(element, 219, null, '[');
|
||||
|
||||
@@ -96,6 +96,7 @@
|
||||
|
||||
/**
|
||||
* Fired when the user selects a line.
|
||||
*
|
||||
* @event line-selected
|
||||
*/
|
||||
|
||||
@@ -169,7 +170,7 @@
|
||||
observer: '_viewModeObserver',
|
||||
},
|
||||
|
||||
/** @type ?Gerrit.LineOfInterest */
|
||||
/** @type {?Gerrit.LineOfInterest} */
|
||||
lineOfInterest: Object,
|
||||
|
||||
loading: {
|
||||
@@ -206,7 +207,7 @@
|
||||
* bypassed. If the value is a number, then that number represents the
|
||||
* context preference to use when rendering the bypassed diff.
|
||||
*
|
||||
* @type (number|null)
|
||||
* @type {number|null}
|
||||
*/
|
||||
_safetyBypass: {
|
||||
type: Number,
|
||||
@@ -241,6 +242,7 @@
|
||||
* Observes comment nodes added or removed after the initial render.
|
||||
* Can be used to unregister when the entire diff is (re-)rendered or upon
|
||||
* detachment.
|
||||
*
|
||||
* @type {?PolymerDomApi.ObserveHandle}
|
||||
*/
|
||||
_incrementalNodeObserver: Object,
|
||||
@@ -248,6 +250,7 @@
|
||||
/**
|
||||
* Observes comment nodes added or removed at any point.
|
||||
* Can be used to unregister upon detachment.
|
||||
*
|
||||
* @type {?PolymerDomApi.ObserveHandle}
|
||||
*/
|
||||
_nodeObserver: Object,
|
||||
@@ -324,8 +327,8 @@
|
||||
// up the diff, because they are in the shadow DOM of the gr-diff element.
|
||||
// This takes the shadow DOM selection if one exists.
|
||||
return this.root.getSelection ?
|
||||
this.root.getSelection() :
|
||||
document.getSelection();
|
||||
this.root.getSelection() :
|
||||
document.getSelection();
|
||||
},
|
||||
|
||||
_observeNodes() {
|
||||
@@ -524,8 +527,8 @@
|
||||
return false;
|
||||
}
|
||||
const patchNum = el.classList.contains(DiffSide.LEFT) ?
|
||||
this.patchRange.basePatchNum :
|
||||
this.patchRange.patchNum;
|
||||
this.patchRange.basePatchNum :
|
||||
this.patchRange.patchNum;
|
||||
|
||||
const isEdit = this.patchNumEquals(patchNum, this.EDIT_NAME);
|
||||
const isEditBase = this.patchNumEquals(patchNum, this.PARENT_NAME) &&
|
||||
@@ -576,6 +579,7 @@
|
||||
/**
|
||||
* Gets or creates a comment thread group for a specific line and side on a
|
||||
* diff.
|
||||
*
|
||||
* @param {!Object} contentEl
|
||||
* @param {!Gerrit.DiffSide} commentSide
|
||||
* @return {!Node}
|
||||
@@ -875,6 +879,7 @@
|
||||
|
||||
/**
|
||||
* Find the last chunk for the given side.
|
||||
*
|
||||
* @param {!Object} diff
|
||||
* @param {boolean} leftSide true if checking the base of the diff,
|
||||
* false if testing the revision.
|
||||
@@ -892,8 +897,8 @@
|
||||
chunkIndex--;
|
||||
chunk = diff.content[chunkIndex];
|
||||
} while (
|
||||
// We haven't reached the beginning.
|
||||
chunkIndex >= 0 &&
|
||||
// We haven't reached the beginning.
|
||||
chunkIndex >= 0 &&
|
||||
|
||||
// The chunk doesn't have both sides.
|
||||
!chunk.ab &&
|
||||
@@ -911,6 +916,7 @@
|
||||
|
||||
/**
|
||||
* Check whether the specified side of the diff has a trailing newline.
|
||||
*
|
||||
* @param {!Object} diff
|
||||
* @param {boolean} leftSide true if checking the base of the diff,
|
||||
* false if testing the revision.
|
||||
@@ -961,6 +967,7 @@
|
||||
/**
|
||||
* Get the approximate length of the diff as the sum of the maximum
|
||||
* length of the chunks.
|
||||
*
|
||||
* @param {Object} diff object
|
||||
* @return {number}
|
||||
*/
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
|
||||
const parentCounts = revisionInfo.getParentCountMap();
|
||||
const currentParentCount = parentCounts.hasOwnProperty(patchNum) ?
|
||||
parentCounts[patchNum] : 1;
|
||||
parentCounts[patchNum] : 1;
|
||||
const maxParents = revisionInfo.getMaxParents();
|
||||
const isMerge = currentParentCount > 1;
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
* The basePatchNum should always be <= patchNum -- because sortedRevisions
|
||||
* is sorted in reverse order (higher patchset nums first), invalid base
|
||||
* patch nums have an index greater than the index of patchNum.
|
||||
*
|
||||
* @param {number|string} basePatchNum The possible base patch num.
|
||||
* @param {number|string} patchNum The current selected patch num.
|
||||
* @param {!Array} sortedRevisions
|
||||
@@ -246,7 +247,7 @@
|
||||
_computePatchSetDescription(revisions, patchNum, opt_addFrontSpace) {
|
||||
const rev = this.getRevisionByPatchNum(revisions, patchNum);
|
||||
return (rev && rev.description) ?
|
||||
(opt_addFrontSpace ? ' ' : '') +
|
||||
(opt_addFrontSpace ? ' ' : '') +
|
||||
rev.description.substring(0, PATCH_DESC_MAX_LENGTH) : '';
|
||||
},
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ limitations under the License.
|
||||
assert.deepEqual(element._computeBaseDropdownContent(availablePatches,
|
||||
patchNum, sortedRevisions, element.changeComments,
|
||||
element.revisionInfo),
|
||||
expectedResult);
|
||||
expectedResult);
|
||||
});
|
||||
|
||||
test('_computeBaseDropdownContent called when patchNum updates', () => {
|
||||
@@ -344,7 +344,7 @@ limitations under the License.
|
||||
|
||||
assert.deepEqual(element._computePatchDropdownContent(availablePatches,
|
||||
basePatchNum, sortedRevisions, element.changeComments),
|
||||
expectedResult);
|
||||
expectedResult);
|
||||
});
|
||||
|
||||
test('filesWeblinks', () => {
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
|
||||
/**
|
||||
* Layer method to add annotations to a line.
|
||||
*
|
||||
* @param {!HTMLElement} el The DIV.contentText element to apply the
|
||||
* annotation to.
|
||||
* @param {!HTMLElement} lineNumberEl
|
||||
@@ -66,12 +67,12 @@
|
||||
annotate(el, lineNumberEl, line) {
|
||||
let ranges = [];
|
||||
if (line.type === GrDiffLine.Type.REMOVE || (
|
||||
line.type === GrDiffLine.Type.BOTH &&
|
||||
line.type === GrDiffLine.Type.BOTH &&
|
||||
el.getAttribute('data-side') !== 'right')) {
|
||||
ranges = ranges.concat(this._getRangesForLine(line, 'left'));
|
||||
}
|
||||
if (line.type === GrDiffLine.Type.ADD || (
|
||||
line.type === GrDiffLine.Type.BOTH &&
|
||||
line.type === GrDiffLine.Type.BOTH &&
|
||||
el.getAttribute('data-side') !== 'left')) {
|
||||
ranges = ranges.concat(this._getRangesForLine(line, 'right'));
|
||||
}
|
||||
@@ -85,6 +86,7 @@
|
||||
|
||||
/**
|
||||
* Register a listener for layer updates.
|
||||
*
|
||||
* @param {function(number, number, string)} fn The update handler function.
|
||||
* Should accept as arguments the line numbers for the start and end of
|
||||
* the update and the side as a string.
|
||||
@@ -95,6 +97,7 @@
|
||||
|
||||
/**
|
||||
* Notify Layer listeners of changes to annotations.
|
||||
*
|
||||
* @param {number} start The line where the update starts.
|
||||
* @param {number} end The line where the update ends.
|
||||
* @param {string} side The side of the update. ('left' or 'right')
|
||||
@@ -108,6 +111,7 @@
|
||||
/**
|
||||
* Handle change in the ranges by updating the ranges maps and by
|
||||
* emitting appropriate update notifications.
|
||||
*
|
||||
* @param {Object} record The change record.
|
||||
*/
|
||||
_handleCommentRangesChange(record) {
|
||||
@@ -134,7 +138,7 @@
|
||||
this._updateRangesMap(
|
||||
side, range, hovering, (forLine, start, end, hovering) => {
|
||||
const index = forLine.findIndex(lineRange =>
|
||||
lineRange.start === start && lineRange.end === end);
|
||||
lineRange.start === start && lineRange.end === end);
|
||||
forLine[index].hovering = hovering;
|
||||
});
|
||||
}
|
||||
@@ -147,7 +151,7 @@
|
||||
this._updateRangesMap(
|
||||
side, range, hovering, (forLine, start, end) => {
|
||||
const index = forLine.findIndex(lineRange =>
|
||||
lineRange.start === start && lineRange.end === end);
|
||||
lineRange.start === start && lineRange.end === end);
|
||||
forLine.splice(index, 1);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@
|
||||
* The promise last returned from `process()` while the asynchronous
|
||||
* processing is running - `null` otherwise. Provides a `cancel()`
|
||||
* method that rejects it with `{isCancelled: true}`.
|
||||
*
|
||||
* @type {?Object}
|
||||
*/
|
||||
_processPromise: {
|
||||
@@ -183,6 +184,7 @@
|
||||
/**
|
||||
* Annotation layer method to add syntax annotations to the given element
|
||||
* for the given line.
|
||||
*
|
||||
* @param {!HTMLElement} el
|
||||
* @param {!HTMLElement} lineNumberEl
|
||||
* @param {!Object} line (GrDiffLine)
|
||||
@@ -193,11 +195,11 @@
|
||||
// Determine the side.
|
||||
let side;
|
||||
if (line.type === GrDiffLine.Type.REMOVE || (
|
||||
line.type === GrDiffLine.Type.BOTH &&
|
||||
line.type === GrDiffLine.Type.BOTH &&
|
||||
el.getAttribute('data-side') !== 'right')) {
|
||||
side = 'left';
|
||||
} else if (line.type === GrDiffLine.Type.ADD || (
|
||||
el.getAttribute('data-side') !== 'left')) {
|
||||
el.getAttribute('data-side') !== 'left')) {
|
||||
side = 'right';
|
||||
}
|
||||
|
||||
@@ -227,6 +229,7 @@
|
||||
/**
|
||||
* Start processing syntax for the loaded diff and notify layer listeners
|
||||
* as syntax info comes online.
|
||||
*
|
||||
* @return {Promise}
|
||||
*/
|
||||
process() {
|
||||
@@ -322,6 +325,7 @@
|
||||
* Take a string of HTML with the (potentially nested) syntax markers
|
||||
* Highlight.js emits and emit a list of text ranges and classes for the
|
||||
* markers.
|
||||
*
|
||||
* @param {string} str The string of HTML.
|
||||
* @return {!Array<!Object>} The list of ranges.
|
||||
*/
|
||||
@@ -357,6 +361,7 @@
|
||||
/**
|
||||
* For a given state, process the syntax for the next line (or pair of
|
||||
* lines).
|
||||
*
|
||||
* @param {!Object} state The processing state for the layer.
|
||||
*/
|
||||
_processNextLine(state) {
|
||||
@@ -471,6 +476,7 @@
|
||||
|
||||
/**
|
||||
* Tells whether the state has exhausted its current section.
|
||||
*
|
||||
* @param {!Object} state
|
||||
* @return {boolean}
|
||||
*/
|
||||
@@ -487,6 +493,7 @@
|
||||
/**
|
||||
* For a given state, notify layer listeners of any processed line ranges
|
||||
* that have not yet been notified.
|
||||
*
|
||||
* @param {!Object} state
|
||||
*/
|
||||
_notify(state) {
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
|
||||
/**
|
||||
* Given a path string, checks that it is a valid file path.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {boolean}
|
||||
*/
|
||||
@@ -126,6 +127,7 @@
|
||||
|
||||
/**
|
||||
* Given a dom event, gets the dialog that lies along this event path.
|
||||
*
|
||||
* @param {!Event} e
|
||||
* @return {!Element|undefined}
|
||||
*/
|
||||
@@ -214,17 +216,17 @@
|
||||
const dialog = this._getDialogFromEvent(e);
|
||||
return this.$.restAPI.renameFileInChangeEdit(this.change._number,
|
||||
this._path, this._newPath).then(res => {
|
||||
if (!res.ok) { return; }
|
||||
this._closeDialog(dialog, true);
|
||||
Gerrit.Nav.navigateToChange(this.change);
|
||||
});
|
||||
if (!res.ok) { return; }
|
||||
this._closeDialog(dialog, true);
|
||||
Gerrit.Nav.navigateToChange(this.change);
|
||||
});
|
||||
},
|
||||
|
||||
_queryFiles(input) {
|
||||
return this.$.restAPI.queryChangeFiles(this.change._number,
|
||||
this.patchNum, input).then(res => res.map(file => {
|
||||
return {name: file};
|
||||
}));
|
||||
return {name: file};
|
||||
}));
|
||||
},
|
||||
|
||||
_computeIsInvisible(id, hiddenActions) {
|
||||
|
||||
@@ -141,11 +141,11 @@
|
||||
}
|
||||
return this.$.restAPI.renameFileInChangeEdit(this._changeNum,
|
||||
this._path, path).then(res => {
|
||||
if (!res.ok) { return; }
|
||||
if (!res.ok) { return; }
|
||||
|
||||
this._successfulSave = true;
|
||||
this._viewEditInChangeView();
|
||||
});
|
||||
this._successfulSave = true;
|
||||
this._viewEditInChangeView();
|
||||
});
|
||||
},
|
||||
|
||||
_viewEditInChangeView() {
|
||||
@@ -191,13 +191,13 @@
|
||||
this.$.storage.eraseEditableContentItem(this.storageKey);
|
||||
return this.$.restAPI.saveChangeEdit(this._changeNum, this._path,
|
||||
this._newContent).then(res => {
|
||||
this._saving = false;
|
||||
this._showAlert(res.ok ? SAVED_MESSAGE : SAVE_FAILED_MSG);
|
||||
if (!res.ok) { return; }
|
||||
this._saving = false;
|
||||
this._showAlert(res.ok ? SAVED_MESSAGE : SAVE_FAILED_MSG);
|
||||
if (!res.ok) { return; }
|
||||
|
||||
this._content = this._newContent;
|
||||
this._successfulSave = true;
|
||||
});
|
||||
this._content = this._newContent;
|
||||
this._successfulSave = true;
|
||||
});
|
||||
},
|
||||
|
||||
_showAlert(message) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user