Adding checkbox to annotations API to toggle annotations on/off
Change-Id: I661869c5ef60da9180aecd2fb4e672648cdc80f4
This commit is contained in:
@@ -277,6 +277,12 @@ limitations under the License.
|
|||||||
on-tap="_handlePrefsTap">Preferences</gr-button>
|
on-tap="_handlePrefsTap">Preferences</gr-button>
|
||||||
</span>
|
</span>
|
||||||
</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$="blameLoader [[_computeBlameLoaderClass(_isImageDiff, _isBlameSupported)]]">
|
||||||
<span class="separator"></span>
|
<span class="separator"></span>
|
||||||
<gr-button
|
<gr-button
|
||||||
|
@@ -51,6 +51,45 @@
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* The notify function will call the listeners of all required annotation
|
||||||
* layers. Intended to be called by the plugin when all required data for
|
* layers. Intended to be called by the plugin when all required data for
|
||||||
|
@@ -23,14 +23,23 @@ limitations under the License.
|
|||||||
<link rel="import" href="../../../test/common-test-setup.html"/>
|
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||||
<link rel="import" href="../../change/gr-change-actions/gr-change-actions.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>
|
<script>
|
||||||
suite('gr-annotation-actions-js-api tests', () => {
|
suite('gr-annotation-actions-js-api tests', () => {
|
||||||
let annotationActions;
|
let annotationActions;
|
||||||
let sandbox;
|
let sandbox;
|
||||||
|
let plugin;
|
||||||
|
|
||||||
setup(() => {
|
setup(() => {
|
||||||
sandbox = sinon.sandbox.create();
|
sandbox = sinon.sandbox.create();
|
||||||
let plugin;
|
|
||||||
Gerrit.install(p => { plugin = p; }, '0.1',
|
Gerrit.install(p => { plugin = p; }, '0.1',
|
||||||
'http://test.com/plugins/testplugin/static/test.js');
|
'http://test.com/plugins/testplugin/static/test.js');
|
||||||
annotationActions = plugin.annotationApi();
|
annotationActions = plugin.annotationApi();
|
||||||
@@ -101,6 +110,45 @@ limitations under the License.
|
|||||||
assert.isTrue(layer2Spy.called);
|
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', () => {
|
test('layer notify listeners', () => {
|
||||||
const annotationLayer = annotationActions.getLayer(
|
const annotationLayer = annotationActions.getLayer(
|
||||||
'/dummy/path', 1, 2);
|
'/dummy/path', 1, 2);
|
||||||
|
@@ -20,27 +20,30 @@
|
|||||||
changeNum: 77001,
|
changeNum: 77001,
|
||||||
patchNum: 1,
|
patchNum: 1,
|
||||||
};
|
};
|
||||||
|
coverageData['go/sklog/sklog.go'] = {
|
||||||
|
linesMissingCoverage: [3, 322, 323, 324],
|
||||||
|
totalLines: 350,
|
||||||
|
changeNum: 85963,
|
||||||
|
patchNum: 13,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Gerrit.install(plugin => {
|
Gerrit.install(plugin => {
|
||||||
const coverageData = {};
|
const coverageData = {};
|
||||||
plugin.annotationApi().addNotifier(notifyFunc => {
|
let displayCoverage = false;
|
||||||
new Promise(resolve => setTimeout(resolve, 3000)).then(
|
const annotationApi = plugin.annotationApi();
|
||||||
() => {
|
annotationApi.addLayer(context => {
|
||||||
populateWithDummyData(coverageData);
|
|
||||||
Object.keys(coverageData).forEach(file => {
|
|
||||||
notifyFunc(file, 0, coverageData[file].totalLines, 'right');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}).addLayer(context => {
|
|
||||||
if (Object.keys(coverageData).length === 0) {
|
if (Object.keys(coverageData).length === 0) {
|
||||||
// Coverage data is not ready yet.
|
// Coverage data is not ready yet.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const path = context.path;
|
const path = context.path;
|
||||||
const line = context.line;
|
const line = context.line;
|
||||||
// Highlight lines missing coverage with this background color.
|
// Highlight lines missing coverage with this background color if
|
||||||
const cssClass = Gerrit.css('background-color: #EF9B9B');
|
// coverage should be displayed, else do nothing.
|
||||||
|
const cssClass = displayCoverage
|
||||||
|
? Gerrit.css('background-color: #EF9B9B')
|
||||||
|
: Gerrit.css('');
|
||||||
if (coverageData[path] &&
|
if (coverageData[path] &&
|
||||||
coverageData[path].changeNum === context.changeNum &&
|
coverageData[path].changeNum === context.changeNum &&
|
||||||
coverageData[path].patchNum === context.patchNum) {
|
coverageData[path].patchNum === context.patchNum) {
|
||||||
@@ -49,6 +52,21 @@
|
|||||||
context.annotateRange(0, line.text.length, cssClass, 'right');
|
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>
|
</script>
|
||||||
|
Reference in New Issue
Block a user