Skip to content

Commit 395dc1f

Browse files
committed
Improvement - VueUiDashboard - Add support for custom components
1 parent 4a3857f commit 395dc1f

File tree

3 files changed

+116
-17
lines changed

3 files changed

+116
-17
lines changed

src/SomeTest.vue

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script setup>
2+
import { ref, computed } from "vue";
3+
4+
defineProps({
5+
str: {
6+
type: String,
7+
default: ''
8+
}
9+
})
10+
</script>
11+
12+
<template>
13+
<div :style="{background: 'red', color: 'white'}">
14+
{{ str }}
15+
</div>
16+
</template>

src/TestingArena.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
*/
13-
import { ref, computed, onMounted, nextTick, watch } from "vue";
13+
import { ref, computed, onMounted, nextTick, watch, markRaw } from "vue";
1414
import Box from "./Box.vue";
1515
import BaseIcon from "./atoms/BaseIcon.vue";
1616
import TableTest from "./components/vue-ui-table.vue";
@@ -63,6 +63,7 @@ import TestCursor from "./components/vue-ui-cursor.vue";
6363
import TestTrend from "./components/vue-ui-spark-trend.vue";
6464
import TestStrip from "./components/vue-ui-strip-plot.vue";
6565
import TestDumb from "./components/vue-ui-dumbbell.vue";
66+
import SomeTest from "./SomeTest.vue";
6667
6768
const dataset = ref([
6869
{
@@ -1463,6 +1464,15 @@ const comps = ref([
14631464
component: "VueUiOnion",
14641465
props: { config: { userOptions: { show: false } }, dataset: onionDataset },
14651466
},
1467+
{
1468+
id: 3,
1469+
width: 20,
1470+
height: 60,
1471+
left: 44,
1472+
top: 50,
1473+
component: markRaw(SomeTest),
1474+
props: { str: 'SOME TEST' },
1475+
},
14661476
]);
14671477
14681478
function testchange(el) {

src/components/vue-ui-dashboard.vue

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,71 @@
11
<script setup>
2-
import { ref, watch, computed } from 'vue';
2+
import { ref, watch, computed, defineAsyncComponent } from 'vue';
33
import pdf from '../pdf';
44
import { useNestedProp } from "../useNestedProp";
55
import { useConfig } from '../useConfig';
66
import { createUid } from '../lib';
77
8-
// TODO: prevent default on all chart interactions involving mouse movements
9-
// TODO: find a way to make height of each item fit the content
8+
const builtInComponents = {
9+
VueDataUi : defineAsyncComponent(() => import("../components/vue-data-ui.vue")),
10+
VueUi3dBar : defineAsyncComponent(() => import("../components/vue-ui-3d-bar.vue")),
11+
VueUiAccordion : defineAsyncComponent(() => import("../components/vue-ui-accordion.vue")),
12+
VueUiAgePyramid : defineAsyncComponent(() => import("../components/vue-ui-age-pyramid.vue")),
13+
VueUiAnnotator : defineAsyncComponent(() => import("../components/vue-ui-annotator.vue")),
14+
VueUiCandlestick : defineAsyncComponent(() => import("../components/vue-ui-candlestick.vue")),
15+
VueUiChestnut : defineAsyncComponent(() => import("../components/vue-ui-chestnut.vue")),
16+
VueUiDigits : defineAsyncComponent(() => import("../components/vue-ui-digits.vue")),
17+
VueUiDonut : defineAsyncComponent(() => import("../components/vue-ui-donut.vue")),
18+
VueUiDonutEvolution : defineAsyncComponent(() => import("../components/vue-ui-donut-evolution.vue")),
19+
VueUiDumbbell : defineAsyncComponent(() => import("../components/vue-ui-dumbbell.vue")),
20+
VueUiFlow : defineAsyncComponent(() => import("../components/vue-ui-flow.vue")),
21+
VueUiGalaxy : defineAsyncComponent(() => import("../components/vue-ui-galaxy.vue")),
22+
VueUiGauge : defineAsyncComponent(() => import("../components/vue-ui-gauge.vue")),
23+
VueUiHeatmap : defineAsyncComponent(() => import("../components/vue-ui-heatmap.vue")),
24+
VueUiKpi : defineAsyncComponent(() => import("../components/vue-ui-kpi.vue")),
25+
VueUiMiniLoader : defineAsyncComponent(() => import("../components/vue-ui-mini-loader.vue")),
26+
VueUiMolecule : defineAsyncComponent(() => import("../components/vue-ui-molecule.vue")),
27+
VueUiMoodRadar : defineAsyncComponent(() => import("../components/vue-ui-mood-radar.vue")),
28+
VueUiNestedDonuts : defineAsyncComponent(() => import("../components/vue-ui-nested-donuts.vue")),
29+
VueUiOnion : defineAsyncComponent(() => import("../components/vue-ui-onion.vue")),
30+
VueUiParallelCoordinatePlot : defineAsyncComponent(() => import("../components/vue-ui-parallel-coordinate-plot.vue")),
31+
VueUiQuadrant : defineAsyncComponent(() => import("../components/vue-ui-quadrant.vue")),
32+
VueUiQuickChart : defineAsyncComponent(() => import("../components/vue-ui-quick-chart.vue")),
33+
VueUiRadar : defineAsyncComponent(() => import("../components/vue-ui-radar.vue")),
34+
VueUiRating : defineAsyncComponent(() => import("../components/vue-ui-rating.vue")),
35+
VueUiRelationCircle : defineAsyncComponent(() => import("../components/vue-ui-relation-circle.vue")),
36+
VueUiRings : defineAsyncComponent(() => import("../components/vue-ui-rings.vue")),
37+
VueUiScatter : defineAsyncComponent(() => import("../components/vue-ui-scatter.vue")),
38+
VueUiSkeleton : defineAsyncComponent(() => import("../components/vue-ui-skeleton.vue")),
39+
VueUiSmiley : defineAsyncComponent(() => import("../components/vue-ui-smiley.vue")),
40+
VueUiSparkHistogram : defineAsyncComponent(() => import("../components/vue-ui-sparkhistogram.vue")),
41+
VueUiSparkStackbar : defineAsyncComponent(() => import("../components/vue-ui-sparkstackbar.vue")),
42+
VueUiSparkTrend : defineAsyncComponent(() => import("../components/vue-ui-spark-trend.vue")),
43+
VueUiSparkbar : defineAsyncComponent(() => import("../components/vue-ui-sparkbar.vue")),
44+
VueUiSparkgauge : defineAsyncComponent(() => import('../components/vue-ui-sparkgauge.vue')),
45+
VueUiSparkline : defineAsyncComponent(() => import("../components/vue-ui-sparkline.vue")),
46+
VueUiStripPlot : defineAsyncComponent(() => import("../components/vue-ui-strip-plot.vue")),
47+
VueUiTable : defineAsyncComponent(() => import("../components/vue-ui-table.vue")),
48+
VueUiTableHeatmap : defineAsyncComponent(() => import("../components/vue-ui-table-heatmap.vue")),
49+
VueUiTableSparkline : defineAsyncComponent(() => import("../components/vue-ui-table-sparkline.vue")),
50+
VueUiThermometer : defineAsyncComponent(() => import("../components/vue-ui-thermometer.vue")),
51+
VueUiTimer : defineAsyncComponent(() => import("../components/vue-ui-timer.vue")),
52+
VueUiTiremarks : defineAsyncComponent(() => import("../components/vue-ui-tiremarks.vue")),
53+
VueUiTreemap : defineAsyncComponent(() => import("../components/vue-ui-treemap.vue")),
54+
VueUiVerticalBar : defineAsyncComponent(() => import("../components/vue-ui-vertical-bar.vue")),
55+
VueUiWaffle : defineAsyncComponent(() => import("../components/vue-ui-waffle.vue")),
56+
VueUiWheel : defineAsyncComponent(() => import("../components/vue-ui-wheel.vue")),
57+
VueUiWordCloud : defineAsyncComponent(() => import("../components/vue-ui-word-cloud.vue")),
58+
VueUiXy : defineAsyncComponent(() => import("../components/vue-ui-xy.vue")),
59+
VueUiXyCanvas : defineAsyncComponent(() => import("../components/vue-ui-xy-canvas.vue")),
60+
VueUiCarouselTable : defineAsyncComponent(() => import('../components/vue-ui-carousel-table.vue')),
61+
VueUiGizmo : defineAsyncComponent(() => import('../components/vue-ui-gizmo.vue')),
62+
VueUiStackbar : defineAsyncComponent(() => import('../components/vue-ui-stackbar.vue')),
63+
VueUiBullet : defineAsyncComponent(() => import('../components/vue-ui-bullet.vue')),
64+
VueUiFunnel : defineAsyncComponent(() => import('../components/vue-ui-funnel.vue')),
65+
VueUiHistoryPlot : defineAsyncComponent(() => import('../components/vue-ui-history-plot.vue')),
66+
VueUiCirclePack : defineAsyncComponent(() => import('../components/vue-ui-circle-pack.vue')),
67+
VueUiWorld : defineAsyncComponent(() => import('../components/vue-ui-world.vue')),
68+
};
1069
1170
const { vue_ui_dashboard: DEFAULT_CONFIG } = useConfig();
1271
@@ -30,13 +89,21 @@ function toggleLock() {
3089
isLocked.value = !isLocked.value;
3190
}
3291
33-
const gridSize = 20;
34-
const items = ref(props.dataset.map((item,i) => {
35-
return {
92+
const gridSize = 1;
93+
const items = ref(props.dataset.map((item, i) => ({
94+
...item,
95+
index: i
96+
})));
97+
98+
const resolvedItems = computed(() =>
99+
items.value.map(item => ({
36100
...item,
37-
index: i
38-
}
39-
}));
101+
resolvedComponent: typeof item.component === 'string'
102+
? builtInComponents[item.component]
103+
: item.component
104+
}))
105+
);
106+
40107
const dragging = ref(null);
41108
const resizing = ref(null);
42109
const dragStart = ref({ x: 0, y: 0 });
@@ -297,7 +364,6 @@ defineExpose({
297364
getItemsPositions,
298365
toggleLock
299366
})
300-
301367
</script>
302368

303369
<template>
@@ -320,7 +386,7 @@ defineExpose({
320386
<span v-else>PDF</span>
321387
</button>
322388
</div>
323-
<div class="vue-ui-dashboard-container" ref="dashboardContainer" :id="`vue-ui-dashboard_${uid}`" :style="`border:${borderBoard}; sbackground:${boardColor}; aspect-ratio:${aspectRatio}`">
389+
<div class="vue-ui-dashboard-container" ref="dashboardContainer" :id="`vue-ui-dashboard_${uid}`" :style="`border:${borderBoard}; background:${boardColor}; aspect-ratio:${aspectRatio}`">
324390
<div
325391
class="vue-ui-dashboard-grid-container"
326392
ref="container"
@@ -332,7 +398,7 @@ defineExpose({
332398
>
333399
<div class="vue-ui-dashboard-grid"></div>
334400
<div
335-
v-for="(item, index) in items"
401+
v-for="(item, index) in resolvedItems"
336402
:key="item.id"
337403
:class="{'vue-ui-dashboard-grid-item': true, 'vue-ui-dashboard-grid-item--locked': isLocked }"
338404
:style="{
@@ -342,7 +408,7 @@ defineExpose({
342408
top: `${item.top}%`,
343409
cursor: 'move',
344410
boxShadow: changeIndex === index ? '0 6px 12px -3px rgba(0,0,0,0.3)' : '',
345-
zIndex: changeIndex === index ? items.length + 1 : item.index,
411+
zIndex: changeIndex === index ? resolvedItems.length + 1 : item.index,
346412
backgroundColor: FINAL_CONFIG.style.item.backgroundColor
347413
}"
348414
@mousedown="startDrag(index)"
@@ -378,8 +444,15 @@ defineExpose({
378444
@touchend="onTouchEnd"
379445
></div>
380446
</template>
381-
382-
<slot name="content" :item="item" :index="index" :left="item.left" :top="item.top" :height="item.height" :width="item.width"></slot>
447+
448+
<component
449+
:is="item.resolvedComponent"
450+
v-bind="item.props"
451+
v-if="item.resolvedComponent"
452+
/>
453+
<template v-else>
454+
<slot name="content" :item="item" :index="index" :left="item.left" :top="item.top" :height="item.height" :width="item.width"></slot>
455+
</template>
383456
</div>
384457
</div>
385458
</div>
@@ -489,4 +562,4 @@ defineExpose({
489562
transform: rotate(360deg);
490563
}
491564
}
492-
</style>
565+
</style>

0 commit comments

Comments
 (0)