Merge "Adding checkbox to annotations API to toggle annotations on/off"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index 794e1fb..36ae32a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -287,6 +287,12 @@
on-tap="_handlePrefsTap">Preferences</gr-button>
</span>
</span>
+ <gr-endpoint-decorator name="annotation-toggler">
+ <span hidden id="annotation-span">
+ <label for="annotation-checkbox" id="annotation-label"></label>
+ <input is="iron-input" type="checkbox" id="annotation-checkbox" disabled>
+ </span>
+ </gr-endpoint-decorator>
<span class$="blameLoader [[_computeBlameLoaderClass(_isImageDiff, _isBlameSupported)]]">
<span class="separator"></span>
<gr-button
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js
index 94bae45..6350c54 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api.js
@@ -52,6 +52,45 @@
};
/**
+ * Returns a checkbox HTMLElement that can be used to toggle annotations
+ * on/off. The checkbox will be initially disabled. Plugins should enable it
+ * when data is ready and should add a click handler to toggle CSS on/off.
+ *
+ * Note1: Calling this method from multiple plugins will only work for the
+ * 1st call. It will print an error message for all subsequent calls
+ * and will not invoke their onAttached functions.
+ * Note2: This method will be deprecated and eventually removed when
+ * https://bugs.chromium.org/p/gerrit/issues/detail?id=8077 is
+ * implemented.
+ *
+ * @param {String} checkboxLabel Will be used as the label for the checkbox.
+ * Optional. "Enable" is used if this is not specified.
+ * @param {Function<HTMLElement>} onAttached The function that will be called
+ * when the checkbox is attached to the page.
+ */
+ GrAnnotationActionsInterface.prototype.enableToggleCheckbox = function(
+ checkboxLabel, onAttached) {
+ this.plugin.hook('annotation-toggler').onAttached(element => {
+ if (!element.content.hidden) {
+ console.error(
+ element.content.id + ' is already enabled. Cannot re-enable.');
+ return;
+ }
+ element.content.removeAttribute('hidden');
+
+ const label = element.content.querySelector('#annotation-label');
+ if (checkboxLabel) {
+ label.textContent = checkboxLabel;
+ } else {
+ label.textContent = 'Enable';
+ }
+ const checkbox = element.content.querySelector('#annotation-checkbox');
+ onAttached(checkbox);
+ });
+ return this;
+ };
+
+ /**
* The notify function will call the listeners of all required annotation
* layers. Intended to be called by the plugin when all required data for
* annotation is available.
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
index 39623ed..a19df85 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-annotation-actions-js-api_test.html
@@ -23,14 +23,23 @@
<link rel="import" href="../../../test/common-test-setup.html"/>
<link rel="import" href="../../change/gr-change-actions/gr-change-actions.html">
+<test-fixture id="basic">
+ <template>
+ <span hidden id="annotation-span">
+ <label for="annotation-checkbox" id="annotation-label"></label>
+ <input is="iron-input" type="checkbox" id="annotation-checkbox" disabled>
+ </span>
+ </template>
+</test-fixture>
+
<script>
suite('gr-annotation-actions-js-api tests', () => {
let annotationActions;
let sandbox;
+ let plugin;
setup(() => {
sandbox = sinon.sandbox.create();
- let plugin;
Gerrit.install(p => { plugin = p; }, '0.1',
'http://test.com/plugins/testplugin/static/test.js');
annotationActions = plugin.annotationApi();
@@ -101,6 +110,45 @@
assert.isTrue(layer2Spy.called);
});
+ test('toggle checkbox', () => {
+ fakeEl = {content: fixture('basic')};
+ const hookStub = {onAttached: sandbox.stub()};
+ sandbox.stub(plugin, 'hook').returns(hookStub);
+
+ let checkbox;
+ let onAttachedFuncCalled = false;
+ const onAttachedFunc = c => {
+ checkbox = c;
+ onAttachedFuncCalled = true;
+ };
+ annotationActions.enableToggleCheckbox('test label', onAttachedFunc);
+ emulateAttached = () => hookStub.onAttached.callArgWith(0, fakeEl);
+ emulateAttached();
+
+ // Assert that onAttachedFunc is called and HTML elements have the
+ // expected state.
+ assert.isTrue(onAttachedFuncCalled);
+ assert.equal(checkbox.id, 'annotation-checkbox');
+ assert.isTrue(checkbox.disabled);
+ assert.equal(document.getElementById('annotation-label').textContent,
+ 'test label');
+ assert.isFalse(document.getElementById('annotation-span').hidden);
+
+ // Assert that error is shown if we try to enable checkbox again.
+ onAttachedFuncCalled = false;
+ annotationActions.enableToggleCheckbox('test label2', onAttachedFunc);
+ const errorStub = sandbox.stub(
+ console, 'error', (msg, err) => undefined);
+ emulateAttached();
+ assert.isTrue(
+ errorStub.calledWith(
+ 'annotation-span is already enabled. Cannot re-enable.'));
+ // Assert that onAttachedFunc is not called and the label has not changed.
+ assert.isFalse(onAttachedFuncCalled);
+ assert.equal(document.getElementById('annotation-label').textContent,
+ 'test label');
+ });
+
test('layer notify listeners', () => {
const annotationLayer = annotationActions.getLayer(
'/dummy/path', 1, 2);
diff --git a/polygerrit-ui/app/samples/coverage-plugin.html b/polygerrit-ui/app/samples/coverage-plugin.html
index 6f76dc4..9bec658 100644
--- a/polygerrit-ui/app/samples/coverage-plugin.html
+++ b/polygerrit-ui/app/samples/coverage-plugin.html
@@ -20,35 +20,53 @@
changeNum: 77001,
patchNum: 1,
};
+ coverageData['go/sklog/sklog.go'] = {
+ linesMissingCoverage: [3, 322, 323, 324],
+ totalLines: 350,
+ changeNum: 85963,
+ patchNum: 13,
+ };
}
Gerrit.install(plugin => {
const coverageData = {};
- plugin.annotationApi().addNotifier(notifyFunc => {
- new Promise(resolve => setTimeout(resolve, 3000)).then(
- () => {
- populateWithDummyData(coverageData);
- Object.keys(coverageData).forEach(file => {
- notifyFunc(file, 0, coverageData[file].totalLines, 'right');
- });
- });
- }).addLayer(context => {
+ let displayCoverage = false;
+ const annotationApi = plugin.annotationApi();
+ annotationApi.addLayer(context => {
if (Object.keys(coverageData).length === 0) {
- // Coverage data is not ready yet.
+ // Coverage data is not ready yet.
return;
}
const path = context.path;
const line = context.line;
- // Highlight lines missing coverage with this background color.
- const cssClass = Gerrit.css('background-color: #EF9B9B');
+ // Highlight lines missing coverage with this background color if
+ // coverage should be displayed, else do nothing.
+ const cssClass = displayCoverage
+ ? Gerrit.css('background-color: #EF9B9B')
+ : Gerrit.css('');
if (coverageData[path] &&
- coverageData[path].changeNum === context.changeNum &&
- coverageData[path].patchNum === context.patchNum) {
+ coverageData[path].changeNum === context.changeNum &&
+ coverageData[path].patchNum === context.patchNum) {
const linesMissingCoverage = coverageData[path].linesMissingCoverage;
if (linesMissingCoverage.includes(line.afterNumber)) {
context.annotateRange(0, line.text.length, cssClass, 'right');
}
}
+ }).enableToggleCheckbox('Display Coverage', checkbox => {
+ // Checkbox is attached so now add the notifier that will be controlled
+ // by the checkbox.
+ annotationApi.addNotifier(notifyFunc => {
+ new Promise(resolve => setTimeout(resolve, 3000)).then(() => {
+ populateWithDummyData(coverageData);
+ checkbox.disabled = false;
+ checkbox.onclick = e => {
+ displayCoverage = e.target.checked;
+ Object.keys(coverageData).forEach(file => {
+ notifyFunc(file, 0, coverageData[file].totalLines, 'right');
+ });
+ };
+ });
+ });
});
});
</script>