-
Notifications
You must be signed in to change notification settings - Fork 597
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
Support field
in condition
#1980
Changes from 1 commit
57d8176
e39ec50
323e4bb
5c873ef
9a953fa
fba528d
46fbafe
b82b8ab
902dbb9
584361b
49a9688
ddf2317
61a62d7
06cc8dc
28a18bc
012807d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ import {Channel, NONSPATIAL_SCALE_CHANNELS, UNIT_CHANNELS, UNIT_SCALE_CHANNELS, | |
import {CellConfig, Config} from '../config'; | ||
import {Encoding, normalizeEncoding} from '../encoding'; | ||
import * as vlEncoding from '../encoding'; // TODO: remove | ||
import {field, FieldDef, FieldRefOption, isFieldDef} from '../fielddef'; | ||
import {field, FieldDef, FieldRefOption, getFieldDef, isConditionalDef, isFieldDef} from '../fielddef'; | ||
import {Legend} from '../legend'; | ||
import {FILL_STROKE_CONFIG, isMarkDef, Mark, MarkDef, TEXT as TEXT_MARK} from '../mark'; | ||
import {defaultScaleConfig, Domain, hasDiscreteDomain, Scale} from '../scale'; | ||
|
@@ -156,10 +156,13 @@ export class UnitModel extends ModelWithField { | |
if (isFieldDef(channelDef)) { | ||
fieldDef = channelDef; | ||
specifiedScale = channelDef.scale; | ||
} else if (isConditionalDef(channelDef) && isFieldDef(channelDef.condition)) { | ||
fieldDef = channelDef.condition; | ||
specifiedScale = channelDef.condition.scale; | ||
} else if (channel === 'x') { | ||
fieldDef = vlEncoding.getFieldDef(encoding, 'x2'); | ||
fieldDef = getFieldDef(encoding.x2); | ||
} else if (channel === 'y') { | ||
fieldDef = vlEncoding.getFieldDef(encoding, 'y2'); | ||
fieldDef = getFieldDef(encoding.y2); | ||
} | ||
|
||
if (fieldDef) { | ||
|
@@ -249,12 +252,15 @@ export class UnitModel extends ModelWithField { | |
private initLegend(encoding: Encoding<string>): Dict<Legend> { | ||
return NONSPATIAL_SCALE_CHANNELS.reduce(function(_legend, channel) { | ||
const channelDef = encoding[channel]; | ||
if (isFieldDef(channelDef)) { | ||
const legendSpec = channelDef.legend; | ||
if (legendSpec !== null && legendSpec !== false) { | ||
_legend[channel] = {...legendSpec}; | ||
if (channelDef) { | ||
const legend = isFieldDef(channelDef) ? channelDef.legend : | ||
(channelDef.condition && isFieldDef(channelDef.condition)) ? channelDef.condition.legend : null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, here, rather than multiple ternaries depending on where the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to #1980 (comment), TS won't know that this is a |
||
|
||
if (legend !== null && legend !== false) { | ||
_legend[channel] = {...legend}; | ||
} | ||
} | ||
|
||
return _legend; | ||
}, {}); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ export type Condition<T> = { | |
* ... | ||
* } | ||
*/ | ||
export type ConditionalFieldDef<F, V> = F & {condition?: Condition<V>}; | ||
export type ConditionalFieldDef<F extends FieldDef<any>, V extends ValueDef<any>> = F & {condition?: Condition<V>}; | ||
|
||
/** | ||
* A ValueDef with Condition<ValueDef | FieldDef> | ||
|
@@ -55,7 +55,7 @@ export type ConditionalFieldDef<F, V> = F & {condition?: Condition<V>}; | |
* value: ..., | ||
* } | ||
*/ | ||
export type ConditionalValueDef<F, V> = V & {condition?: Condition<F | V>}; | ||
export type ConditionalValueDef<F extends FieldDef<any>, V extends ValueDef<any>> = V & {condition?: Condition<F | V>}; | ||
|
||
/** | ||
* Reference to a repeated value. | ||
|
@@ -173,7 +173,18 @@ export interface TextFieldDef<F> extends FieldDef<F> { | |
|
||
export type ConditionalTextDef<F> = Conditional<TextFieldDef<F>, ValueDef<string|number|boolean>>; | ||
|
||
export type ChannelDef<F> = FieldDef<F> | ValueDef<any>; | ||
export type ChannelDef<F> = Conditional<FieldDef<F>, ValueDef<any>>; | ||
|
||
export function isConditionalDef<F>(channelDef: ChannelDef<F>): channelDef is Conditional<FieldDef<F>, ValueDef<any>> { | ||
return !!channelDef && !!channelDef.condition; | ||
} | ||
|
||
/** | ||
* Return if a channelDef is a ConditionalValueDef with ConditionFieldDef | ||
*/ | ||
export function hasConditionFieldDef<F>(channelDef: ChannelDef<F>): channelDef is (ValueDef<any> & {condition: FieldDef<F>}) { | ||
return !!channelDef && !!channelDef.condition && isFieldDef(channelDef.condition); | ||
} | ||
|
||
export function isFieldDef<F>(channelDef: ChannelDef<F>): channelDef is FieldDef<F> | PositionFieldDef<F> | LegendFieldDef<F, any> | OrderFieldDef<F> | TextFieldDef<F> { | ||
return !!channelDef && (!!channelDef['field'] || channelDef['aggregate'] === 'count'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Relatedly, I see that several There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, say a channelDef could be
(1 & 2 are
(3-5 are
(6-7 are
On the other hand, In a way, getFieldDef is more like If you have better name suggestions, let me know :) |
||
|
@@ -296,13 +307,32 @@ export function defaultType(fieldDef: FieldDef<Field>, channel: Channel): Type { | |
} | ||
} | ||
|
||
/** | ||
* Returns the fieldDef -- either from the outer channelDef or from the condition of channelDef. | ||
* @param channelDef | ||
*/ | ||
export function getFieldDef<F>(channelDef: ChannelDef<F>): FieldDef<F> { | ||
if (isFieldDef(channelDef)) { | ||
return channelDef; | ||
} else if (hasConditionFieldDef(channelDef)) { | ||
return channelDef.condition; | ||
} | ||
return undefined; | ||
} | ||
|
||
/** | ||
* Convert type to full, lowercase type, or augment the fieldDef with a default type if missing. | ||
*/ | ||
export function normalize(channelDef: ChannelDef<string>, channel: Channel) { | ||
export function normalize(channelDef: ChannelDef<string>, channel: Channel): ChannelDef<any> { | ||
// If a fieldDef contains a field, we need type. | ||
if (isFieldDef(channelDef)) { | ||
return normalizeFieldDef(channelDef, channel); | ||
} else if (hasConditionFieldDef(channelDef)) { | ||
return { | ||
...channelDef, | ||
// Need to cast as normalizeFieldDef normally return FieldDef, but here we know that it is definitely Condition<FieldDef> | ||
condition: normalizeFieldDef(channelDef.condition, channel) as Condition<FieldDef<string>> | ||
}; | ||
} | ||
return channelDef; | ||
} | ||
|
@@ -347,7 +377,6 @@ export function normalizeFieldDef(fieldDef: FieldDef<string>, channel: Channel) | |
log.warn(warning); | ||
} | ||
return fieldDef; | ||
|
||
} | ||
|
||
export function normalizeBin(bin: Bin|boolean, channel: Channel) { | ||
|
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.
Could these first two branches be consolidated using the new
getFieldDef
method?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.
Yeah I tried this earlier too. However, TypeScript won't know that
channelDef.condition
is not only aFieldDef
, but also aScaleFieldDef
. So we either have to do type casting or have to do this and I generally prefer to avoid casting.