Get rid of some global variables - Part 7

* Replace the following global variables with named imports:
  - GrEventHelper
  - GrPluginRestApi
  - GrRepoApi
* Update gr-app-global-var-init.js

Change-Id: If1ac4eb7e6acd4191486012a37da0ff90a143e80
This commit is contained in:
Dmitrii Filippov
2020-04-06 16:40:13 +02:00
parent c1afe41564
commit 67d206b776
10 changed files with 251 additions and 265 deletions

View File

@@ -166,10 +166,7 @@ module.exports = {
// Instead export variables from modules
// TODO(dmfilippov): Remove global variables from polygerrit
"Gerrit": "readonly",
"GrEventHelper": "readonly",
"GrPluginActionContext": "readonly",
"GrPluginRestApi": "readonly",
"GrRepoApi": "readonly",
"GrReporting": "readonly",
"GrSettingsApi": "readonly",
"GrStylesApi": "readonly",

View File

@@ -58,6 +58,9 @@ import {GrAnnotationActionsInterface} from './shared/gr-js-api-interface/gr-anno
import {GrChangeMetadataApi} from './plugins/gr-change-metadata-api/gr-change-metadata-api.js';
import {GrEmailSuggestionsProvider} from '../scripts/gr-email-suggestions-provider/gr-email-suggestions-provider.js';
import {GrGroupSuggestionsProvider} from '../scripts/gr-group-suggestions-provider/gr-group-suggestions-provider.js';
import {GrEventHelper} from './plugins/gr-event-helper/gr-event-helper.js';
import {GrPluginRestApi} from './shared/gr-js-api-interface/gr-plugin-rest-api.js';
import {GrRepoApi} from './plugins/gr-repo-api/gr-repo-api.js';
export function initGlobalVariables() {
window.GrDisplayNameUtils = GrDisplayNameUtils;
@@ -99,4 +102,7 @@ export function initGlobalVariables() {
window.GrChangeMetadataApi = GrChangeMetadataApi;
window.GrEmailSuggestionsProvider = GrEmailSuggestionsProvider;
window.GrGroupSuggestionsProvider = GrGroupSuggestionsProvider;
window.GrEventHelper = GrEventHelper;
window.GrPluginRestApi = GrPluginRestApi;
window.GrRepoApi = GrRepoApi;
}

View File

@@ -24,93 +24,88 @@ $_documentContainer.innerHTML = `<dom-module id="gr-event-helper">
document.head.appendChild($_documentContainer.content);
(function(window) {
'use strict';
/** @constructor */
export function GrEventHelper(element) {
this.element = element;
this._unsubscribers = [];
}
/** @constructor */
function GrEventHelper(element) {
this.element = element;
this._unsubscribers = [];
}
/**
* Add a callback to arbitrary event.
* The callback may return false to prevent event bubbling.
*
* @param {string} event Event name
* @param {function(Event):boolean} callback
* @return {function()} Unsubscribe function.
*/
GrEventHelper.prototype.on = function(event, callback) {
return this._listen(this.element, callback, {event});
};
/**
* Add a callback to arbitrary event.
* The callback may return false to prevent event bubbling.
*
* @param {string} event Event name
* @param {function(Event):boolean} callback
* @return {function()} Unsubscribe function.
*/
GrEventHelper.prototype.on = function(event, callback) {
return this._listen(this.element, callback, {event});
};
/**
* Alias of onClick
*
* @see onClick
*/
GrEventHelper.prototype.onTap = function(callback) {
return this._listen(this.element, callback);
};
/**
* Alias of onClick
*
* @see onClick
*/
GrEventHelper.prototype.onTap = function(callback) {
return this._listen(this.element, callback);
};
/**
* Add a callback to element click or touch.
* The callback may return false to prevent event bubbling.
*
* @param {function(Event):boolean} callback
* @return {function()} Unsubscribe function.
*/
GrEventHelper.prototype.onClick = function(callback) {
return this._listen(this.element, callback);
};
/**
* Add a callback to element click or touch.
* The callback may return false to prevent event bubbling.
*
* @param {function(Event):boolean} callback
* @return {function()} Unsubscribe function.
*/
GrEventHelper.prototype.onClick = function(callback) {
return this._listen(this.element, callback);
};
/**
* Alias of captureClick
*
* @see captureClick
*/
GrEventHelper.prototype.captureTap = function(callback) {
return this._listen(this.element.parentElement, callback, {capture: true});
};
/**
* Alias of captureClick
*
* @see captureClick
*/
GrEventHelper.prototype.captureTap = function(callback) {
return this._listen(this.element.parentElement, callback, {capture: true});
};
/**
* Add a callback to element click or touch ahead of normal flow.
* Callback is installed on parent during capture phase.
* https://www.w3.org/TR/DOM-Level-3-Events/#event-flow
* The callback may return false to cancel regular event listeners.
*
* @param {function(Event):boolean} callback
* @return {function()} Unsubscribe function.
*/
GrEventHelper.prototype.captureClick = function(callback) {
return this._listen(this.element.parentElement, callback, {capture: true});
};
/**
* Add a callback to element click or touch ahead of normal flow.
* Callback is installed on parent during capture phase.
* https://www.w3.org/TR/DOM-Level-3-Events/#event-flow
* The callback may return false to cancel regular event listeners.
*
* @param {function(Event):boolean} callback
* @return {function()} Unsubscribe function.
*/
GrEventHelper.prototype.captureClick = function(callback) {
return this._listen(this.element.parentElement, callback, {capture: true});
};
GrEventHelper.prototype._listen = function(container, callback, opt_options) {
const capture = opt_options && opt_options.capture;
const event = opt_options && opt_options.event || 'click';
const handler = e => {
if (e.path.indexOf(this.element) !== -1) {
let mayContinue = true;
try {
mayContinue = callback(e);
} catch (e) {
console.warn(`Plugin error handing event: ${e}`);
}
if (mayContinue === false) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
}
GrEventHelper.prototype._listen = function(container, callback, opt_options) {
const capture = opt_options && opt_options.capture;
const event = opt_options && opt_options.event || 'click';
const handler = e => {
if (e.path.indexOf(this.element) !== -1) {
let mayContinue = true;
try {
mayContinue = callback(e);
} catch (e) {
console.warn(`Plugin error handing event: ${e}`);
}
};
container.addEventListener(event, handler, capture);
const unsubscribe = () =>
container.removeEventListener(event, handler, capture);
this._unsubscribers.push(unsubscribe);
return unsubscribe;
if (mayContinue === false) {
e.stopImmediatePropagation();
e.stopPropagation();
e.preventDefault();
}
}
};
container.addEventListener(event, handler, capture);
const unsubscribe = () =>
container.removeEventListener(event, handler, capture);
this._unsubscribers.push(unsubscribe);
return unsubscribe;
};
window.GrEventHelper = GrEventHelper;
})(window);

View File

@@ -27,7 +27,6 @@ limitations under the License.
<dom-element id="some-element">
<script type="module">
import '../../../test/common-test-setup.js';
import './gr-event-helper.js';
import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js';
Polymer({
is: 'some-element',
@@ -51,8 +50,9 @@ Polymer({
<script type="module">
import '../../../test/common-test-setup.js';
import './gr-event-helper.js';
import {addListener} from '@polymer/polymer/lib/utils/gestures.js';
import {GrEventHelper} from './gr-event-helper.js';
suite('gr-event-helper tests', () => {
let element;
let instance;

View File

@@ -25,51 +25,42 @@ $_documentContainer.innerHTML = `<dom-module id="gr-repo-api">
document.head.appendChild($_documentContainer.content);
(function(window) {
'use strict';
/** @constructor */
export function GrRepoApi(plugin) {
this._hook = null;
this.plugin = plugin;
}
// Prevent redefinition.
if (window.GrRepoApi) { return; }
GrRepoApi.prototype._createHook = function(title) {
this._hook = this.plugin.hook('repo-command').onAttached(element => {
const pluginCommand =
document.createElement('gr-plugin-repo-command');
pluginCommand.title = title;
element.appendChild(pluginCommand);
});
};
/** @constructor */
function GrRepoApi(plugin) {
this._hook = null;
this.plugin = plugin;
GrRepoApi.prototype.createCommand = function(title, callback) {
if (this._hook) {
console.warn('Already set up.');
return this._hook;
}
GrRepoApi.prototype._createHook = function(title) {
this._hook = this.plugin.hook('repo-command').onAttached(element => {
const pluginCommand =
document.createElement('gr-plugin-repo-command');
pluginCommand.title = title;
element.appendChild(pluginCommand);
});
};
GrRepoApi.prototype.createCommand = function(title, callback) {
if (this._hook) {
console.warn('Already set up.');
return this._hook;
this._createHook(title);
this._hook.onAttached(element => {
if (callback(element.repoName, element.config) === false) {
element.hidden = true;
}
this._createHook(title);
this._hook.onAttached(element => {
if (callback(element.repoName, element.config) === false) {
element.hidden = true;
}
});
return this;
};
});
return this;
};
GrRepoApi.prototype.onTap = function(callback) {
if (!this._hook) {
console.warn('Call createCommand first.');
return this;
}
this._hook.onAttached(element => {
this.plugin.eventHelper(element).on('command-tap', callback);
});
GrRepoApi.prototype.onTap = function(callback) {
if (!this._hook) {
console.warn('Call createCommand first.');
return this;
};
window.GrRepoApi = GrRepoApi;
})(window);
}
this._hook.onAttached(element => {
this.plugin.eventHelper(element).on('command-tap', callback);
});
return this;
};

View File

@@ -34,7 +34,7 @@ limitations under the License.
<script type="module">
import '../../../test/common-test-setup.js';
import '../gr-endpoint-decorator/gr-endpoint-decorator.js';
import './gr-repo-api.js';
suite('gr-repo-api tests', () => {
let sandbox;
let repoApi;

View File

@@ -16,15 +16,12 @@
*/
import '../../../scripts/bundled-polymer.js';
import '../../core/gr-reporting/gr-reporting.js';
import '../../plugins/gr-event-helper/gr-event-helper.js';
import '../../plugins/gr-repo-api/gr-repo-api.js';
import '../../plugins/gr-settings-api/gr-settings-api.js';
import '../../plugins/gr-styles-api/gr-styles-api.js';
import '../gr-rest-api-interface/gr-rest-api-interface.js';
import './gr-api-utils.js';
import './gr-js-api-interface-element.js';
import './gr-plugin-action-context.js';
import './gr-plugin-rest-api.js';
import './gr-public-js-api.js';
import './gr-plugin-loader.js';
import './gr-gerrit.js';

View File

@@ -14,139 +14,134 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function(window) {
'use strict';
let restApi;
let restApi;
function getRestApi() {
if (!restApi) {
restApi = document.createElement('gr-rest-api-interface');
function getRestApi() {
if (!restApi) {
restApi = document.createElement('gr-rest-api-interface');
}
return restApi;
}
export function GrPluginRestApi(opt_prefix) {
this.opt_prefix = opt_prefix || '';
}
GrPluginRestApi.prototype.getLoggedIn = function() {
return getRestApi().getLoggedIn();
};
GrPluginRestApi.prototype.getVersion = function() {
return getRestApi().getVersion();
};
GrPluginRestApi.prototype.getConfig = function() {
return getRestApi().getConfig();
};
GrPluginRestApi.prototype.invalidateReposCache = function() {
getRestApi().invalidateReposCache();
};
GrPluginRestApi.prototype.getAccount = function() {
return getRestApi().getAccount();
};
GrPluginRestApi.prototype.getAccountCapabilities = function(capabilities) {
return getRestApi().getAccountCapabilities(capabilities);
};
GrPluginRestApi.prototype.getRepos =
function(filter, reposPerPage, opt_offset) {
return getRestApi().getRepos(filter, reposPerPage, opt_offset);
};
/**
* Fetch and return native browser REST API Response.
*
* @param {string} method HTTP Method (GET, POST, etc)
* @param {string} url URL without base path or plugin prefix
* @param {Object=} payload Respected for POST and PUT only.
* @param {?function(?Response, string=)=} opt_errFn
* passed as null sometimes.
* @return {!Promise}
*/
GrPluginRestApi.prototype.fetch = function(method, url, opt_payload,
opt_errFn, opt_contentType) {
return getRestApi().send(method, this.opt_prefix + url, opt_payload,
opt_errFn, opt_contentType);
};
/**
* Fetch and parse REST API response, if request succeeds.
*
* @param {string} method HTTP Method (GET, POST, etc)
* @param {string} url URL without base path or plugin prefix
* @param {Object=} payload Respected for POST and PUT only.
* @param {?function(?Response, string=)=} opt_errFn
* passed as null sometimes.
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.send = function(method, url, opt_payload,
opt_errFn, opt_contentType) {
return this.fetch(method, url, opt_payload, opt_errFn, opt_contentType)
.then(response => {
if (response.status < 200 || response.status >= 300) {
return response.text().then(text => {
if (text) {
return Promise.reject(new Error(text));
} else {
return Promise.reject(new Error(response.status));
}
});
} else {
return getRestApi().getResponseObject(response);
}
});
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.get = function(url) {
return this.send('GET', url);
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.post = function(url, opt_payload, opt_errFn,
opt_contentType) {
return this.send('POST', url, opt_payload, opt_errFn, opt_contentType);
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.put = function(url, opt_payload, opt_errFn,
opt_contentType) {
return this.send('PUT', url, opt_payload, opt_errFn, opt_contentType);
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on 204, rejects on error.
*/
GrPluginRestApi.prototype.delete = function(url) {
return this.fetch('DELETE', url).then(response => {
if (response.status !== 204) {
return response.text().then(text => {
if (text) {
return Promise.reject(new Error(text));
} else {
return Promise.reject(new Error(response.status));
}
});
}
return restApi;
}
function GrPluginRestApi(opt_prefix) {
this.opt_prefix = opt_prefix || '';
}
GrPluginRestApi.prototype.getLoggedIn = function() {
return getRestApi().getLoggedIn();
};
GrPluginRestApi.prototype.getVersion = function() {
return getRestApi().getVersion();
};
GrPluginRestApi.prototype.getConfig = function() {
return getRestApi().getConfig();
};
GrPluginRestApi.prototype.invalidateReposCache = function() {
getRestApi().invalidateReposCache();
};
GrPluginRestApi.prototype.getAccount = function() {
return getRestApi().getAccount();
};
GrPluginRestApi.prototype.getAccountCapabilities = function(capabilities) {
return getRestApi().getAccountCapabilities(capabilities);
};
GrPluginRestApi.prototype.getRepos =
function(filter, reposPerPage, opt_offset) {
return getRestApi().getRepos(filter, reposPerPage, opt_offset);
};
/**
* Fetch and return native browser REST API Response.
*
* @param {string} method HTTP Method (GET, POST, etc)
* @param {string} url URL without base path or plugin prefix
* @param {Object=} payload Respected for POST and PUT only.
* @param {?function(?Response, string=)=} opt_errFn
* passed as null sometimes.
* @return {!Promise}
*/
GrPluginRestApi.prototype.fetch = function(method, url, opt_payload,
opt_errFn, opt_contentType) {
return getRestApi().send(method, this.opt_prefix + url, opt_payload,
opt_errFn, opt_contentType);
};
/**
* Fetch and parse REST API response, if request succeeds.
*
* @param {string} method HTTP Method (GET, POST, etc)
* @param {string} url URL without base path or plugin prefix
* @param {Object=} payload Respected for POST and PUT only.
* @param {?function(?Response, string=)=} opt_errFn
* passed as null sometimes.
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.send = function(method, url, opt_payload,
opt_errFn, opt_contentType) {
return this.fetch(method, url, opt_payload, opt_errFn, opt_contentType)
.then(response => {
if (response.status < 200 || response.status >= 300) {
return response.text().then(text => {
if (text) {
return Promise.reject(new Error(text));
} else {
return Promise.reject(new Error(response.status));
}
});
} else {
return getRestApi().getResponseObject(response);
}
});
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.get = function(url) {
return this.send('GET', url);
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.post = function(url, opt_payload, opt_errFn,
opt_contentType) {
return this.send('POST', url, opt_payload, opt_errFn, opt_contentType);
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on success, rejects on error.
*/
GrPluginRestApi.prototype.put = function(url, opt_payload, opt_errFn,
opt_contentType) {
return this.send('PUT', url, opt_payload, opt_errFn, opt_contentType);
};
/**
* @param {string} url URL without base path or plugin prefix
* @return {!Promise} resolves on 204, rejects on error.
*/
GrPluginRestApi.prototype.delete = function(url) {
return this.fetch('DELETE', url).then(response => {
if (response.status !== 204) {
return response.text().then(text => {
if (text) {
return Promise.reject(new Error(text));
} else {
return Promise.reject(new Error(response.status));
}
});
}
return response;
});
};
window.GrPluginRestApi = GrPluginRestApi;
})(window);
return response;
});
};

View File

@@ -26,6 +26,8 @@ limitations under the License.
<script type="module">
import '../../../test/common-test-setup.js';
import './gr-js-api-interface.js';
import {GrPluginRestApi} from './gr-plugin-rest-api.js';
suite('gr-plugin-rest-api tests', () => {
let instance;
let sandbox;

View File

@@ -25,6 +25,9 @@ import {GrPopupInterface} from '../../plugins/gr-popup-interface/gr-popup-interf
import {GrAdminApi} from '../../plugins/gr-admin-api/gr-admin-api.js';
import {GrAnnotationActionsInterface} from './gr-annotation-actions-js-api.js';
import {GrChangeMetadataApi} from '../../plugins/gr-change-metadata-api/gr-change-metadata-api.js';
import {GrEventHelper} from '../../plugins/gr-event-helper/gr-event-helper.js';
import {GrPluginRestApi} from './gr-plugin-rest-api.js';
import {GrRepoApi} from '../../plugins/gr-repo-api/gr-repo-api.js';
(function(window) {
'use strict';