Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ export default defineComponent({
if (!props.attribute.user && track.attributes[props.attribute.name]) {
valueMap[track.attributes[props.attribute.name] as string] = true;
} else if (props.attribute.user && track.attributes.userAttributes) {
const userAttr = (track.attributes.userAttributes[user]) as StringKeyObject;
if (userAttr[props.attribute.name]) {
const userAttr = track.attributes.userAttributes[user] as StringKeyObject | undefined;
if (userAttr && userAttr[props.attribute.name]) {
valueMap[userAttr[props.attribute.name] as string] = true;
}
}
Expand All @@ -63,8 +63,8 @@ export default defineComponent({
if (!props.attribute.user && feature.attributes[props.attribute.name]) {
valueMap[feature.attributes[props.attribute.name] as string] = true;
} else if (props.attribute.user && feature.attributes.userAttributes) {
const userAttr = (feature.attributes.userAttributes[user]) as StringKeyObject;
if (userAttr[props.attribute.name]) {
const userAttr = feature.attributes.userAttributes[user] as StringKeyObject | undefined;
if (userAttr && userAttr[props.attribute.name]) {
valueMap[userAttr[props.attribute.name] as string] = true;
}
}
Expand Down
18 changes: 17 additions & 1 deletion client/src/layers/AnnotationLayers/AttributeLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,20 +353,36 @@ export default class AttributeLayer extends BaseLayer<AttributeTextData> {
this.renderAttributes = attributes;
this.user = user;
this.autoColorIndex = [];
const getMissingValueColor = (attribute: Attribute) => {
if (attribute.noneColor) {
return attribute.noneColor;
}
return attribute.valueColors?.[''];
};
// We create the color formatter for the render attributesW
this.renderAttributes.forEach((item) => {
if (item.datatype === 'text') {
this.autoColorIndex.push((data: string | number | boolean) => {
if (data === undefined || data === null || data === '') {
return getMissingValueColor(item) || item.color || 'white';
}
if (item.staticColor) {
return item.color || 'white';
}
if (item.valueColors && Object.keys(item.valueColors).length) {
return item.valueColors[data as string] || item.color || 'white';
}
return item.color || 'white';
});
} else if (item.datatype === 'number') {
this.autoColorIndex.push((data: string | number | boolean) => {
if (data === undefined || data === null || data === '') {
return getMissingValueColor(item) || item.color || 'white';
}
if (item.valueColors && Object.keys(item.valueColors).length) {
const colorArr = Object.entries(item.valueColors as Record<string, string>)
.map(([key, val]) => ({ key: parseFloat(key), val }));
.map(([key, val]) => ({ key: parseFloat(key), val }))
.filter((entry) => !Number.isNaN(entry.key));
colorArr.sort((a, b) => a.key - b.key);

const colorNums = colorArr.map((map) => map.key);
Expand Down
32 changes: 27 additions & 5 deletions client/src/use/useAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default function UseAttributes(
login,
}: UseAttributesParams,
) {
function getMissingValueColor(attribute?: Attribute) {
return attribute?.valueColors?.[''];
}

const attributes: Ref<Record<string, Attribute>> = ref({});
const attributeFilters: Ref<AttributeFilter[]> = ref([]);
const timelineGraphs: Ref<Record<string, TimelineGraph & {filtered?: boolean}>> = ref({});
Expand Down Expand Up @@ -490,28 +494,46 @@ export default function UseAttributes(
return null;
});

const getAttributeValueColor = (attribute: Attribute, val: string) => {
const getAttributeValueColor = (attribute: Attribute, val?: string | number | boolean) => {
if (val === undefined || val === null || val === '') {
if (attribute.noneColor) {
return attribute.noneColor;
}
return getMissingValueColor(attribute)
|| attribute.color
|| trackStyleManager.typeStyling.value.color(attribute.name);
}
if (attribute.datatype === 'text') {
if (attribute.staticColor) {
if (attribute.color) {
return attribute.color;
}
return trackStyleManager.typeStyling.value.color(attribute.name);
}
if (attribute.valueColors && attribute.valueColors[val]) {
return attribute.valueColors[val];
const strVal = val.toString();
if (attribute.valueColors && attribute.valueColors[strVal]) {
return attribute.valueColors[strVal];
}
}
return trackStyleManager.typeStyling.value.color(val);
return trackStyleManager.typeStyling.value.color(val.toString());
};

const numericalColorScaling = computed(() => {
const autoColorIndex: Record<string, (data: string | number | boolean) => string> = {};
Object.entries(attributes.value).forEach(([baseKey, item]) => {
autoColorIndex[baseKey] = ((data: string | number | boolean) => {
if (data === undefined || data === null || data === '') {
if (item.noneColor) {
return item.noneColor;
}
return getMissingValueColor(item)
|| item.color
|| trackStyleManager.typeStyling.value.color(item.name);
}
if (item.datatype === 'number' && item.valueColors && Object.keys(item.valueColors).length) {
const colorArr = Object.entries(item.valueColors as Record<string, string>)
.map(([key, val]) => ({ key: parseFloat(key), val }));
.map(([key, val]) => ({ key: parseFloat(key), val }))
.filter((entry) => !Number.isNaN(entry.key));
colorArr.sort((a, b) => a.key - b.key);

const colorNums = colorArr.map((map) => map.key);
Expand Down
1 change: 1 addition & 0 deletions docs/UI-AttributeRendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Under the Rendering Tab for the Attribute Editor if you turn on Render there wil
* **Value**
* *Value Text Size* - Text size in pixel for the value. This will remain constant when scrolling in/out of the track.
* *Value Color* - Text color for the display text. If set to auto it will utilize the attribute color. If Auto is turned off you can set a custom display text color.
* For text attributes with Value Color set to auto, colors follow Attribute Value Colors behavior (None Color for empty/missing values, Static Color for non-empty values when enabled, otherwise per-value mappings).
* **Dimensions**
* *% Type* - For width and height it will size the area for the attribute based on the track width/height.
* *px Type* - It will size the dimension of the width/height in pixels. This is useful if you have tracks of varying sizes and always want the attributes to fit properly.
Expand Down
6 changes: 6 additions & 0 deletions docs/UI-AttributeSwimlanes.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ Simply use the key filter to select the attributes you whish to graph and config

If you are creating a swimlane for a numerical attribute, utilize the value colors to create a color gradient which can be used to represent the values.

For text attributes in swimlanes, color resolution follows the Attribute Value Colors settings:

1. Missing (`undefined`/`null`) or empty (`''`) values use **None Color** when enabled.
1. If **Static Color** is enabled, non-empty values use the attribute base color.
1. Otherwise, per-value text color mappings are used.

## Swimlane Key

![Swimlane Key](images/AttributeTimeline/SwimlaneKey.png)
Expand Down
11 changes: 11 additions & 0 deletions docs/UI-Attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ Attributes that are of type text can have their colors preset and saved in the c

These colors can be used in the Attribute Rendering or the Swimlane views for attributes to properly render the system.

For text attributes, color selection follows this order:

1. If the value is missing (`undefined`/`null`) or empty (`''`), use **None Color** when enabled.
1. If the value is empty (`''`) and a color is set for the empty string key in Value Colors, that color can be used when None Color is not set.
1. If **Static Color** is enabled, all non-empty text values use the attribute base color.
1. Otherwise, per-value color mappings are used.

!!! info

Empty/missing aliases like `NA`, `N/A`, or `__EMPTY__` are not used for automatic empty handling. Use **None Color** and/or the empty string (`''`) value key.

![Edit Attribute Value Number Colors](images/Attributes/AttributeValueNumberColors.png)

Added the capability to create color gradients for Attribute Values. This will allow numerical values to have custom color gradients which can be used in swimlanes, or in displaying the values of attributes as well.
Expand Down
Loading