-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Templates #2761
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Templates #2761
Conversation
rangeselector.buttons updatemenus.buttons slider.steps axes.tickformatstops mapbox.layers
rangeselector.buttons updatemenus.buttons parcoords & splom.dimensions (and DRY these a bit)
there may be other similar logic we need to update for templates, but these are the most readily apparent ones
cc @nicolaskruchten this is happening 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the way this looks so far.
The coerce-level template logic appears pretty robust 💪
@@ -513,6 +513,16 @@ module.exports = { | |||
tickformatstops: { | |||
_isLinkedToArray: 'tickformatstop', | |||
|
|||
visible: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe enabled
(similar to transforms) here would make more sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.... but maybe it isn't worth breaking symmetric with all other templated arrays 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, enabled
certainly makes more sense here. I thought about that but deferred to symmetry at the time. But the way this ended up working out, it would be easy to make visibilityAttr: 'enabled'
or something an option to handleArrayContainerDefaults
. I'll give that a try.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switched to enabled
in fb489aa
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm glad this wasn't too hard to implement 🎉
}) | ||
.then(function() { | ||
expect(getLayerLength(gd)).toEqual(2); | ||
expect(countVisibleLayers(gd)).toEqual(2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice tests. Thanks!
@@ -10,6 +10,12 @@ | |||
|
|||
|
|||
module.exports = { | |||
visible: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Brilliant commit ✨
* @param {string} dataAttr: the attribute of each dimension containing the data | ||
* @param {integer} len: an already-existing length from other attributes | ||
*/ | ||
module.exports = function(traceOut, dimensions, dataAttr, len) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nicely done 🥇
var handleArrayContainerDefaults = require('../../plots/array_container_defaults'); | ||
var handleAnnotationDefaults = require('./annotation_defaults'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
YES. Thanks for doing this 💯
// Note: does not need template propagation, since coerceAxis is still | ||
// based on the subplot-wide coerce function. Though it may be more | ||
// efficient to make a new coerce function, then we *would* need to | ||
// propagate the template. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the note 📚
@@ -34,7 +34,6 @@ var Template = require('../plot_api/plot_template'); | |||
* - parentObj {object} (as in closure) | |||
* - opts {object} (as in closure) | |||
* - itemOpts {object} | |||
* - itemIsNotPlainObject {boolean} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice cleanup!
src/plot_api/plot_template.js
Outdated
@@ -12,7 +12,56 @@ | |||
var Lib = require('../lib'); | |||
var plotAttributes = require('../plots/attributes'); | |||
|
|||
var TEMPLATEITEMNAME = exports.TEMPLATEITEMNAME = 'templateitemname'; | |||
var TEMPLATEITEMNAME = 'templateitemname'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm usually not a fan of three-word attribute names, but I can't really think of a better alternative, so 👍
// value back to the input - so it doesn't make sense to template this. | ||
// TODO: should we prohibit this in `coerce` as well, or honor it if | ||
// someone enters it explicitly? | ||
_noTemplating: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prevented makeTemplate
from pulling out axis.type
with this flag, as it seems more likely to cause problems than fix them, but I did NOT prevent coerce
from using it if someone makes a template of manually and includes it (to say "always make this axis categorical" for example). Seem reasonable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seem reasonable?
Very reasonable 👌
@@ -397,6 +397,8 @@ function isInSchema(schema, key) { | |||
} | |||
|
|||
function getNestedSchema(schema, key) { | |||
if(key in schema) return schema[key]; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not part of templating, just noticed it as there's similar logic in templates and I was looking to see how you handled it here 🙈
@@ -18,7 +18,7 @@ | |||
"yaxis2":{"title":"category","range":[0,1],"domain":[0.6,1],"anchor":"x2","type":"category","showgrid":false,"zeroline":false,"showticklabels":false}, | |||
"height":400, | |||
"width":800, | |||
"margin": {"l":20,"r":20,"top":10,"bottom":10,"pad":0}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to change the image so just deleted these bad attrs uncovered when testing this fix.
Perhaps we should make a test that validates all our mocks, to ensure we're not accidentally encouraging mistaken usage like this? Not in this PR of course...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should make a test that validates all our mocks, to ensure we're not accidentally encouraging mistaken usage like this?
That's a great idea 👍
src/plot_api/plot_template.js
Outdated
@@ -203,6 +203,8 @@ exports.arrayTemplater = function(container, name, inclusionAttr) { | |||
// it's explicitly marked visible - in which case it gets NO template, | |||
// not even the default. | |||
out[inclusionAttr] = itemIn[inclusionAttr] || false; | |||
// special falsy value we can look for in validateTemplate | |||
out._template = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case is just special because we were told to look for a template by name and it wasn't found.
Otherwise _template
can be null
(no template was found but that's fine) or undefined
(we don't need to propagate the template into this container).
@@ -38,7 +38,7 @@ var isArrayOrTypedArray = Lib.isArrayOrTypedArray; | |||
* - {string} msg | |||
* error message (shown in console in logger config argument is enable) | |||
*/ | |||
module.exports = function valiate(data, layout) { | |||
module.exports = function validate(data, layout) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good 👁️
src/plot_api/template_api.js
Outdated
else { | ||
// TODO: any need to look deeper than the first level of layout? | ||
// I don't think so, that gets all the subplot types which should be | ||
// sufficient. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about xaxis.rangeslider.yaxis2
from #2364?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, good point. You're right, though it's a lot of complication (for example for xaxis.rangeslider.yaxis
we'd have to look for xaxis<N>.rangeslider.yaxis<M>
for any combination of <N>
and <M>
and only generate an error if we don't find any of them. And the only time this would alert you that the template isn't appropriate is if the template has a xaxis<N>.rangeslider.yaxis<M>
but does NOT have yaxis<M>
- ie your template had opinions about how that y axis should work inside the rangeslider, but left the y axis itself untouched. This is of course possible, just seems very unlikely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is of course possible, just seems very unlikely.
Right. I don't this needs special handling. A comment about this would suffice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actually wasn't all that hard - recursed into layout in 15931cf
* to test. If omitted, we will look for a template already attached as the | ||
* plot's `layout.template` attribute. | ||
* | ||
* @returns {array} array of error objects each containing: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THanks for making this have a similar API as Plotly.validate
!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One difference is I didn't make the object fields consistent - they all have code
but each error, in fact even more specific than each code
, includes whatever extra data it deems relevant. Given the nature of the issues (some apply to a specific trace, some to a path, some to a trace type but not a specific trace, etc... as opposed to Plotly.validate
where you can basically always trace the issue back to a specific path) it seemed a bit to constraining to give them all the same fields.
// value back to the input - so it doesn't make sense to template this. | ||
// Note: we do NOT prohibit this in `coerce`, so if someone enters a | ||
// type in the template explicitly it will be honored as the default. | ||
_noTemplating: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
polar.angularaxis.type
does not inherit from type
in cartesian/layout_attributes.js
. Should it also have _noTemplating: true
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good call - angularaxis.type
gets _noTemplating
in b1c6f0a
test/jasmine/tests/template_test.js
Outdated
1); | ||
}); | ||
|
||
it('catches missing template.data', function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐄 catches missing template.layout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch! 818cac9
Fantastic. 💃 |
For #2469
The first 6 commits - up through 3dee25c - are essentially prep work, mostly standardizing and simplifying our handling of container arrays.
Then there's one large commit 5cca8d3 that implements the coerce-level templating that I settled on, after first trying to merge templates into
data
andlayout
directly at the beginning ofsupplyDefaults
, which failed for a variety of reasons.After that are a bunch of cleanup commits, like 8e2a321 making array objects (which may not exist in
layout
if they came from named template items) work with GUI editing.TODO:
@etpinard anything here look problematic to you?