adds charts panel

This commit is contained in:
2025-02-15 15:42:33 -08:00
parent 69c0b0965d
commit e9751c2489
16 changed files with 600 additions and 42 deletions

View File

@@ -0,0 +1,50 @@
<script setup lang="ts">
defineProps<{
icon: string;
}>();
</script>
<template>
<i :class="`icon ${icon}`"></i>
</template>
<style scoped lang="scss">
@use '@/assets/variables';
.icon {
display: inline-block;
height: 1em;
}
.icon:before {
display: inline-block;
content: ' ';
background-color: variables.$text-color;
mask-size: cover;
width: 1em;
height: 1em;
}
.icon.hamburger.menu:before {
mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9IjAgMCAxMCAxMCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlV2lkdGg9IjFweCI+PGxpbmUgeDE9IjAiIHkxPSIxIiB4Mj0iMTAiIHkyPSIxIj48L2xpbmU+PGxpbmUgeDE9IjAiIHkxPSI1IiB4Mj0iMTAiIHkyPSI1Ij48L2xpbmU+PGxpbmUgeDE9IjAiIHkxPSI5IiB4Mj0iMTAiIHkyPSI5Ij48L2xpbmU+PC9zdmc+IA==');
}
.icon.close:before {
mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9IjAgMCAxMCAxMCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlV2lkdGg9IjFweCI+PGxpbmUgeDE9IjAiIHkxPSIwIiB4Mj0iMTAiIHkyPSIxMCI+PC9saW5lPjxsaW5lIHgxPSIxMCIgeTE9IjAiIHgyPSIwIiB5Mj0iMTAiPjwvbGluZT48L3N2Zz4g');
}
.icon.up.arrow:before {
mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9IjAgMCAxMCAxMCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlV2lkdGg9IjFweCI+PGxpbmUgeDE9IjAiIHkxPSIxMCIgeDI9IjUiIHkyPSIwIj48L2xpbmU+PGxpbmUgeDE9IjUiIHkxPSIwIiB4Mj0iMTAiIHkyPSIxMCI+PC9saW5lPjwvc3ZnPg==');
}
.icon.down.arrow:before {
mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9IjAgMCAxMCAxMCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlV2lkdGg9IjFweCI+PGxpbmUgeDE9IjAiIHkxPSIwIiB4Mj0iNSIgeTI9IjEwIj48L2xpbmU+PGxpbmUgeDE9IjUiIHkxPSIxMCIgeDI9IjEwIiB5Mj0iMCI+PC9saW5lPjwvc3ZnPg==');
}
/*
<svg xmlns='http://www.w3.org/2000/svg' viewBox="0 0 10 10" stroke="white" strokeWidth="1px">
<line x1="0" y1="0" x2="5" y2="10"></line>
<line x1="5" y1="10" x2="10" y2="0"></line>
</svg>
*/
</style>

View File

@@ -16,6 +16,7 @@ import {
getDurationString,
parseDurationString,
} from '@/datetime';
import { onDocumentShown } from '@/composables/document.ts';
const props = defineProps<{
initial_duration?: number;
@@ -32,7 +33,7 @@ const props = defineProps<{
const divRef = useTemplateRef<HTMLDivElement>('graph-div');
const width = ref(0);
const height = ref(0);
const raw_height = ref(0);
const controls_height = 32;
const min_time_label_separation = 250;
@@ -41,13 +42,18 @@ const resize_observer = new ResizeObserver((elements) => {
for (const element of elements) {
if (element.target == divRef.value) {
width.value = element.contentBoxSize[0].inlineSize;
height.value =
element.contentBoxSize[0].blockSize -
(props.include_controls ? controls_height : 0);
raw_height.value = element.contentBoxSize[0].blockSize;
}
}
});
const height = computed(() => {
return Math.max(
raw_height.value - (props.include_controls ? controls_height : 0),
1,
);
});
watch([divRef], ([divRef]) => {
if (divRef) {
resize_observer.observe(divRef);
@@ -132,6 +138,10 @@ watch([now], ([now_value]) => {
}
});
onDocumentShown(() => {
fetch_history.value++;
});
const max_x_text = computed({
// getter
get() {
@@ -193,8 +203,12 @@ const legend_x_stride = computed(() => 0);
const legend_y_stride = computed(() => 16);
const legend_width_output = computed(() => legend_width - 8);
const graph_width = computed(() => {
return Math.max(width.value - border_left.value - border_right.value, 1);
});
const line_duration = computed(() => {
const width_px = width.value;
const width_px = graph_width.value;
const diff_x = max_x.value - min_x.value;
return time_lines.find((duration) => {
const line_count = diff_x / duration;
@@ -263,8 +277,7 @@ provide<GraphData>(GRAPH_DATA, {
max_temporal_resolution: max_temporal_resolution,
live: live,
fetch_history: fetch_history,
width: () =>
Math.max(width.value - border_left.value - border_right.value, 0),
width: graph_width,
height: () =>
Math.max(height.value - border_top.value - border_bottom.value, 0),
x_map: x_map,

View File

@@ -6,17 +6,35 @@ import Axis from '@/components/GraphAxis.vue';
import { computed } from 'vue';
const props = defineProps<{
telemetry_definition: TelemetryDefinition | null;
secondary: TelemetryDefinition | null;
selection: TelemetryDefinition | null;
mouseover: TelemetryDefinition | null;
}>();
const telemetry_definition = computed(() => {
if (props.mouseover) {
return props.mouseover;
}
return props.selection;
});
const secondary = computed(() => {
if (props.mouseover) {
if (props.selection) {
if (props.selection.uuid != props.mouseover.uuid) {
return props.selection;
}
}
}
return null;
});
const lines = computed(() => {
const result = [];
if (props.secondary) {
result.push(props.secondary);
if (secondary.value) {
result.push(secondary.value);
}
if (props.telemetry_definition) {
result.push(props.telemetry_definition);
if (telemetry_definition.value) {
result.push(telemetry_definition.value);
}
return result;
});

View File

@@ -389,7 +389,7 @@ function onMouseExit(event: MouseEvent) {
</g>
<ValueLabel
v-if="current_data_point"
class="fade_other_selected"
class="fade_other_selected label"
:x="graph_data.x_map(toValue(graph_data.max_x)) + text_offset"
:y="axis_data.y_map(current_data_point.y)"
:value="current_data_point.y"
@@ -473,6 +473,10 @@ function onMouseExit(event: MouseEvent) {
opacity: 25%;
}
.fade .fade_other_selected.label {
opacity: 0;
}
.fade .no-fade .fade_other_selected {
opacity: 100%;
}

View File

@@ -9,11 +9,10 @@ const props = defineProps<{
search?: string;
}>();
const selected = defineModel<TelemetryDefinition | null>();
const emit = defineEmits<{
(
e: 'select',
tlm_entry: [TelemetryDefinition | null, TelemetryDefinition | null],
): void;
(e: 'mouseover', tlm_entry: TelemetryDefinition | null): void;
}>();
const search_value = computed(() => (props.search || '').toLowerCase());
@@ -33,7 +32,6 @@ const sorted_tlm_data = computed(() => {
});
const mousedover = ref<TelemetryDefinition | null>(null);
const selected = ref<TelemetryDefinition | null>(null);
function onMouseover(tlm_entry: TelemetryDefinition) {
mousedover.value = tlm_entry;
@@ -47,17 +45,8 @@ function onClick(tlm_entry: TelemetryDefinition) {
selected.value = tlm_entry;
}
watch([mousedover, selected], ([mousedover_val, selected_val]) => {
if (mousedover_val) {
emit('select', [
mousedover_val,
mousedover_val.uuid != selected_val?.uuid ? selected_val : null,
]);
} else if (selected_val) {
emit('select', [selected_val, null]);
} else {
emit('select', [null, null]);
}
watch([mousedover], ([mousedover_val]) => {
emit('mouseover', mousedover_val);
});
</script>