|
1 | 1 | <script setup lang="ts">
|
2 | 2 | import { ref, computed, watch, onMounted } from 'vue';
|
| 3 | +import VegaLite from './VegaLite.vue'; |
3 | 4 | import {
|
4 | 5 | type ParsedUDIGrammar,
|
5 | 6 | type UDIGrammar,
|
6 | 7 | parseSpecification,
|
7 | 8 | } from './Parser';
|
8 | 9 | import { useDataSourcesStore } from '@/stores/DataSourcesStore';
|
| 10 | +import { storeToRefs } from 'pinia'; |
9 | 11 |
|
10 | 12 | const dataSourcesStore = useDataSourcesStore();
|
| 13 | +const { loading } = storeToRefs(dataSourcesStore); |
11 | 14 |
|
12 | 15 | export interface ParserProps {
|
13 | 16 | spec: UDIGrammar;
|
14 | 17 | }
|
15 | 18 |
|
| 19 | +// TODO: infer based on data, or assume schema |
| 20 | +const columnTypes = { |
| 21 | + species: 'nominal', |
| 22 | + island: 'nominal', |
| 23 | + bill_length_mm: 'quantitative', |
| 24 | + bill_depth_mm: 'quantitative', |
| 25 | + flipper_length_mm: 'quantitative', |
| 26 | + body_mass_g: 'quantitative', |
| 27 | + sex: 'nominal', |
| 28 | +}; |
| 29 | +
|
16 | 30 | const props = defineProps<ParserProps>();
|
17 | 31 |
|
18 | 32 | const parsedSpec = ref<ParsedUDIGrammar | null>(null);
|
19 | 33 |
|
| 34 | +const isGoGComponent = ref<boolean>(false); |
| 35 | +const vegaLiteSpec = ref<string>(''); |
20 | 36 | onMounted(() => {
|
21 | 37 | // parse/validate grammar
|
22 | 38 | parsedSpec.value = parseSpecification(props.spec);
|
23 | 39 | for (const dataSource of parsedSpec.value.dataSource) {
|
24 | 40 | dataSourcesStore.initDataSource(dataSource);
|
25 | 41 | }
|
| 42 | + buildVisualization(); |
| 43 | +
|
| 44 | + // if (isVegaLiteCompatible(parsedSpec.value)) { |
| 45 | + // vegaLiteSpec.value = convertToVegaSpec(parsedSpec.value); |
| 46 | + // isGoGComponent.value = true; |
| 47 | + // } |
26 | 48 | });
|
| 49 | +
|
| 50 | +watch(loading, () => buildVisualization()); |
| 51 | +
|
| 52 | +function buildVisualization(): void { |
| 53 | + console.log('build vis'); |
| 54 | + // // parse/validate grammar |
| 55 | + // parsedSpec.value = parseSpecification(props.spec); |
| 56 | + // for (const dataSource of parsedSpec.value.dataSource) { |
| 57 | + // dataSourcesStore.initDataSource(dataSource); |
| 58 | + // } |
| 59 | +
|
| 60 | + if (isVegaLiteCompatible(parsedSpec.value)) { |
| 61 | + vegaLiteSpec.value = convertToVegaSpec(parsedSpec.value); |
| 62 | + isGoGComponent.value = true; |
| 63 | + } |
| 64 | +} |
| 65 | +
|
| 66 | +function isVegaLiteCompatible(spec: ParsedUDIGrammar): boolean { |
| 67 | + return Array.isArray(spec.dataRepresentation); |
| 68 | +} |
| 69 | +
|
| 70 | +function convertToVegaSpec(spec: ParsedUDIGrammar): string { |
| 71 | + const vegaSpec = { |
| 72 | + $schema: 'https://vega.github.io/schema/vega-lite/v5.json', |
| 73 | + // data: { url: './data/penguins.csv' }, |
| 74 | + data: { values: [] }, |
| 75 | + }; |
| 76 | +
|
| 77 | + // add data |
| 78 | + // TODO: assume one data source |
| 79 | + const dataInterface = spec.dataSource[0]; |
| 80 | + vegaSpec.data.values = dataSourcesStore.getDataObject(dataInterface.key); |
| 81 | + console.log(vegaSpec); |
| 82 | + // TODO: perform transformations |
| 83 | +
|
| 84 | + // dataInterface. |
| 85 | +
|
| 86 | + // add layers |
| 87 | + const inputLayers = spec.dataRepresentation; |
| 88 | + if (!Array.isArray(inputLayers)) { |
| 89 | + throw new Error('invalid spec passed to vega conversion'); |
| 90 | + } |
| 91 | + const outputLayers = inputLayers.map((gogComponent) => { |
| 92 | + let encoding = {}; |
| 93 | + for (let [key, value] of Object.entries(gogComponent.encoding)) { |
| 94 | + encoding[key] = { |
| 95 | + field: value.field, |
| 96 | + type: columnTypes[value.field], |
| 97 | + }; |
| 98 | + } |
| 99 | + return { |
| 100 | + mark: gogComponent.mark, |
| 101 | + encoding, |
| 102 | + }; |
| 103 | + }); |
| 104 | + vegaSpec['layer'] = outputLayers; |
| 105 | +
|
| 106 | + return JSON.stringify(vegaSpec); |
| 107 | +} |
27 | 108 | </script>
|
28 | 109 |
|
29 | 110 | <template>
|
30 | 111 | <div>Blargen Flargen</div>
|
31 | 112 | <div>{{ props.spec }}</div>
|
| 113 | + <VegaLite v-if="isGoGComponent" :spec="vegaLiteSpec" /> |
32 | 114 | </template>
|
33 | 115 |
|
34 | 116 | <style scoped lang="scss"></style>
|
0 commit comments