chore: add Nuxt 3 Getting Started Demo (#332)
Co-authored-by: Petar Todorov <petar.todorov@progre>
This commit is contained in:
Родитель
d4ba072fa9
Коммит
8170a19496
|
@ -0,0 +1,8 @@
|
|||
node_modules
|
||||
*.log*
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
.output
|
||||
.env
|
||||
dist
|
|
@ -0,0 +1,42 @@
|
|||
# Nuxt 3 Minimal Starter
|
||||
|
||||
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install the dependencies:
|
||||
|
||||
```bash
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install --shamefully-hoist
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on http://localhost:3000
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
npm run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
|
@ -0,0 +1,8 @@
|
|||
<template>
|
||||
<div>
|
||||
<NuxtPage />
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
@import '@progress/kendo-theme-default';
|
||||
</style>
|
|
@ -0,0 +1,12 @@
|
|||
const categories = [
|
||||
{ "CategoryID": 1, "CategoryName": "Beverages" },
|
||||
{ "CategoryID": 2, "CategoryName": "Condiments" },
|
||||
{ "CategoryID": 3, "CategoryName": "Confections" },
|
||||
{ "CategoryID": 4, "CategoryName": "Dairy Products" },
|
||||
{ "CategoryID": 5, "CategoryName": "Grains/Cereals" },
|
||||
{ "CategoryID": 6, "CategoryName": "Meat/Poultry" },
|
||||
{ "CategoryID": 7, "CategoryName": "Produce" },
|
||||
{ "CategoryID": 8, "CategoryName": "Seafood" }
|
||||
];
|
||||
|
||||
export { categories as categoriesData };
|
|
@ -0,0 +1,20 @@
|
|||
const products = [
|
||||
{ "ProductID": 1, "ProductName": "Tea", "CategoryID": 1, "QuantityPerUnit": "10 boxes x 20 bags", "UnitPrice": 18.0, "UnitsInStock": 39, "Discontinued": false },
|
||||
{ "ProductID": 7, "ProductName": "Dried Pears", "CategoryID": 7, "QuantityPerUnit": "12 - 1 lb pkgs.", "UnitPrice": 30.0, "UnitsInStock": 15, "Discontinued": false },
|
||||
{ "ProductID": 8, "ProductName": "Cranberry Sauce", "CategoryID": 2, "QuantityPerUnit": "12 - 12 oz jars", "UnitPrice": 40.0, "UnitsInStock": 6, "Discontinued": false },
|
||||
{ "ProductID": 9, "ProductName": "Mishi Kobe Niku", "CategoryID": 6, "QuantityPerUnit": "18 - 500 g pkgs.", "UnitPrice": 97.0, "UnitsInStock": 29, "Discontinued": true },
|
||||
{ "ProductID": 14, "ProductName": "Tofu", "CategoryID": 7, "QuantityPerUnit": "40 - 100 g pkgs.", "UnitPrice": 23.25, "UnitsInStock": 35, "Discontinued": false },
|
||||
{ "ProductID": 17, "ProductName": "Alice Mutton", "CategoryID": 6, "QuantityPerUnit": "20 - 1 kg tins", "UnitPrice": 39.0, "UnitsInStock": 0, "Discontinued": false },
|
||||
{ "ProductID": 19, "ProductName": "Teatime Biscuits", "CategoryID": 3, "QuantityPerUnit": "10 boxes x 12 pieces", "UnitPrice": 9.2, "UnitsInStock": 25, "Discontinued": false },
|
||||
{ "ProductID": 40, "ProductName": "Boston Crab Meat", "CategoryID": 8, "QuantityPerUnit": "24 - 4 oz tins", "UnitPrice": 18.4, "UnitsInStock": 123, "Discontinued": false },
|
||||
{ "ProductID": 43, "ProductName": "Coffee", "CategoryID": 1, "QuantityPerUnit": "16 - 500 g tins", "UnitPrice": 46.0, "UnitsInStock": 17, "Discontinued": false },
|
||||
{ "ProductID": 48, "ProductName": "Chocolate", "CategoryID": 3, "QuantityPerUnit": "10 pkgs.", "UnitPrice": 12.75, "UnitsInStock": 15, "Discontinued": false },
|
||||
{ "ProductID": 56, "ProductName": "Gnocchi di nonna Alice", "CategoryID": 5, "QuantityPerUnit": "24 - 250 g pkgs.", "UnitPrice": 38.0, "UnitsInStock": 21, "Discontinued": true },
|
||||
{ "ProductID": 57, "ProductName": "Ravioli Angelo", "CategoryID": 5, "QuantityPerUnit": "24 - 250 g pkgs.", "UnitPrice": 19.5, "UnitsInStock": 36, "Discontinued": false },
|
||||
{ "ProductID": 60, "ProductName": "Camembert Pierrot", "CategoryID": 4, "QuantityPerUnit": "15 - 300 g rounds", "UnitPrice": 34.0, "UnitsInStock": 19, "Discontinued": true },
|
||||
{ "ProductID": 65, "ProductName": "Hot Pepper Sauce", "CategoryID": 2, "QuantityPerUnit": "32 - 8 oz bottles", "UnitPrice": 21.05, "UnitsInStock": 76, "Discontinued": false },
|
||||
{ "ProductID": 72, "ProductName": "Mozzarella di Giovanni", "CategoryID": 4, "QuantityPerUnit": "24 - 200 g pkgs.", "UnitPrice": 34.8, "UnitsInStock": 14, "Discontinued": false },
|
||||
{ "ProductID": 73, "ProductName": "Röd Kaviar", "CategoryID": 8, "QuantityPerUnit": "24 - 150 g jars", "UnitPrice": 15.0, "UnitsInStock": 101, "Discontinued": true }
|
||||
];
|
||||
|
||||
export { products as productsData };
|
|
@ -0,0 +1,4 @@
|
|||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
|
||||
})
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nuxt": "3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@progress/kendo-data-query": "^1.6.0",
|
||||
"@progress/kendo-drawing": "^1.17.2",
|
||||
"@progress/kendo-licensing": "^1.2.2",
|
||||
"@progress/kendo-theme-default": "^5.11.0",
|
||||
"@progress/kendo-vue-animation": "^3.7.3",
|
||||
"@progress/kendo-vue-data-tools": "^3.7.3",
|
||||
"@progress/kendo-vue-dateinputs": "^3.7.3",
|
||||
"@progress/kendo-vue-dialogs": "^3.7.3",
|
||||
"@progress/kendo-vue-dropdowns": "^3.7.3",
|
||||
"@progress/kendo-vue-grid": "^3.7.3",
|
||||
"@progress/kendo-vue-indicators": "^3.7.3",
|
||||
"@progress/kendo-vue-inputs": "^3.7.3",
|
||||
"@progress/kendo-vue-intl": "^3.7.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<dropdownlist :data-items="categories" :data-item-key="'CategoryID'" :text-field="'CategoryName'"
|
||||
:default-item="defaultItems" @change="handleDropDownChange"></dropdownlist> Selected category ID:
|
||||
<strong>{{ dropdownlistCategory }}</strong>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { categoriesData } from '../appdata/categories';
|
||||
import { DropDownList as dropdownlist, DropDownListChangeEvent } from '@progress/kendo-vue-dropdowns';
|
||||
const emit = defineEmits(['change'])
|
||||
|
||||
|
||||
|
||||
const categories = categoriesData;
|
||||
const defaultItems = { CategoryID: null, CategoryName: "Product categories" };
|
||||
const dropdownlistCategory = ref(null);
|
||||
const handleDropDownChange = (e: DropDownListChangeEvent) => {
|
||||
emit('change', { category: e.target.value.CategoryID })
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<grid :data-items="dataResult" :pageable="pageable" :sortable="sortable" :sort="sort" :take="take" :skip="skip"
|
||||
:columns="columns" @datastatechange="dataStateChange" @rowclick="rowClick" :style="{ height: '400px' }">
|
||||
<template v-slot:discontinuedTemplate="{ props }">
|
||||
<td :colspan="1">
|
||||
<KCheckBox :checked="props.dataItem.Discontinued" :disabled="true" />
|
||||
</td>
|
||||
</template>
|
||||
</grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { productsData } from '../appdata/products';
|
||||
import { process, DataResult, State, CompositeFilterDescriptor, SortDescriptor } from '@progress/kendo-data-query';
|
||||
import { Grid as grid, GridDataStateChangeEvent, GridRowClickEvent, GridColumnProps } from '@progress/kendo-vue-grid';
|
||||
import { Checkbox as KCheckBox } from '@progress/kendo-vue-inputs';
|
||||
|
||||
|
||||
const emit = defineEmits(['rowClick'])
|
||||
const props = defineProps({
|
||||
category: { type: Number, default: null },
|
||||
})
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
const dataState: State = {
|
||||
skip: skip.value,
|
||||
take: take.value,
|
||||
sort: sort.value,
|
||||
};
|
||||
dataResult.value = process(products, dataState);
|
||||
});
|
||||
|
||||
const products = productsData;
|
||||
const pageable = ref(true);
|
||||
const sortable = ref(true);
|
||||
const skip = ref<number | undefined>(0);
|
||||
const take = ref<number | undefined>(10);
|
||||
const sort = ref<SortDescriptor[] | undefined>([
|
||||
{ field: "ProductName", dir: "asc" }
|
||||
]);
|
||||
const filter = ref<CompositeFilterDescriptor>({ logic: "and", filters: [] });
|
||||
|
||||
watch(() => props.category, () => handleDropDownChange())
|
||||
|
||||
const handleDropDownChange = () => {
|
||||
if (props.category !== null) {
|
||||
filter.value = {
|
||||
logic: 'and',
|
||||
filters: [{ field: 'CategoryID', operator: 'eq', value: props.category }]
|
||||
}
|
||||
skip.value = 0
|
||||
} else {
|
||||
filter.value = {} as CompositeFilterDescriptor
|
||||
skip.value = 0
|
||||
};
|
||||
|
||||
const event: GridDataStateChangeEvent = {
|
||||
data: {
|
||||
skip: skip.value,
|
||||
take: take.value,
|
||||
sort: sort.value,
|
||||
filter: filter.value
|
||||
}
|
||||
};
|
||||
|
||||
dataStateChange(event);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ field: 'ProductName', title: 'Product Name' },
|
||||
{ field: 'UnitPrice', title: 'Price' },
|
||||
{ field: 'UnitsInStock', title: 'Units in Stock' },
|
||||
{ field: 'Discontinued', cell: 'discontinuedTemplate' }
|
||||
] as GridColumnProps[];
|
||||
|
||||
const dataResult = ref<DataResult>({ data: [] as any, total: 0 });
|
||||
|
||||
const createAppState = (dataState: State) => {
|
||||
take.value = dataState.take;
|
||||
skip.value = dataState.skip;
|
||||
sort.value = dataState.sort;
|
||||
};
|
||||
|
||||
const dataStateChange = (event: GridDataStateChangeEvent) => {
|
||||
createAppState(event.data);
|
||||
if (event.data.filter !== undefined && event.data.filter.logic) {
|
||||
dataResult.value = process(products, {
|
||||
skip: event.data.skip,
|
||||
take: event.data.take,
|
||||
sort: event.data.sort,
|
||||
filter: event.data.filter
|
||||
});
|
||||
} else {
|
||||
dataResult.value = process(products, {
|
||||
skip: event.data.skip,
|
||||
take: event.data.take,
|
||||
sort: event.data.sort,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const rowClick = (event: GridRowClickEvent) => {
|
||||
const windowVisible = true;
|
||||
const gridClickedRow = event.dataItem;
|
||||
emit('rowClick', { windowVisible, gridClickedRow })
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<script lang="ts" setup>
|
||||
import { Window as window } from '@progress/kendo-vue-dialogs';
|
||||
const emit = defineEmits(['closeWindow'])
|
||||
|
||||
const props = defineProps({
|
||||
rowData: { type: Object, default: { windowVisible: false, gridClickedRow: { "ProductName": "", "ProductID": "", QuantityPerUnit: "" } } },
|
||||
})
|
||||
|
||||
const closeWindow = () => {
|
||||
emit('closeWindow', { windowVisible: false })
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<window v-if="props.rowData.windowVisible" :title="'Product Details'" @close="closeWindow" :height="250">
|
||||
<dl :style="{ 'text-align': 'left' }">
|
||||
<dt>Product Name</dt>
|
||||
<dd>{{ props.rowData.gridClickedRow.ProductName }}</dd>
|
||||
<dt>Product ID</dt>
|
||||
<dd>{{ props.rowData.gridClickedRow.ProductID }}</dd>
|
||||
<dt>Quantity per Unit</dt>
|
||||
<dd>{{ props.rowData.gridClickedRow.QuantityPerUnit }}</dd>
|
||||
</dl>
|
||||
</window>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,33 @@
|
|||
<script lang="ts" setup>
|
||||
import DropDownList from './KendoDropDownList.vue';
|
||||
import Grid from './KendoGrid.vue';
|
||||
import Window from './KendoWindow.vue';
|
||||
|
||||
const rowData = ref({});
|
||||
const category = ref();
|
||||
|
||||
const onRowClick = (event: any) => {
|
||||
rowData.value = event;
|
||||
}
|
||||
|
||||
const onCloseWindow = (event: any) => {
|
||||
rowData.value = { windowVisible: false };
|
||||
}
|
||||
|
||||
const onCategoryChange = (event: any) => {
|
||||
category.value = event.category;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Hello Kendo UI for Vue with Nuxt 3!</h1>
|
||||
<DropDownList @change="onCategoryChange" />
|
||||
<Grid @row-click="onRowClick" :category="category" />
|
||||
<Window :row-data="rowData" @close-window="onCloseWindow" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
// https://nuxt.com/docs/guide/concepts/typescript
|
||||
"extends": "./.nuxt/tsconfig.json"
|
||||
}
|
Загрузка…
Ссылка в новой задаче