terrier-engine 4.32.0 → 4.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data-dive/gen/models.ts +3 -1
- package/data-dive/plots/dive-plot-axes.ts +62 -0
- package/data-dive/plots/dive-plot-editor.ts +33 -7
- package/data-dive/plots/dive-plot-trace.ts +16 -0
- package/data-dive/plots/dive-plots.ts +11 -19
- package/package.json +1 -1
- package/terrier/forms.ts +1 -1
- package/terrier/parts/page-part.ts +2 -4
package/data-dive/gen/models.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// This file was automatically generated on 2024-07-17
|
|
1
|
+
// This file was automatically generated on 2024-07-25 17:02:53 -0500, DO NOT EDIT IT MANUALLY!
|
|
2
2
|
|
|
3
3
|
import { Query } from "../queries/queries"
|
|
4
4
|
|
|
@@ -171,6 +171,7 @@ export type DdDiveRun = {
|
|
|
171
171
|
output_data?: object
|
|
172
172
|
output_file_data?: Attachment | { path: string }
|
|
173
173
|
status: "initial" | "running" | "success" | "error"
|
|
174
|
+
delivery_mode?: string
|
|
174
175
|
delivery_recipients?: string[]
|
|
175
176
|
delivery_data?: object
|
|
176
177
|
created_by?: DdUser
|
|
@@ -194,6 +195,7 @@ export type UnpersistedDdDiveRun = {
|
|
|
194
195
|
output_data?: object
|
|
195
196
|
output_file_data?: Attachment | { path: string }
|
|
196
197
|
status: "initial" | "running" | "success" | "error"
|
|
198
|
+
delivery_mode?: string
|
|
197
199
|
delivery_recipients?: string[]
|
|
198
200
|
delivery_data?: object
|
|
199
201
|
created_by?: DdUser
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {AxisType} from "tuff-plot/axis"
|
|
2
|
+
import {TerrierFormFields} from "../../terrier/forms"
|
|
3
|
+
import {PartTag} from "tuff-core/parts"
|
|
4
|
+
import TerrierPart from "../../terrier/parts/terrier-part"
|
|
5
|
+
import {DbErrors} from "../../terrier/db-client"
|
|
6
|
+
import * as inflection from "inflection"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// let's not worry about a top axis for now
|
|
10
|
+
const axisSides = ['left', 'bottom', 'right'] as const
|
|
11
|
+
export type AxisSide = typeof axisSides[number]
|
|
12
|
+
|
|
13
|
+
export type DivePlotAxisType = AxisType | 'none'
|
|
14
|
+
|
|
15
|
+
export type DivePlotAxis = {
|
|
16
|
+
type: DivePlotAxisType
|
|
17
|
+
title: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const axisTypeOptions = [
|
|
21
|
+
{value: 'none', title: 'None'},
|
|
22
|
+
{value: 'number', title: 'Number'},
|
|
23
|
+
{value: 'time', title: 'Date/Time'},
|
|
24
|
+
{value: 'group', title: 'Grouped Bars'},
|
|
25
|
+
{value: 'stack', title: 'Stacked Bars'},
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
export class DivePlotAxisFields extends TerrierFormFields<DivePlotAxis> {
|
|
29
|
+
|
|
30
|
+
constructor(part: TerrierPart<any>, axis: DivePlotAxis, readonly side: AxisSide, errors?: DbErrors<DivePlotAxis>) {
|
|
31
|
+
super(part, axis, errors)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
render(parent: PartTag) {
|
|
35
|
+
parent.div(`.dd-dive-plot-axis-fields.tt-form.shrink.${this.side}`, container => {
|
|
36
|
+
container.div('.side').text(`${inflection.titleize(this.side)} Axis:`)
|
|
37
|
+
|
|
38
|
+
// title
|
|
39
|
+
this.textInput(container, "title", {placeholder: "Title"})
|
|
40
|
+
|
|
41
|
+
// type
|
|
42
|
+
const typeDir = this.side == 'bottom' ? 'row' : 'column'
|
|
43
|
+
container.div(`.tt-flex.wrapped.small-gap.${typeDir}`, flex => {
|
|
44
|
+
axisTypeOptions.forEach(option => {
|
|
45
|
+
if ((this.side == 'bottom' || this.side == 'left') && option.value == 'none') {
|
|
46
|
+
return // don't let them not have a bottom or left axis
|
|
47
|
+
}
|
|
48
|
+
flex.label(".caption-size", label => {
|
|
49
|
+
this.radio(label, 'type', option.value)
|
|
50
|
+
label.span().text(option.title)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
const DivePlotAxes = {
|
|
60
|
+
axisSides
|
|
61
|
+
}
|
|
62
|
+
export default DivePlotAxes
|
|
@@ -3,12 +3,13 @@ import {ModalPart} from "../../terrier/modals"
|
|
|
3
3
|
import {DiveEditorState} from "../dives/dive-editor"
|
|
4
4
|
import {UnpersistedDdDivePlot} from "../gen/models"
|
|
5
5
|
import {TerrierFormFields} from "../../terrier/forms"
|
|
6
|
-
import {DivePlotTrace} from "./dive-plots"
|
|
7
6
|
import Messages from "tuff-core/messages"
|
|
8
7
|
import {Logger} from "tuff-core/logging"
|
|
9
8
|
import DivePlotList from "./dive-plot-list"
|
|
10
9
|
import Db from "../dd-db"
|
|
11
10
|
import DivePlotRenderPart from "./dive-plot-render-part"
|
|
11
|
+
import {DivePlotAxis, DivePlotAxisFields} from "./dive-plot-axes"
|
|
12
|
+
import {DivePlotTrace} from "./dive-plot-trace"
|
|
12
13
|
|
|
13
14
|
const log = new Logger("DivePlotList")
|
|
14
15
|
|
|
@@ -16,12 +17,13 @@ export type DivePlotEditorState = DiveEditorState & {
|
|
|
16
17
|
plot: UnpersistedDdDivePlot
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
20
|
export default class DivePlotEditor extends ModalPart<DivePlotEditorState> {
|
|
22
21
|
|
|
23
22
|
plot!: UnpersistedDdDivePlot
|
|
24
23
|
fields!: TerrierFormFields<UnpersistedDdDivePlot>
|
|
24
|
+
leftAxisFields!: DivePlotAxisFields
|
|
25
|
+
rightAxisFields!: DivePlotAxisFields
|
|
26
|
+
bottomAxisFields!: DivePlotAxisFields
|
|
25
27
|
traces: DivePlotTrace[] = []
|
|
26
28
|
renderPart!: DivePlotRenderPart
|
|
27
29
|
saveKey = Messages.untypedKey()
|
|
@@ -39,6 +41,15 @@ export default class DivePlotEditor extends ModalPart<DivePlotEditorState> {
|
|
|
39
41
|
|
|
40
42
|
this.fields = new TerrierFormFields<UnpersistedDdDivePlot>(this, this.plot)
|
|
41
43
|
|
|
44
|
+
// axis fields
|
|
45
|
+
const axes = this.plot.layout.axes || {}
|
|
46
|
+
const leftAxis: DivePlotAxis = axes['left'] || {type: 'number', title: ''}
|
|
47
|
+
this.leftAxisFields = new DivePlotAxisFields(this, leftAxis, 'left')
|
|
48
|
+
const rightAxis: DivePlotAxis = axes['right'] || {type: 'none', title: ''}
|
|
49
|
+
this.rightAxisFields = new DivePlotAxisFields(this, rightAxis, 'right')
|
|
50
|
+
const bottomAxis: DivePlotAxis = axes['bottom'] || {type: 'number', title: ''}
|
|
51
|
+
this.bottomAxisFields = new DivePlotAxisFields(this, bottomAxis, 'bottom')
|
|
52
|
+
|
|
42
53
|
this.traces = this.plot.traces || []
|
|
43
54
|
|
|
44
55
|
this.renderPart = this.makePart(DivePlotRenderPart, this.state)
|
|
@@ -57,12 +68,20 @@ export default class DivePlotEditor extends ModalPart<DivePlotEditorState> {
|
|
|
57
68
|
|
|
58
69
|
renderContent(parent: PartTag): void {
|
|
59
70
|
parent.div(".tt-flex.column.padded.gap", mainColumn => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
this.fields.
|
|
71
|
+
|
|
72
|
+
mainColumn.div(".dd-plot-axes-and-preview.tt-flex.column.gap", axesAndPreview => {
|
|
73
|
+
this.fields.compoundField(axesAndPreview, field => {
|
|
74
|
+
field.label(".required").text("Title")
|
|
75
|
+
this.fields.textInput(field, 'title', {class: 'shrink plot-title'})
|
|
76
|
+
}).class('plot-title-field')
|
|
77
|
+
axesAndPreview.div('.tt-flex.gap', row => {
|
|
78
|
+
this.leftAxisFields.render(row)
|
|
79
|
+
row.part(this.renderPart)
|
|
80
|
+
this.rightAxisFields.render(row)
|
|
81
|
+
})
|
|
82
|
+
this.bottomAxisFields.render(axesAndPreview)
|
|
63
83
|
})
|
|
64
84
|
|
|
65
|
-
mainColumn.part(this.renderPart)
|
|
66
85
|
|
|
67
86
|
mainColumn.h3(".glyp-items").text("Traces")
|
|
68
87
|
|
|
@@ -72,6 +91,13 @@ export default class DivePlotEditor extends ModalPart<DivePlotEditorState> {
|
|
|
72
91
|
async save() {
|
|
73
92
|
const plotData = await this.fields.serialize()
|
|
74
93
|
const plot = {...this.plot, title: plotData.title}
|
|
94
|
+
|
|
95
|
+
plot.layout.axes = {
|
|
96
|
+
left: await this.leftAxisFields.serialize(),
|
|
97
|
+
bottom: await this.bottomAxisFields.serialize(),
|
|
98
|
+
right: await this.rightAxisFields.serialize()
|
|
99
|
+
}
|
|
100
|
+
|
|
75
101
|
log.info("Saving plot", plot)
|
|
76
102
|
|
|
77
103
|
const res = await Db().upsert('dd_dive_plot', plot)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {MarkerStyle, TraceStyle, TraceType, YAxisName} from "tuff-plot/trace";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Similar to the tuff-plot Trace but not strongly typed to the data type since it's dynamically assigned to a query.
|
|
5
|
+
*/
|
|
6
|
+
export type DivePlotTrace = {
|
|
7
|
+
id: string
|
|
8
|
+
type: TraceType
|
|
9
|
+
title: string
|
|
10
|
+
query_id: string
|
|
11
|
+
x: string
|
|
12
|
+
y: string
|
|
13
|
+
y_axis: YAxisName
|
|
14
|
+
style?: TraceStyle
|
|
15
|
+
marker?: MarkerStyle
|
|
16
|
+
}
|
|
@@ -1,27 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import {MarkerStyle, TraceStyle, TraceType, YAxisName} from "tuff-plot/trace"
|
|
3
|
-
import {PlotLayout} from "tuff-plot/layout"
|
|
4
1
|
import {DdDive, DdDivePlot} from "../gen/models"
|
|
5
2
|
import Db from "../dd-db"
|
|
3
|
+
import {DivePlotAxis} from "./dive-plot-axes"
|
|
6
4
|
|
|
7
|
-
/**
|
|
8
|
-
* Similar to the tuff-plot Trace but not strongly typed to the data type since it's dynamically assigned to a query.
|
|
9
|
-
*/
|
|
10
|
-
export type DivePlotTrace = {
|
|
11
|
-
id: string
|
|
12
|
-
type: TraceType
|
|
13
|
-
title: string
|
|
14
|
-
query_id: string
|
|
15
|
-
x: string
|
|
16
|
-
y: string
|
|
17
|
-
y_axis: YAxisName
|
|
18
|
-
style?: TraceStyle
|
|
19
|
-
marker?: MarkerStyle
|
|
20
|
-
}
|
|
21
5
|
|
|
22
|
-
//
|
|
23
|
-
export type DivePlotLayout =
|
|
6
|
+
// mimic PlotLayout but with our own types
|
|
7
|
+
export type DivePlotLayout = {
|
|
8
|
+
pad?: number
|
|
9
|
+
axes?: {
|
|
10
|
+
left?: DivePlotAxis
|
|
11
|
+
top?: DivePlotAxis
|
|
12
|
+
right?: DivePlotAxis
|
|
13
|
+
bottom?: DivePlotAxis
|
|
14
|
+
}
|
|
24
15
|
|
|
16
|
+
}
|
|
25
17
|
/**
|
|
26
18
|
* Get all plots for the given dive.
|
|
27
19
|
* @param dive
|
package/package.json
CHANGED
package/terrier/forms.ts
CHANGED
|
@@ -150,7 +150,7 @@ export class TerrierFormFields<T extends FormPartData> extends FormFields<T> {
|
|
|
150
150
|
* @param fun a function that accepts the field as an argument, to actually populate the field
|
|
151
151
|
*/
|
|
152
152
|
compoundField(parent: PartTag, fun: (field: DivTag) => any) {
|
|
153
|
-
parent.div(".tt-compound-field", field => {
|
|
153
|
+
return parent.div(".tt-compound-field", field => {
|
|
154
154
|
fun(field)
|
|
155
155
|
})
|
|
156
156
|
}
|
|
@@ -150,8 +150,6 @@ export default abstract class PagePart<TState> extends ContentPart<TState> {
|
|
|
150
150
|
if (!this._breadcrumbs.length && !this._title?.length) return
|
|
151
151
|
|
|
152
152
|
parent.h1('.breadcrumbs', h1 => {
|
|
153
|
-
const crumbs = Array.from(this._breadcrumbs)
|
|
154
|
-
|
|
155
153
|
// add a breadcrumb for the page title
|
|
156
154
|
if (this._title?.length) {
|
|
157
155
|
const titleCrumb: Action = {
|
|
@@ -164,10 +162,10 @@ export default abstract class PagePart<TState> extends ContentPart<TState> {
|
|
|
164
162
|
if (this._titleClasses?.length) {
|
|
165
163
|
titleCrumb.classes = this._titleClasses
|
|
166
164
|
}
|
|
167
|
-
|
|
165
|
+
this.addBreadcrumb(titleCrumb)
|
|
168
166
|
}
|
|
169
167
|
|
|
170
|
-
this.app.theme.renderActions(h1,
|
|
168
|
+
this.app.theme.renderActions(h1, Array.from(this._breadcrumbs))
|
|
171
169
|
})
|
|
172
170
|
}
|
|
173
171
|
|