Fix formatting and add selectedBarIds functionality

This commit is contained in:
Simon Larsen 2024-02-22 13:01:04 +00:00
parent a9293f272b
commit 8689f884bf
No known key found for this signature in database
GPG Key ID: AB45983AA9C81CDE
10 changed files with 88 additions and 21 deletions

View File

@ -31,11 +31,12 @@ export default class Includes extends SerializableObject {
public static override fromJSON(json: JSONObject): Includes { public static override fromJSON(json: JSONObject): Includes {
if (json['_type'] === ObjectType.Includes) { if (json['_type'] === ObjectType.Includes) {
const valuesArray: Array<string> = [];
const valuesArray: Array<string> = []; for (const value of (json['value'] as Array<string>) || []) {
valuesArray.push(
for(const value of json['value'] as Array<string> || []) { JSONFunctions.deserializeValue(value) as string
valuesArray.push(JSONFunctions.deserializeValue(value) as string); );
} }
return new Includes(valuesArray); return new Includes(valuesArray);

View File

@ -37,8 +37,8 @@ export class Statement implements BaseQueryParams {
typeof param === 'string' typeof param === 'string'
? 'Identifier' ? 'Identifier'
: Statement.toColumnType(param); : Statement.toColumnType(param);
return prev + `{p${i - 1}:${dataType}}` + curr; return prev + `{p${i - 1}:${dataType}}` + curr;
} }
); );
@ -105,11 +105,13 @@ export class Statement implements BaseQueryParams {
) { ) {
finalValue = v.value.value; finalValue = v.value.value;
} else if (v.value instanceof Includes) { } else if (v.value instanceof Includes) {
if (v.type === TableColumnType.Text || v.type === TableColumnType.ObjectID) { if (
v.type === TableColumnType.Text ||
v.type === TableColumnType.ObjectID
) {
finalValue = v.value.values.map((val: string | ObjectID) => { finalValue = v.value.values.map((val: string | ObjectID) => {
return `${val.toString()}`; return `${val.toString()}`;
}) });
} else { } else {
finalValue = v.value.values; finalValue = v.value.values;
} }
@ -152,7 +154,9 @@ export class Statement implements BaseQueryParams {
})}`; })}`;
} }
private static toColumnType(statementParam: StatementParameter | string): string { private static toColumnType(
statementParam: StatementParameter | string
): string {
// ensure we have a mapping for all types (a missing mapping will // ensure we have a mapping for all types (a missing mapping will
// be a compile error) // be a compile error)
const columnTypes: Dictionary<string> = { const columnTypes: Dictionary<string> = {
@ -169,11 +173,13 @@ export class Statement implements BaseQueryParams {
[TableColumnType.LongNumber]: 'Int128', [TableColumnType.LongNumber]: 'Int128',
}; };
if((statementParam as StatementParameter).value instanceof Includes){ if ((statementParam as StatementParameter).value instanceof Includes) {
return 'Array(String)'; return 'Array(String)';
} }
return columnTypes[(statementParam as StatementParameter).type] || 'String'; return (
columnTypes[(statementParam as StatementParameter).type] || 'String'
);
} }
} }

View File

@ -405,8 +405,6 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
} }
} }
return whereStatement; return whereStatement;
} }

View File

@ -23,6 +23,9 @@ export interface ComponentProps {
chartTimelineStart: number; chartTimelineStart: number;
chartTimelineEnd: number; chartTimelineEnd: number;
timelineWidth: number; timelineWidth: number;
areOtherBarsSelected: boolean;
onSelect: (barId: string) => void;
onDeselect: (barId: string) => void;
} }
const Bar: FunctionComponent<ComponentProps> = ( const Bar: FunctionComponent<ComponentProps> = (
@ -30,6 +33,8 @@ const Bar: FunctionComponent<ComponentProps> = (
): ReactElement => { ): ReactElement => {
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const [isSelected, setIsSelected] = useState(false);
// calculate bar width. // calculate bar width.
let barWidth: number = let barWidth: number =
((props.bar.barTimelineEnd - props.bar.barTimelineStart) / ((props.bar.barTimelineEnd - props.bar.barTimelineStart) /
@ -61,12 +66,20 @@ const Bar: FunctionComponent<ComponentProps> = (
setIsHovered(false); setIsHovered(false);
}; };
let barOpacity: number = 1;
if(props.areOtherBarsSelected && !isSelected) {
barOpacity = 0.5;
}
return ( return (
// rectangle div with curved corners and text inside in tailwindcss // rectangle div with curved corners and text inside in tailwindcss
<div <div
className="flex absolute" className="flex absolute"
style={{ style={{
marginLeft: `${barLeftPosition}px`, marginLeft: `${barLeftPosition}px`,
}} }}
> >
<div <div
@ -75,9 +88,18 @@ const Bar: FunctionComponent<ComponentProps> = (
marginLeft: `${barLeftPosition}px`, marginLeft: `${barLeftPosition}px`,
width: `${barWidth}px`, width: `${barWidth}px`,
backgroundColor: `${props.bar.barColor.toString()}`, backgroundColor: `${props.bar.barColor.toString()}`,
opacity: barOpacity,
}} }}
onMouseEnter={handleMouseEnter} onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave} onMouseLeave={handleMouseLeave}
onClick={() => {
if (isSelected) {
props.onDeselect(props.bar.id);
} else {
props.onSelect(props.bar.id);
}
setIsSelected(!isSelected);
}}
> >
{!showLabelOutsideBar && ( {!showLabelOutsideBar && (
<BarLabel <BarLabel
@ -96,6 +118,7 @@ const Bar: FunctionComponent<ComponentProps> = (
className="h-8 pt-1 pb-1 mt-2.5 mb-2.5" className="h-8 pt-1 pb-1 mt-2.5 mb-2.5"
style={{ style={{
marginLeft: `${barLeftPosition + barWidth + 10}px`, marginLeft: `${barLeftPosition + barWidth + 10}px`,
opacity: barOpacity,
}} }}
> >
<BarLabel <BarLabel

View File

@ -10,6 +10,7 @@ export interface GanttChartProps {
rows: GanttChartRow[]; rows: GanttChartRow[];
bars: GanttChartBar[]; bars: GanttChartBar[];
timeline: GanttChartTimeline; timeline: GanttChartTimeline;
onBarSelectChange: (barIds: string[]) => void;
} }
export interface ComponentProps { export interface ComponentProps {
@ -21,6 +22,8 @@ const GanttChart: FunctionComponent<ComponentProps> = (
): ReactElement => { ): ReactElement => {
const eachIntervalDefaultWidth: number = 100; // in pixels const eachIntervalDefaultWidth: number = 100; // in pixels
const [selectedBarIds, setSelectedBarIds] = React.useState<string[]>([]);
const [chartWidth, setChartWidth] = React.useState<number>(0); const [chartWidth, setChartWidth] = React.useState<number>(0);
const [timelineWidth, setTimelineWidth] = React.useState<number>(2000); const [timelineWidth, setTimelineWidth] = React.useState<number>(2000);
@ -70,6 +73,11 @@ const GanttChart: FunctionComponent<ComponentProps> = (
chartTimelineStart={props.chart.timeline.start} chartTimelineStart={props.chart.timeline.start}
rows={props.chart.rows} rows={props.chart.rows}
bars={props.chart.bars} bars={props.chart.bars}
selectedBarIds={selectedBarIds}
onBarSelectChange={(barIds: string[]) => {
setSelectedBarIds(barIds);
props.chart.onBarSelectChange(barIds);
}}
/> />
</div> </div>
</ChartContainer> </ChartContainer>

View File

@ -15,6 +15,8 @@ export interface ComponentProps {
chartTimelineStart: number; chartTimelineStart: number;
chartTimelineEnd: number; chartTimelineEnd: number;
timelineWidth: number; timelineWidth: number;
selectedBarIds: string[];
onBarSelectChange: (barIds: string[]) => void;
} }
const Row: FunctionComponent<ComponentProps> = ( const Row: FunctionComponent<ComponentProps> = (
@ -43,6 +45,28 @@ const Row: FunctionComponent<ComponentProps> = (
chartTimelineEnd={props.chartTimelineEnd} chartTimelineEnd={props.chartTimelineEnd}
chartTimelineStart={props.chartTimelineStart} chartTimelineStart={props.chartTimelineStart}
timelineWidth={props.timelineWidth} timelineWidth={props.timelineWidth}
areOtherBarsSelected={props.selectedBarIds.length > 0}
onSelect={(barId: string) => {
// check if the bar is already selected
if (props.selectedBarIds.includes(barId)) {
return;
}
props.onBarSelectChange([...props.selectedBarIds, barId]);
}}
onDeselect={(barId: string) => {
// check if the bar is already selected
if (!props.selectedBarIds.includes(barId)) {
return;
}
props.onBarSelectChange(
props.selectedBarIds.filter((id: string) => {
return id !== barId;
})
);
}}
/> />
); );
})} })}

View File

@ -8,6 +8,8 @@ export interface ComponentProps {
chartTimelineStart: number; chartTimelineStart: number;
chartTimelineEnd: number; chartTimelineEnd: number;
timelineWidth: number; timelineWidth: number;
selectedBarIds: string[];
onBarSelectChange: (barIds: string[]) => void;
} }
const Rows: FunctionComponent<ComponentProps> = ( const Rows: FunctionComponent<ComponentProps> = (
@ -27,6 +29,8 @@ const Rows: FunctionComponent<ComponentProps> = (
bars={props.bars.filter((bar: GanttChartBar) => { bars={props.bars.filter((bar: GanttChartBar) => {
return bar.rowId === row.id; return bar.rowId === row.id;
})} })}
selectedBarIds={props.selectedBarIds}
onBarSelectChange={props.onBarSelectChange}
/> />
); );
})} })}

View File

@ -22,6 +22,9 @@ import DashboardLogsViewer from '../../../../../../Components/LogsViewer/LogsVie
const TraceView: FunctionComponent<PageComponentProps> = ( const TraceView: FunctionComponent<PageComponentProps> = (
_props: PageComponentProps _props: PageComponentProps
): ReactElement => { ): ReactElement => {
const [selectedSpans, setSelectedSpans] = React.useState<string[]>([]);
const oneuptimeSpanId: ObjectID = Navigation.getLastParamAsObjectID(0); const oneuptimeSpanId: ObjectID = Navigation.getLastParamAsObjectID(0);
const telemetryServiceId: ObjectID = Navigation.getLastParamAsObjectID(0); const telemetryServiceId: ObjectID = Navigation.getLastParamAsObjectID(0);
@ -255,6 +258,9 @@ const TraceView: FunctionComponent<PageComponentProps> = (
description: span.spanId!, description: span.spanId!,
}; };
}), }),
onBarSelectChange(barIds: Array<string>) {
setSelectedSpans(barIds);
},
bars: spans.map((span: Span) => { bars: spans.map((span: Span) => {
const spanColor: { const spanColor: {
barColor: Color; barColor: Color;
@ -319,6 +325,7 @@ const TraceView: FunctionComponent<PageComponentProps> = (
noLogsMessage="No logs found for this trace." noLogsMessage="No logs found for this trace."
telemetryServiceIds={[telemetryServiceId]} telemetryServiceIds={[telemetryServiceId]}
traceIds={[traceId]} traceIds={[traceId]}
spanIds={selectedSpans}
enableRealtime={false} enableRealtime={false}
/> />
)} )}

View File

@ -140,9 +140,9 @@ router.post(
span['endTimeUnixNano'] as number span['endTimeUnixNano'] as number
); );
dbSpan.durationUnixNano = span[ dbSpan.durationUnixNano =
'endTimeUnixNano' (span['endTimeUnixNano'] as number) -
] as number - (span['startTimeUnixNano'] as number); (span['startTimeUnixNano'] as number);
dbSpan.name = span['name'] as string; dbSpan.name = span['name'] as string;
dbSpan.kind = dbSpan.kind =

View File

@ -267,7 +267,6 @@ export default class Span extends AnalyticsBaseModel {
}, },
}), }),
new AnalyticsTableColumn({ new AnalyticsTableColumn({
key: 'durationUnixNano', key: 'durationUnixNano',
title: 'Duration in Unix Nano', title: 'Duration in Unix Nano',
@ -588,7 +587,6 @@ export default class Span extends AnalyticsBaseModel {
this.setColumnValue('startTimeUnixNano', v); this.setColumnValue('startTimeUnixNano', v);
} }
public get durationUnixNano(): number | undefined { public get durationUnixNano(): number | undefined {
return this.getColumnValue('durationUnixNano') as number | undefined; return this.getColumnValue('durationUnixNano') as number | undefined;
} }
@ -653,8 +651,6 @@ export default class Span extends AnalyticsBaseModel {
this.setColumnValue('endTime', v); this.setColumnValue('endTime', v);
} }
public get traceId(): string | undefined { public get traceId(): string | undefined {
return this.getColumnValue('traceId') as string | undefined; return this.getColumnValue('traceId') as string | undefined;
} }