Skip to content

Commit a144402

Browse files
authored
AI Column: Write JS Framework demos, DataGrid, Vue (#31707)
1 parent 11990f3 commit a144402

File tree

8 files changed

+2307
-0
lines changed

8 files changed

+2307
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<template>
2+
<DxDataGrid
3+
keyExpr="ID"
4+
:dataSource="vehicles"
5+
:showBorders="true"
6+
:aiIntegration="aiIntegration"
7+
:onAIColumnRequestCreating="onAIColumnRequestCreating"
8+
>
9+
<DxGrouping :contextMenuEnabled="false"/>
10+
<DxPaging :pageSize="10"/>
11+
12+
<DxColumn
13+
caption="Trademark"
14+
dataField="TrademarkName"
15+
:width="200"
16+
cellTemplate="trademark-cell"
17+
/>
18+
<template #trademark-cell="{ data: { data: vehicle} }">
19+
<Trademark
20+
:vehicle="vehicle"
21+
@showInfo="showInfo"
22+
/>
23+
</template>
24+
<DxColumn
25+
dataField="Price"
26+
alignment="left"
27+
format="currency"
28+
:width="100"
29+
/>
30+
<DxColumn
31+
caption="Category"
32+
:minWidth="180"
33+
cellTemplate="category-cell"
34+
/>
35+
<template #category-cell="{ data: { data: vehicle} }">
36+
<Category :category="vehicle.CategoryName"/>
37+
</template>
38+
<DxColumn
39+
dataField="Modification"
40+
:width="180"
41+
/>
42+
<DxColumn
43+
dataField="Horsepower"
44+
:width="140"
45+
/>
46+
<DxColumn
47+
dataField="BodyStyleName"
48+
caption="Body Style"
49+
:width="180"
50+
/>
51+
<DxColumn
52+
name="AI Column"
53+
caption="AI Column"
54+
cssClass="ai__cell"
55+
type="ai"
56+
:ai="{
57+
prompt: 'Identify the country where this vehicle model is originally manufactured or developed, based on its brand, model, and specifications.',
58+
mode: 'auto',
59+
noDataText: 'No data',
60+
}"
61+
:fixed="true"
62+
fixedPosition="right"
63+
:width="200"
64+
/>
65+
</DxDataGrid>
66+
<DxPopup
67+
v-model:visible="popupVisible"
68+
title="Image Info"
69+
width="360"
70+
height="260"
71+
:dragEnabled="false"
72+
:hideOnOutsideClick="true"
73+
:onHiding="hideInfo"
74+
>
75+
<DxPosition
76+
at="center"
77+
my="center"
78+
collision="fit"
79+
/>
80+
<template #content>
81+
<LicenseInfo :vehicle="currentVehicle"/>
82+
</template>
83+
</DxPopup>
84+
</template>
85+
86+
<script setup lang="ts">
87+
import { ref } from 'vue';
88+
import { DxDataGrid, DxColumn, DxGrouping, DxPaging } from 'devextreme-vue/data-grid';
89+
import { DxPopup, DxPosition } from 'devextreme-vue/popup';
90+
import { vehicles, type Vehicle } from './data.ts';
91+
import { aiIntegration } from './service.ts';
92+
import Trademark from './Trademark.vue';
93+
import Category from './Category.vue';
94+
import LicenseInfo from './LicenseInfo.vue';
95+
96+
const currentVehicle = ref<Vehicle | undefined>();
97+
const popupVisible = ref(false);
98+
99+
const showInfo = (vehicle: Vehicle) => {
100+
currentVehicle.value = vehicle;
101+
popupVisible.value = true;
102+
};
103+
104+
const hideInfo = () => {
105+
popupVisible.value = false;
106+
};
107+
108+
const onAIColumnRequestCreating = (e: { data: Partial<Vehicle>[] }) => {
109+
e.data = e.data.map((item) => ({
110+
ID: item.ID,
111+
TrademarkName: item.TrademarkName,
112+
Name: item.Name,
113+
Modification: item.Modification,
114+
}));
115+
};
116+
</script>
117+
118+
<style scoped>
119+
#app .ai__cell {
120+
background-color: var(--dx-datagrid-row-alternation-bg);
121+
}
122+
</style>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<template>
2+
<div class="category__wrapper">{{ category }}</div>
3+
</template>
4+
5+
<script setup lang="ts">
6+
defineProps<{
7+
category: string,
8+
}>();
9+
</script>
10+
11+
<style scoped>
12+
.category__wrapper {
13+
display: inline-block;
14+
padding: 2px 8px;
15+
border-radius: 24px;
16+
background-color: var(--dx-color-separator);
17+
}
18+
</style>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<template>
2+
<p><b>Image licensed under: </b> <span>{{ LicenseName }}</span></p>
3+
<p><b>Author: </b> <span>{{ Author }}</span></p>
4+
<p>
5+
<b>Source link: </b>
6+
<a
7+
:href="vehicleLink"
8+
target="_blank"
9+
rel="noopener noreferrer"
10+
>
11+
{{ vehicleLink }}
12+
</a>
13+
</p>
14+
<p><b>Edits: </b> <span>{{ Edits }}</span></p>
15+
</template>
16+
17+
<script setup lang="ts">
18+
import type { Vehicle } from './data.ts';
19+
20+
const props = withDefaults(defineProps<{
21+
vehicle?: Vehicle,
22+
}>(), {
23+
vehicle: () => ({} as Vehicle),
24+
});
25+
26+
const {
27+
LicenseName,
28+
Author,
29+
Source,
30+
Edits,
31+
} = props.vehicle;
32+
const vehicleLink = `https://${Source}`;
33+
</script>
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<template>
2+
<div class="trademark__wrapper">
3+
<div class="trademark__img-wrapper">
4+
<img
5+
class="trademark__img"
6+
:src="`../../../../images/vehicles/image_${ID}.png`"
7+
:alt="`${TrademarkName} ${Name}`"
8+
@click="emit('showInfo', vehicle)"
9+
@keydown="onKeyDown"
10+
role="button"
11+
tabindex="0"
12+
aria-haspopup="dialog"
13+
:aria-label="`${TrademarkName} ${Name} - press Enter for image info`"
14+
>
15+
</div>
16+
<div class="trademark__text-wrapper">
17+
<div class="trademark__text trademark__text--title">{{ TrademarkName }}</div>
18+
<div class="trademark__text trademark__text--subtitle">{{ Name }}</div>
19+
</div>
20+
</div>
21+
</template>
22+
23+
<script setup lang="ts">
24+
import type { Vehicle } from './data.ts';
25+
26+
interface TrademarkNameProps { vehicle: Vehicle }
27+
interface TrademarkNameEmits { (e: 'showInfo', v: Vehicle): void }
28+
29+
const { vehicle } = defineProps<TrademarkNameProps>();
30+
const emit = defineEmits<TrademarkNameEmits>();
31+
32+
const { ID, TrademarkName, Name } = vehicle;
33+
34+
const onKeyDown = (event: KeyboardEvent) => {
35+
if (event.key === 'Enter') {
36+
emit('showInfo', vehicle);
37+
}
38+
};
39+
</script>
40+
41+
<style scoped>
42+
.trademark__wrapper {
43+
display: flex;
44+
align-items: center;
45+
gap: 8px;
46+
}
47+
48+
.trademark__img-wrapper {
49+
width: 40px;
50+
height: 40px;
51+
border: var(--dx-border-width) solid var(--dx-color-border);
52+
border-radius: var(--dx-border-radius);
53+
cursor: pointer;
54+
}
55+
56+
.trademark__img-wrapper img {
57+
width: 100%;
58+
height: 100%;
59+
object-fit: cover;
60+
object-position: center;
61+
border-radius: var(--dx-border-radius);
62+
}
63+
64+
.trademark__text-wrapper {
65+
width: calc(100% - 48px);
66+
}
67+
68+
.trademark__text {
69+
margin: 0;
70+
padding: 0;
71+
white-space: nowrap;
72+
overflow: hidden;
73+
text-overflow: ellipsis;
74+
}
75+
76+
.trademark__text--title {
77+
font-weight: 600;
78+
}
79+
80+
.trademark__text--subtitle {
81+
font-weight: 400;
82+
}
83+
</style>

0 commit comments

Comments
 (0)