Skip to content

Commit

Permalink
182089941 add log strings graph (#1400)
Browse files Browse the repository at this point in the history
* Adds uuid library for session key in logging

Initial commit of event logging

* Logs component title change, create or show component, component closed
Adds document metadata to document model properties
Log message now has document title as activity property value.

* Clean up some of the changes for getting document title from V2 documents to Logger.

* removes metadata property from document model since we are storing that information in `properties` prop

* Clean up logger code. Adds a error catcher when logger is not initialized.

Fixes logger jest tests and skips some of them.

Adds xhr-mock for jest test.

Temporarily removes logger.debug.test

* Adds log string to calculator

* Adds console log of string sent to log server

* Adds event_value prop to the log.

Adds log to some case table actions

* Uses the new implemention of sending log messages throught the model.applyModelChanges

* Adds `event-value` to the log props

* Change incorrect model to apply changes to for logging

* Adds logs to graph parent visibility and show measures toggle

Adds logs for graph background and point color change

* Removes uuid library

* Adds logging for graph adornment checkbox

Adds logging for graph  adornments:
movable point adornment, movable value, plotted function formula

* Removes uuid

Adds undo/redo to cases expand/collapse cases

Move graph transparency and background color apply model change to the point format palette

Fixes logic for logging parent toggle and measures for selection

* Removed unused logger types

* Changes the ILogMessage type

* Changes  log `event_value` to string, and `parameters` to Record <string, unknown>

Adds use logging context to be able to pass info from one component to another for logging.

Moves logging for plotted function from plotted-function-formula-adapter to plotted-function-adornment-banner

Moves logging cell edits from cell-text-editor to use-rows

Changes logging `args` to keys: string[], and values: unknown[]

* Removes logging for cell text changes until further investigation

* Clean up merge errors in attribute-menu-list

* Remove logging from plotted function formula adapter

Update ILogMessage type to use object instead arrays of keys and values

* Adds logging to graph events:
- toggle lsrl
- drag numeric axis
- drag catogorical axis labels
- bin drag to change width
- rescale axis from data
- changes to bin width in graph inspector palette

* Updates and adds graph event logging

* Update log messages to use arg objects instead of keys and values arrays.

* Adds logging for:

swapping category legend order

Changing point color

Hide/show graph points

graph axis attribute change

* REmove unused variable

* Add back axis utils missing variable

* chore: code review suggestions

* chore: code review suggestions

* add back missing function import

---------

Co-authored-by: Kirk Swenson <[email protected]>
  • Loading branch information
eireland and kswenson authored Aug 16, 2024
1 parent 11065cd commit e1befa2
Show file tree
Hide file tree
Showing 19 changed files with 275 additions and 136 deletions.
1 change: 1 addition & 0 deletions v3/src/components/axis/axis-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export interface DragInfo {
initialOffset: number
currentOffset: number
currentDragPosition: number
currentDragPositionCatName: string
categorySet?: ICategorySet
categories: string[]
bandwidth: number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {observer} from "mobx-react-lite"
import React, {useEffect, useRef} from "react"
import {reaction} from "mobx"
import {drag, ScaleContinuousNumeric, select} from "d3"
import { logStringifiedObjectMessage } from "../../../lib/log-message"
import { t } from "../../../utilities/translation/translate"
import {RectIndices, selectDragRects} from "../axis-types"
import {useAxisLayoutContext} from "../models/axis-layout-context"
Expand Down Expand Up @@ -117,7 +118,8 @@ export const NumericAxisDragRects = observer(
axisModel.applyModelChange(
() => axisModel.setDomain(...axisModel.domain), {
undoStringKey: dilating ? "DG.Undo.axisDilate" : "DG.Undo.axisDrag",
redoStringKey: dilating ? "DG.Redo.axisDilate" : "DG.Redo.axisDrag"
redoStringKey: dilating ? "DG.Redo.axisDilate" : "DG.Redo.axisDrag",
log: logStringifiedObjectMessage("dragEnd: %@", {lower: axisModel.domain[0], upper: axisModel.domain[1]})
})
dragging = false
dilating = false
Expand Down
13 changes: 12 additions & 1 deletion v3/src/components/axis/hooks/use-sub-axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { EmptyAxisHelper } from "../helper-models/axis-helper"
import { NumericAxisHelper } from "../helper-models/numeric-axis-helper"
import { CatObject, CategoricalAxisHelper } from "../helper-models/categorical-axis-helper"
import { DateAxisHelper } from "../helper-models/date-axis-helper"
import { logMessageWithReplacement } from "../../../lib/log-message"

export interface IUseSubAxis {
subAxisIndex: number
Expand Down Expand Up @@ -51,6 +52,7 @@ export const useSubAxis = ({
initialOffset: 0,
currentOffset: 0,
currentDragPosition: 0,
currentDragPositionCatName: '',
categories: [],
bandwidth: 0,
axisOrientation: 'horizontal',
Expand Down Expand Up @@ -136,6 +138,7 @@ export const useSubAxis = ({
: dI.categories[newCatIndex]
dI.indexOfCategory = newCatIndex
dI.categorySet?.move(dI.catName, catToMoveBefore)
dI.currentDragPositionCatName = catToMoveBefore
} else {
renderSubAxis()
}
Expand All @@ -148,7 +151,15 @@ export const useSubAxis = ({
dI.indexOfCategory = -1 // so dragInfo won't influence category placement
stopAnimation() // disable animation for final placement
renderSubAxis()
}, [stopAnimation, renderSubAxis]),
displayModel.applyModelChange(() => {},
{ undoStringKey: "DG.Undo.graph.swapCategories",
redoStringKey: "DG.Redo.graph.swapCategories",
log: logMessageWithReplacement(
"Moved category %@ into position of %@",
{movedCategory: dI.catName, targetCategory: dI.currentDragPositionCatName})
}
)
}, [stopAnimation, renderSubAxis, displayModel]),

dragBehavior = useMemo(() => drag()
.on("start", onDragStart)
Expand Down
200 changes: 106 additions & 94 deletions v3/src/components/data-display/components/legend/categorical-legend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {mstReaction} from "../../../../utilities/mst-reaction"
import {comparer, reaction} from "mobx"
import {drag, range, select} from "d3"
import React, {useCallback, useEffect, useMemo, useRef} from "react"
import { logMessageWithReplacement } from "../../../../lib/log-message"
// import { setOrExtendSelection } from "../../../../models/data/data-set-utils"
import {isSelectionAction} from "../../../../models/data/data-set-actions"
import {missingColor} from "../../../../utilities/color-utils"
Expand Down Expand Up @@ -84,7 +85,7 @@ export const CategoricalLegend = observer(
currentDragPosition: {x: 0, y: 0}
}),
duration = useRef(0)

const prevCategoryIndex = useRef(0)
const
keysElt = useRef(null)

Expand All @@ -101,31 +102,31 @@ export const CategoricalLegend = observer(
}
}, [dataConfiguration])

const computeLayout = useCallback(() => {
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
const numCategories = categoriesRef.current?.length,
lod: Layout = layoutData.current
lod.fullWidth = tileWidth
lod.maxWidth = 0
categoriesRef.current?.forEach(cat => {
lod.maxWidth = Math.max(lod.maxWidth, measureText(cat, kDataDisplayFont))
})
lod.maxWidth += keySize + padding
lod.numColumns = Math.max(Math.floor(lod.fullWidth / lod.maxWidth), 1)
lod.columnWidth = lod.fullWidth / lod.numColumns
lod.numRows = Math.ceil((numCategories ?? 0) / lod.numColumns)
setCategoryData()
layoutData.current = lod
}, [dataConfiguration, setCategoryData, tileWidth])
const computeLayout = useCallback(() => {
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
const numCategories = categoriesRef.current?.length,
lod: Layout = layoutData.current
lod.fullWidth = tileWidth
lod.maxWidth = 0
categoriesRef.current?.forEach(cat => {
lod.maxWidth = Math.max(lod.maxWidth, measureText(cat, kDataDisplayFont))
})
lod.maxWidth += keySize + padding
lod.numColumns = Math.max(Math.floor(lod.fullWidth / lod.maxWidth), 1)
lod.columnWidth = lod.fullWidth / lod.numColumns
lod.numRows = Math.ceil((numCategories ?? 0) / lod.numColumns)
setCategoryData()
layoutData.current = lod
}, [dataConfiguration, setCategoryData, tileWidth])

const computeDesiredExtent = useCallback(() => {
if (dataConfiguration?.placeCanHaveZeroExtent('legend')) {
return 0
}
computeLayout()
const lod = layoutData.current
return lod.numRows * (keySize + padding) + labelHeight + axisGap
}, [computeLayout, dataConfiguration])
const computeDesiredExtent = useCallback(() => {
if (dataConfiguration?.placeCanHaveZeroExtent('legend')) {
return 0
}
computeLayout()
const lod = layoutData.current
return lod.numRows * (keySize + padding) + labelHeight + axisGap
}, [computeLayout, dataConfiguration])

const refreshKeys = useCallback(() => {
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
Expand Down Expand Up @@ -201,81 +202,92 @@ export const CategoricalLegend = observer(
duration.current = 0
}, [])

const onDrag = useCallback((event: { dx: number; dy: number }) => {
if (event.dx !== 0 || event.dy !== 0) {
const dI = dragInfo.current,
lod = layoutData.current,
numCategories = categoriesRef.current?.length ?? 0,
newDragPosition = {
x: dI.currentDragPosition.x + event.dx,
y: dI.currentDragPosition.y + event.dy
},
newCatIndex = coordinatesToCatIndex(lod, numCategories, newDragPosition)
if (newCatIndex >= 0 && newCatIndex !== dI.indexOfCategory) {
// swap the two categories
dataConfiguration?.storeAllCurrentColorsForAttrRole('legend')
dataConfiguration?.swapCategoriesForAttrRole('legend', dI.indexOfCategory, newCatIndex)
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
setCategoryData()
dI.indexOfCategory = newCatIndex
} else {
refreshKeys()
}
dI.currentDragPosition = newDragPosition
const onDrag = useCallback((event: { dx: number; dy: number }) => {
if (event.dx !== 0 || event.dy !== 0) {
const dI = dragInfo.current,
lod = layoutData.current,
numCategories = categoriesRef.current?.length ?? 0,
newDragPosition = {
x: dI.currentDragPosition.x + event.dx,
y: dI.currentDragPosition.y + event.dy
},
newCatIndex = coordinatesToCatIndex(lod, numCategories, newDragPosition)
if (newCatIndex >= 0 && newCatIndex !== dI.indexOfCategory) {
// swap the two categories
dataConfiguration?.storeAllCurrentColorsForAttrRole('legend')
dataConfiguration?.swapCategoriesForAttrRole('legend', dI.indexOfCategory, newCatIndex)
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
setCategoryData()
prevCategoryIndex.current = dI.indexOfCategory
dI.indexOfCategory = newCatIndex
} else {
refreshKeys()
}
}, [dataConfiguration, setCategoryData, refreshKeys])
dI.currentDragPosition = newDragPosition
}
}, [dataConfiguration, setCategoryData, refreshKeys])

const onDragEnd = useCallback(() => {
duration.current = transitionDuration
dragInfo.current.indexOfCategory = -1
refreshKeys()
}, [refreshKeys])
const dragBehavior = useMemo(() => drag<SVGGElement, number>()
.on("start", onDragStart)
.on("drag", onDrag)
.on("end", onDragEnd), [onDrag, onDragEnd, onDragStart])
const setupKeys = useCallback(() => {
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
const numCategories = categoriesRef.current?.length
const hasCategories = !(numCategories === 1 && categoriesRef.current?.[0] === "__main__")
if (keysElt.current && categoryData.current) {
select(keysElt.current).selectAll('legend-key').remove() // start fresh
const onDragEnd = useCallback(() => {
duration.current = transitionDuration
dragInfo.current.indexOfCategory = -1
refreshKeys()

dataConfiguration?.applyModelChange(() => {}, {
undoStringKey: 'DG.Undo.graph.swapCategories',
redoStringKey: 'DG.Redo.graph.swapCategories',
log: logMessageWithReplacement(
"Moved category %@ into position of %@",
{ movedCategory: categoriesRef.current?.[dragInfo.current.indexOfCategory],
targetCategory: categoriesRef.current?.[prevCategoryIndex.current] })
})
}, [dataConfiguration, refreshKeys])

const dragBehavior = useMemo(() => drag<SVGGElement, number>()
.on("start", onDragStart)
.on("drag", onDrag)
.on("end", onDragEnd), [onDrag, onDragEnd, onDragStart])
const setupKeys = useCallback(() => {
categoriesRef.current = dataConfiguration?.categoryArrayForAttrRole('legend')
const numCategories = categoriesRef.current?.length
const hasCategories = !(numCategories === 1 && categoriesRef.current?.[0] === "__main__")
if (keysElt.current && categoryData.current) {
select(keysElt.current).selectAll('legend-key').remove() // start fresh

if (hasCategories) {
const keysSelection = select(keysElt.current)
.selectAll<SVGGElement, number>('g')
.data(range(0, numCategories ?? 0))
.join(
enter => enter
.append('g')
.attr('class', 'legend-key')
.attr('data-testid', 'legend-key')
.call(dragBehavior)
)
keysSelection.each(function () {
const sel = select<SVGGElement, number>(this),
size = sel.selectAll<SVGRectElement, number>('rect').size()
if (size === 0) {
const handleClick = (event: any, i: number) => {
const caseIds = dataConfiguration?.getCasesForLegendValue(categoryData.current[i].category)
if (caseIds) {
// This is breaking the graph-legend cypress test
// setOrExtendSelection(caseIds, dataConfiguration?.dataset, event.shiftKey)
if (event.shiftKey) dataConfiguration?.dataset?.selectCases(caseIds)
else dataConfiguration?.dataset?.setSelectedCases(caseIds)
}
if (hasCategories) {
const keysSelection = select(keysElt.current)
.selectAll<SVGGElement, number>('g')
.data(range(0, numCategories ?? 0))
.join(
enter => enter
.append('g')
.attr('class', 'legend-key')
.attr('data-testid', 'legend-key')
.call(dragBehavior)
)
keysSelection.each(function () {
const sel = select<SVGGElement, number>(this),
size = sel.selectAll<SVGRectElement, number>('rect').size()
if (size === 0) {
const handleClick = (event: any, i: number) => {
const caseIds = dataConfiguration?.getCasesForLegendValue(categoryData.current[i].category)
if (caseIds) {
// This is breaking the graph-legend cypress test
// setOrExtendSelection(caseIds, dataConfiguration?.dataset, event.shiftKey)
if (event.shiftKey) dataConfiguration?.dataset?.selectCases(caseIds)
else dataConfiguration?.dataset?.setSelectedCases(caseIds)
}
sel.append('rect')
.attr('width', keySize)
.attr('height', keySize)
.on('click', handleClick)
sel.append('text')
.on('click', handleClick)
}
})
}
sel.append('rect')
.attr('width', keySize)
.attr('height', keySize)
.on('click', handleClick)
sel.append('text')
.on('click', handleClick)
}
})
}
}, [dataConfiguration, dragBehavior])
}
}, [dataConfiguration, dragBehavior])

useEffect(function respondToSelectionChange() {
return onAnyAction(dataset, action => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ export const DisplayItemFormatControl = observer(function PointFormatControl(pro
() => displayItemDescription.setPointSizeMultiplier(val),
{
undoStringKey: "DG.Undo.graph.changePointSize",
redoStringKey: "DG.Redo.graph.changePointSize"
redoStringKey: "DG.Redo.graph.changePointSize",
log: "Changed point size"
}
)
}}
Expand Down Expand Up @@ -117,7 +118,8 @@ export const DisplayItemFormatControl = observer(function PointFormatControl(pro
() => displayItemDescription.setPointStrokeColor(e.target.value),
{
undoStringKey: "DG.Undo.graph.changeStrokeColor",
redoStringKey: "DG.Redo.graph.changeStrokeColor"
redoStringKey: "DG.Redo.graph.changeStrokeColor",
log: "Changed stroke color"
}
)
}}/>
Expand Down Expand Up @@ -150,7 +152,8 @@ export const DisplayItemFormatControl = observer(function PointFormatControl(pro
() => displayItemDescription.setPointColor(e.target.value),
{
undoStringKey: "DG.Undo.graph.changePointColor",
redoStringKey: "DG.Redo.graph.changePointColor"
redoStringKey: "DG.Redo.graph.changePointColor",
log: attrType === "categorical" ? "Changed categorical point color" : "Changed point color"
}
)
}}/>
Expand All @@ -166,7 +169,8 @@ export const DisplayItemFormatControl = observer(function PointFormatControl(pro
() => displayItemDescription.setPointStrokeSameAsFill(e.target.checked),
{
undoStringKey: "DG.Undo.graph.changeStrokeColor",
redoStringKey: "DG.Redo.graph.changeStrokeColor"
redoStringKey: "DG.Redo.graph.changeStrokeColor",
log: "Changed stroke color"
}
)
}}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useCallback, useEffect, useRef } from "react"
import { observer } from "mobx-react-lite"
import { drag, select, Selection } from "d3"
import { LogMessageFn, logModelChangeFn } from "../../../../lib/log-message"
import { t } from "../../../../utilities/translation/translate"
import { mstAutorun } from "../../../../utilities/mst-autorun"
import { mstReaction } from "../../../../utilities/mst-reaction"
import { safeGetSnapshot } from "../../../../utilities/mst-utils"
import { Point } from "../../../data-display/data-display-types"
import { IAxisIntercepts, calculateSumOfSquares, curveBasis, lineToAxisIntercepts,
lsrlEquationString } from "../../utilities/graph-utils"
Expand Down Expand Up @@ -53,6 +55,7 @@ export const LSRLAdornment = observer(function LSRLAdornment(props: IAdornmentCo
const lineRef = useRef() as React.RefObject<SVGSVGElement>
const lineObjectsRef = useRef<ILineObject[]>([])
const pointsOnAxes = useRef<IAxisIntercepts>({pt1: {x: 0, y: 0}, pt2: {x: 0, y: 0}})
const logFn = useRef<Maybe<LogMessageFn>>()

const getLines = useCallback(() => {
return dataConfig && model.getLines(xAttrId, yAttrId, cellKey, dataConfig, interceptLocked)
Expand Down Expand Up @@ -112,7 +115,8 @@ export const LSRLAdornment = observer(function LSRLAdornment(props: IAdornmentCo
() => lines?.[lineIndex]?.setEquationCoords({x: left, y: top}),
{
undoStringKey: "DG.Undo.graph.repositionEquation",
redoStringKey: "DG.Redo.graph.repositionEquation"
redoStringKey: "DG.Redo.graph.repositionEquation",
log: logFn.current
}
)
}
Expand Down Expand Up @@ -315,7 +319,13 @@ export const LSRLAdornment = observer(function LSRLAdornment(props: IAdornmentCo

const equation = equationDiv.select<HTMLElement>(`#lsrl-equation-${model.classNameFromKey(cellKey)}-${lineIndex}`)
equation?.call(
drag<HTMLElement, unknown>().on("drag", (e) => handleMoveEquation(e, false, lineIndex))
drag<HTMLElement, unknown>()
.on("start", (e) => {
logFn.current = logModelChangeFn(
"Moved equation from (%@, %@) to (%@, %@)",
() => safeGetSnapshot(lines[lineIndex].equationCoords) ?? { x: "default", y: "default" })
})
.on("drag", (e) => handleMoveEquation(e, false, lineIndex))
.on("end", (e) => handleMoveEquation(e, true, lineIndex))
)
}
Expand Down
Loading

0 comments on commit e1befa2

Please sign in to comment.