diff --git a/package.json b/package.json
new file mode 100644
index 0000000..7a5fce4
--- /dev/null
+++ b/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "kendo-react-template-app",
+ "version": "0.1.0",
+ "private": true,
+ "dependencies": {
+ "@progress/kendo-data-query": "latest",
+ "@progress/kendo-drawing": "latest",
+ "@progress/kendo-react-charts": "latest",
+ "@progress/kendo-react-dateinputs": "latest",
+ "@progress/kendo-react-dialogs": "latest",
+ "@progress/kendo-react-dropdowns": "latest",
+ "@progress/kendo-react-grid": "latest",
+ "@progress/kendo-react-inputs": "latest",
+ "@progress/kendo-react-intl": "latest",
+ "@progress/kendo-react-layout": "latest",
+ "@progress/kendo-react-tooltip": "latest",
+ "@progress/kendo-theme-default": "latest",
+ "bootstrap": "^4.3.1",
+ "hammerjs": "^2.0.8",
+ "node-sass": "^4.12.0",
+ "react": "^16.9.0",
+ "react-dom": "^16.9.0",
+ "react-router-dom": "^5.0.1",
+ "react-scripts": "3.1.1"
+ },
+ "scripts": {
+ "start": "react-scripts start",
+ "build": "react-scripts build",
+ "test": "react-scripts test",
+ "eject": "react-scripts eject"
+ },
+ "eslintConfig": {
+ "extends": "react-app"
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ }
+}
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 0000000..46a558a
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,35 @@
+import React, { useState } from 'react';
+import './App.scss';
+import { Header } from './components/Header'
+import { BrowserRouter as Router, Route } from "react-router-dom";
+import Home from './components/Home';
+import GridPage from './components/GridPage';
+import ChartPage from './components/ChartPage';
+import FormsPage from './components/FormsPage';
+import Footer from './components/Footer';
+
+const App = () => {
+ const [theme, setTheme] = useState("https://unpkg.com/@progress/kendo-theme-default@latest/dist/all.css");
+
+ const changeTheme = (theme) => {
+ setTheme(theme);
+ }
+
+ return (
+
+
+
+
+
+ } key={2}/>
+ } key={3}/>
+ } key={4}/>
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/src/App.scss b/src/App.scss
new file mode 100644
index 0000000..79acbcf
--- /dev/null
+++ b/src/App.scss
@@ -0,0 +1,154 @@
+@import './styles/bootstrap-custom.scss';
+
+.App {
+ text-align: center;
+}
+
+.App-logo {
+ animation: App-logo-spin infinite 20s linear;
+ height: 40vmin;
+ pointer-events: none;
+}
+
+.App-header {
+ background-color: #282c34;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ font-size: calc(10px + 2vmin);
+ color: white;
+}
+
+.App-link {
+ color: #61dafb;
+}
+
+@keyframes App-logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+.app-header>.project-name{
+ text-align: left;
+ letter-spacing: 0;
+ color: #000000;
+ opacity: 1;
+}
+
+.app-header>.nav{
+ float: righnpmt;
+}
+
+.content {
+ min-height: 100vh;
+}
+
+.logo {
+ font-weight: 700;
+ font-size: 24px;
+}
+
+.welcome {
+ text-align: center;
+ font-weight: 900;
+ letter-spacing: 0;
+ color: #000000;
+ opacity: 1;
+}
+
+.message{
+ text-align: center;
+}
+
+.sub-header {
+ text-align: center;
+ font-weight: 400;
+ letter-spacing: 0;
+ color: #919191;
+ opacity: 1;
+ margin-bottom: 4rem;
+}
+
+.get-started {
+ text-align: center;
+ font-weight: 900;
+ font-size: 78px;
+ letter-spacing: 0;
+ color: #000000;
+ opacity: 1;
+ margin-bottom: 1rem;
+}
+
+.kendoka {
+ width: 12.5rem;
+ height: 12.5rem;
+ opacity: 1;
+}
+
+.change-theme {
+ font-size: 14px;
+ color: #9098A5;
+}
+
+.components-list>p>a {
+ margin-left: 0.6em;
+}
+.components-list>p>img {
+ width: 1.25rem;
+ height: 1.3125rem;
+}
+.footer {
+ font-size: 11px;
+ background: #646871 0% 0% no-repeat padding-box;
+ opacity: 1;
+ padding-top: 2rem;
+ padding-bottom: 3rem;
+}
+
+.footer .links {
+ text-align: left;
+ letter-spacing: 0.33px;
+ color: #FFFFFF;
+ font-weight: 700;
+ opacity: 1;
+}
+.divider {
+ margin-left: 0.4rem;
+ margin-right: 0.4rem;
+ opacity: 0.2;
+}
+
+.copyright{
+ letter-spacing: 0.33px;
+ color: #FFFFFF;
+ opacity: 0.6;
+}
+
+.k-widget.k-menu {
+ height: 100%;
+}
+
+.k-widget.k-dropdown, .k-list .k-item {
+ text-transform: uppercase;
+}
+
+.social img {
+ margin-left: 3rem;
+}
+
+.k-menu:not(.k-context-menu)>.k-item>.k-link::before {
+ pointer-events: none;
+}
+a, a:visited {
+ color: inherit;
+ font-weight: 500;
+}
+.k-tooltip {
+ width: 15rem;
+}
\ No newline at end of file
diff --git a/src/App.test.js b/src/App.test.js
new file mode 100644
index 0000000..a754b20
--- /dev/null
+++ b/src/App.test.js
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './App';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render( , div);
+ ReactDOM.unmountComponentAtNode(div);
+});
diff --git a/src/common/sample-products.jsx b/src/common/sample-products.jsx
new file mode 100644
index 0000000..639f419
--- /dev/null
+++ b/src/common/sample-products.jsx
@@ -0,0 +1,1236 @@
+
+export const sampleProducts =
+[{
+ "ProductID" : 1,
+ "ProductName" : "Chai",
+ "SupplierID" : 1,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "10 boxes x 20 bags",
+ "UnitPrice" : 18.0000,
+ "UnitsInStock" : 39,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 2,
+ "ProductName" : "Chang",
+ "SupplierID" : 1,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "24 - 12 oz bottles",
+ "UnitPrice" : 19.0000,
+ "UnitsInStock" : 17,
+ "UnitsOnOrder" : 40,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 3,
+ "ProductName" : "Aniseed Syrup",
+ "SupplierID" : 1,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "12 - 550 ml bottles",
+ "UnitPrice" : 10.0000,
+ "UnitsInStock" : 13,
+ "UnitsOnOrder" : 70,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 4,
+ "ProductName" : "Chef Anton's Cajun Seasoning",
+ "SupplierID" : 2,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "48 - 6 oz jars",
+ "UnitPrice" : 22.0000,
+ "UnitsInStock" : 53,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 5,
+ "ProductName" : "Chef Anton's Gumbo Mix",
+ "SupplierID" : 2,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "36 boxes",
+ "UnitPrice" : 21.3500,
+ "UnitsInStock" : 0,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 6,
+ "ProductName" : "Grandma's Boysenberry Spread",
+ "SupplierID" : 3,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "12 - 8 oz jars",
+ "UnitPrice" : 25.0000,
+ "UnitsInStock" : 120,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 7,
+ "ProductName" : "Uncle Bob's Organic Dried Pears",
+ "SupplierID" : 3,
+ "CategoryID" : 7,
+ "QuantityPerUnit" : "12 - 1 lb pkgs.",
+ "UnitPrice" : 30.0000,
+ "UnitsInStock" : 15,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 7,
+ "CategoryName" : "Produce",
+ "Description" : "Dried fruit and bean curd"
+ }
+}, {
+ "ProductID" : 8,
+ "ProductName" : "Northwoods Cranberry Sauce",
+ "SupplierID" : 3,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "12 - 12 oz jars",
+ "UnitPrice" : 40.0000,
+ "UnitsInStock" : 6,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 9,
+ "ProductName" : "Mishi Kobe Niku",
+ "SupplierID" : 4,
+ "CategoryID" : 6,
+ "QuantityPerUnit" : "18 - 500 g pkgs.",
+ "UnitPrice" : 97.0000,
+ "UnitsInStock" : 29,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 6,
+ "CategoryName" : "Meat/Poultry",
+ "Description" : "Prepared meats"
+ }
+}, {
+ "ProductID" : 10,
+ "ProductName" : "Ikura",
+ "SupplierID" : 4,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "12 - 200 ml jars",
+ "UnitPrice" : 31.0000,
+ "UnitsInStock" : 31,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 11,
+ "ProductName" : "Queso Cabrales",
+ "SupplierID" : 5,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "1 kg pkg.",
+ "UnitPrice" : 21.0000,
+ "UnitsInStock" : 22,
+ "UnitsOnOrder" : 30,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 12,
+ "ProductName" : "Queso Manchego La Pastora",
+ "SupplierID" : 5,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "10 - 500 g pkgs.",
+ "UnitPrice" : 38.0000,
+ "UnitsInStock" : 86,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 13,
+ "ProductName" : "Konbu",
+ "SupplierID" : 6,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "2 kg box",
+ "UnitPrice" : 6.0000,
+ "UnitsInStock" : 24,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 14,
+ "ProductName" : "Tofu",
+ "SupplierID" : 6,
+ "CategoryID" : 7,
+ "QuantityPerUnit" : "40 - 100 g pkgs.",
+ "UnitPrice" : 23.2500,
+ "UnitsInStock" : 35,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 7,
+ "CategoryName" : "Produce",
+ "Description" : "Dried fruit and bean curd"
+ }
+}, {
+ "ProductID" : 15,
+ "ProductName" : "Genen Shouyu",
+ "SupplierID" : 6,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "24 - 250 ml bottles",
+ "UnitPrice" : 15.5000,
+ "UnitsInStock" : 39,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 16,
+ "ProductName" : "Pavlova",
+ "SupplierID" : 7,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "32 - 500 g boxes",
+ "UnitPrice" : 17.4500,
+ "UnitsInStock" : 29,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 17,
+ "ProductName" : "Alice Mutton",
+ "SupplierID" : 7,
+ "CategoryID" : 6,
+ "QuantityPerUnit" : "20 - 1 kg tins",
+ "UnitPrice" : 39.0000,
+ "UnitsInStock" : 0,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 6,
+ "CategoryName" : "Meat/Poultry",
+ "Description" : "Prepared meats"
+ }
+}, {
+ "ProductID" : 18,
+ "ProductName" : "Carnarvon Tigers",
+ "SupplierID" : 7,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "16 kg pkg.",
+ "UnitPrice" : 62.5000,
+ "UnitsInStock" : 42,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 19,
+ "ProductName" : "Teatime Chocolate Biscuits",
+ "SupplierID" : 8,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "10 boxes x 12 pieces",
+ "UnitPrice" : 9.2000,
+ "UnitsInStock" : 25,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 20,
+ "ProductName" : "Sir Rodney's Marmalade",
+ "SupplierID" : 8,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "30 gift boxes",
+ "UnitPrice" : 81.0000,
+ "UnitsInStock" : 40,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 21,
+ "ProductName" : "Sir Rodney's Scones",
+ "SupplierID" : 8,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "24 pkgs. x 4 pieces",
+ "UnitPrice" : 10.0000,
+ "UnitsInStock" : 3,
+ "UnitsOnOrder" : 40,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 22,
+ "ProductName" : "Gustaf's Knäckebröd",
+ "SupplierID" : 9,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "24 - 500 g pkgs.",
+ "UnitPrice" : 21.0000,
+ "UnitsInStock" : 104,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 23,
+ "ProductName" : "Tunnbröd",
+ "SupplierID" : 9,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "12 - 250 g pkgs.",
+ "UnitPrice" : 9.0000,
+ "UnitsInStock" : 61,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 24,
+ "ProductName" : "Guaraná Fantástica",
+ "SupplierID" : 10,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "12 - 355 ml cans",
+ "UnitPrice" : 4.5000,
+ "UnitsInStock" : 20,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 25,
+ "ProductName" : "NuNuCa Nuß-Nougat-Creme",
+ "SupplierID" : 11,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "20 - 450 g glasses",
+ "UnitPrice" : 14.0000,
+ "UnitsInStock" : 76,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 26,
+ "ProductName" : "Gumbär Gummibärchen",
+ "SupplierID" : 11,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "100 - 250 g bags",
+ "UnitPrice" : 31.2300,
+ "UnitsInStock" : 15,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 27,
+ "ProductName" : "Schoggi Schokolade",
+ "SupplierID" : 11,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "100 - 100 g pieces",
+ "UnitPrice" : 43.9000,
+ "UnitsInStock" : 49,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 28,
+ "ProductName" : "Rössle Sauerkraut",
+ "SupplierID" : 12,
+ "CategoryID" : 7,
+ "QuantityPerUnit" : "25 - 825 g cans",
+ "UnitPrice" : 45.6000,
+ "UnitsInStock" : 26,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 7,
+ "CategoryName" : "Produce",
+ "Description" : "Dried fruit and bean curd"
+ }
+}, {
+ "ProductID" : 29,
+ "ProductName" : "Thüringer Rostbratwurst",
+ "SupplierID" : 12,
+ "CategoryID" : 6,
+ "QuantityPerUnit" : "50 bags x 30 sausgs.",
+ "UnitPrice" : 123.7900,
+ "UnitsInStock" : 0,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 6,
+ "CategoryName" : "Meat/Poultry",
+ "Description" : "Prepared meats"
+ }
+}, {
+ "ProductID" : 30,
+ "ProductName" : "Nord-Ost Matjeshering",
+ "SupplierID" : 13,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "10 - 200 g glasses",
+ "UnitPrice" : 25.8900,
+ "UnitsInStock" : 10,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 31,
+ "ProductName" : "Gorgonzola Telino",
+ "SupplierID" : 14,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "12 - 100 g pkgs",
+ "UnitPrice" : 12.5000,
+ "UnitsInStock" : 0,
+ "UnitsOnOrder" : 70,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 32,
+ "ProductName" : "Mascarpone Fabioli",
+ "SupplierID" : 14,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "24 - 200 g pkgs.",
+ "UnitPrice" : 32.0000,
+ "UnitsInStock" : 9,
+ "UnitsOnOrder" : 40,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 33,
+ "ProductName" : "Geitost",
+ "SupplierID" : 15,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "500 g",
+ "UnitPrice" : 2.5000,
+ "UnitsInStock" : 112,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 34,
+ "ProductName" : "Sasquatch Ale",
+ "SupplierID" : 16,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "24 - 12 oz bottles",
+ "UnitPrice" : 14.0000,
+ "UnitsInStock" : 111,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 35,
+ "ProductName" : "Steeleye Stout",
+ "SupplierID" : 16,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "24 - 12 oz bottles",
+ "UnitPrice" : 18.0000,
+ "UnitsInStock" : 20,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 36,
+ "ProductName" : "Inlagd Sill",
+ "SupplierID" : 17,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "24 - 250 g jars",
+ "UnitPrice" : 19.0000,
+ "UnitsInStock" : 112,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 37,
+ "ProductName" : "Gravad lax",
+ "SupplierID" : 17,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "12 - 500 g pkgs.",
+ "UnitPrice" : 26.0000,
+ "UnitsInStock" : 11,
+ "UnitsOnOrder" : 50,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 38,
+ "ProductName" : "Côte de Blaye",
+ "SupplierID" : 18,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "12 - 75 cl bottles",
+ "UnitPrice" : 263.5000,
+ "UnitsInStock" : 17,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 39,
+ "ProductName" : "Chartreuse verte",
+ "SupplierID" : 18,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "750 cc per bottle",
+ "UnitPrice" : 18.0000,
+ "UnitsInStock" : 69,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 40,
+ "ProductName" : "Boston Crab Meat",
+ "SupplierID" : 19,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "24 - 4 oz tins",
+ "UnitPrice" : 18.4000,
+ "UnitsInStock" : 123,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 41,
+ "ProductName" : "Jack's New England Clam Chowder",
+ "SupplierID" : 19,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "12 - 12 oz cans",
+ "UnitPrice" : 9.6500,
+ "UnitsInStock" : 85,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 42,
+ "ProductName" : "Singaporean Hokkien Fried Mee",
+ "SupplierID" : 20,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "32 - 1 kg pkgs.",
+ "UnitPrice" : 14.0000,
+ "UnitsInStock" : 26,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 43,
+ "ProductName" : "Ipoh Coffee",
+ "SupplierID" : 20,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "16 - 500 g tins",
+ "UnitPrice" : 46.0000,
+ "UnitsInStock" : 17,
+ "UnitsOnOrder" : 10,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 44,
+ "ProductName" : "Gula Malacca",
+ "SupplierID" : 20,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "20 - 2 kg bags",
+ "UnitPrice" : 19.4500,
+ "UnitsInStock" : 27,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 45,
+ "ProductName" : "Rogede sild",
+ "SupplierID" : 21,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "1k pkg.",
+ "UnitPrice" : 9.5000,
+ "UnitsInStock" : 5,
+ "UnitsOnOrder" : 70,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 46,
+ "ProductName" : "Spegesild",
+ "SupplierID" : 21,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "4 - 450 g glasses",
+ "UnitPrice" : 12.0000,
+ "UnitsInStock" : 95,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 47,
+ "ProductName" : "Zaanse koeken",
+ "SupplierID" : 22,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "10 - 4 oz boxes",
+ "UnitPrice" : 9.5000,
+ "UnitsInStock" : 36,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 48,
+ "ProductName" : "Chocolade",
+ "SupplierID" : 22,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "10 pkgs.",
+ "UnitPrice" : 12.7500,
+ "UnitsInStock" : 15,
+ "UnitsOnOrder" : 70,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 49,
+ "ProductName" : "Maxilaku",
+ "SupplierID" : 23,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "24 - 50 g pkgs.",
+ "UnitPrice" : 20.0000,
+ "UnitsInStock" : 10,
+ "UnitsOnOrder" : 60,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 50,
+ "ProductName" : "Valkoinen suklaa",
+ "SupplierID" : 23,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "12 - 100 g bars",
+ "UnitPrice" : 16.2500,
+ "UnitsInStock" : 65,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 51,
+ "ProductName" : "Manjimup Dried Apples",
+ "SupplierID" : 24,
+ "CategoryID" : 7,
+ "QuantityPerUnit" : "50 - 300 g pkgs.",
+ "UnitPrice" : 53.0000,
+ "UnitsInStock" : 20,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 7,
+ "CategoryName" : "Produce",
+ "Description" : "Dried fruit and bean curd"
+ }
+}, {
+ "ProductID" : 52,
+ "ProductName" : "Filo Mix",
+ "SupplierID" : 24,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "16 - 2 kg boxes",
+ "UnitPrice" : 7.0000,
+ "UnitsInStock" : 38,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 53,
+ "ProductName" : "Perth Pasties",
+ "SupplierID" : 24,
+ "CategoryID" : 6,
+ "QuantityPerUnit" : "48 pieces",
+ "UnitPrice" : 32.8000,
+ "UnitsInStock" : 0,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : true,
+ "Category" : {
+ "CategoryID" : 6,
+ "CategoryName" : "Meat/Poultry",
+ "Description" : "Prepared meats"
+ }
+}, {
+ "ProductID" : 54,
+ "ProductName" : "Tourtière",
+ "SupplierID" : 25,
+ "CategoryID" : 6,
+ "QuantityPerUnit" : "16 pies",
+ "UnitPrice" : 7.4500,
+ "UnitsInStock" : 21,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 6,
+ "CategoryName" : "Meat/Poultry",
+ "Description" : "Prepared meats"
+ }
+}, {
+ "ProductID" : 55,
+ "ProductName" : "Pâté chinois",
+ "SupplierID" : 25,
+ "CategoryID" : 6,
+ "QuantityPerUnit" : "24 boxes x 2 pies",
+ "UnitPrice" : 24.0000,
+ "UnitsInStock" : 115,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 6,
+ "CategoryName" : "Meat/Poultry",
+ "Description" : "Prepared meats"
+ }
+}, {
+ "ProductID" : 56,
+ "ProductName" : "Gnocchi di nonna Alice",
+ "SupplierID" : 26,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "24 - 250 g pkgs.",
+ "UnitPrice" : 38.0000,
+ "UnitsInStock" : 21,
+ "UnitsOnOrder" : 10,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 57,
+ "ProductName" : "Ravioli Angelo",
+ "SupplierID" : 26,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "24 - 250 g pkgs.",
+ "UnitPrice" : 19.5000,
+ "UnitsInStock" : 36,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 58,
+ "ProductName" : "Escargots de Bourgogne",
+ "SupplierID" : 27,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "24 pieces",
+ "UnitPrice" : 13.2500,
+ "UnitsInStock" : 62,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 59,
+ "ProductName" : "Raclette Courdavault",
+ "SupplierID" : 28,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "5 kg pkg.",
+ "UnitPrice" : 55.0000,
+ "UnitsInStock" : 79,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 60,
+ "ProductName" : "Camembert Pierrot",
+ "SupplierID" : 28,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "15 - 300 g rounds",
+ "UnitPrice" : 34.0000,
+ "UnitsInStock" : 19,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 61,
+ "ProductName" : "Sirop d'érable",
+ "SupplierID" : 29,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "24 - 500 ml bottles",
+ "UnitPrice" : 28.5000,
+ "UnitsInStock" : 113,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 62,
+ "ProductName" : "Tarte au sucre",
+ "SupplierID" : 29,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "48 pies",
+ "UnitPrice" : 49.3000,
+ "UnitsInStock" : 17,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 63,
+ "ProductName" : "Vegie-spread",
+ "SupplierID" : 7,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "15 - 625 g jars",
+ "UnitPrice" : 43.9000,
+ "UnitsInStock" : 24,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 64,
+ "ProductName" : "Wimmers gute Semmelknödel",
+ "SupplierID" : 12,
+ "CategoryID" : 5,
+ "QuantityPerUnit" : "20 bags x 4 pieces",
+ "UnitPrice" : 33.2500,
+ "UnitsInStock" : 22,
+ "UnitsOnOrder" : 80,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 5,
+ "CategoryName" : "Grains/Cereals",
+ "Description" : "Breads, crackers, pasta, and cereal"
+ }
+}, {
+ "ProductID" : 65,
+ "ProductName" : "Louisiana Fiery Hot Pepper Sauce",
+ "SupplierID" : 2,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "32 - 8 oz bottles",
+ "UnitPrice" : 21.0500,
+ "UnitsInStock" : 76,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 66,
+ "ProductName" : "Louisiana Hot Spiced Okra",
+ "SupplierID" : 2,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "24 - 8 oz jars",
+ "UnitPrice" : 17.0000,
+ "UnitsInStock" : 4,
+ "UnitsOnOrder" : 100,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}, {
+ "ProductID" : 67,
+ "ProductName" : "Laughing Lumberjack Lager",
+ "SupplierID" : 16,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "24 - 12 oz bottles",
+ "UnitPrice" : 14.0000,
+ "UnitsInStock" : 52,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 10,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 68,
+ "ProductName" : "Scottish Longbreads",
+ "SupplierID" : 8,
+ "CategoryID" : 3,
+ "QuantityPerUnit" : "10 boxes x 8 pieces",
+ "UnitPrice" : 12.5000,
+ "UnitsInStock" : 6,
+ "UnitsOnOrder" : 10,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 3,
+ "CategoryName" : "Confections",
+ "Description" : "Desserts, candies, and sweet breads"
+ }
+}, {
+ "ProductID" : 69,
+ "ProductName" : "Gudbrandsdalsost",
+ "SupplierID" : 15,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "10 kg pkg.",
+ "UnitPrice" : 36.0000,
+ "UnitsInStock" : 26,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 70,
+ "ProductName" : "Outback Lager",
+ "SupplierID" : 7,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "24 - 355 ml bottles",
+ "UnitPrice" : 15.0000,
+ "UnitsInStock" : 15,
+ "UnitsOnOrder" : 10,
+ "ReorderLevel" : 30,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 71,
+ "ProductName" : "Flotemysost",
+ "SupplierID" : 15,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "10 - 500 g pkgs.",
+ "UnitPrice" : 21.5000,
+ "UnitsInStock" : 26,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 72,
+ "ProductName" : "Mozzarella di Giovanni",
+ "SupplierID" : 14,
+ "CategoryID" : 4,
+ "QuantityPerUnit" : "24 - 200 g pkgs.",
+ "UnitPrice" : 34.8000,
+ "UnitsInStock" : 14,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 0,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 4,
+ "CategoryName" : "Dairy Products",
+ "Description" : "Cheeses"
+ }
+}, {
+ "ProductID" : 73,
+ "ProductName" : "Röd Kaviar",
+ "SupplierID" : 17,
+ "CategoryID" : 8,
+ "QuantityPerUnit" : "24 - 150 g jars",
+ "UnitPrice" : 15.0000,
+ "UnitsInStock" : 101,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 8,
+ "CategoryName" : "Seafood",
+ "Description" : "Seaweed and fish"
+ }
+}, {
+ "ProductID" : 74,
+ "ProductName" : "Longlife Tofu",
+ "SupplierID" : 4,
+ "CategoryID" : 7,
+ "QuantityPerUnit" : "5 kg pkg.",
+ "UnitPrice" : 10.0000,
+ "UnitsInStock" : 4,
+ "UnitsOnOrder" : 20,
+ "ReorderLevel" : 5,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 7,
+ "CategoryName" : "Produce",
+ "Description" : "Dried fruit and bean curd"
+ }
+}, {
+ "ProductID" : 75,
+ "ProductName" : "Rhönbräu Klosterbier",
+ "SupplierID" : 12,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "24 - 0.5 l bottles",
+ "UnitPrice" : 7.7500,
+ "UnitsInStock" : 125,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 25,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 76,
+ "ProductName" : "Lakkalikööri",
+ "SupplierID" : 23,
+ "CategoryID" : 1,
+ "QuantityPerUnit" : "500 ml",
+ "UnitPrice" : 18.0000,
+ "UnitsInStock" : 57,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 20,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 1,
+ "CategoryName" : "Beverages",
+ "Description" : "Soft drinks, coffees, teas, beers, and ales"
+ }
+}, {
+ "ProductID" : 77,
+ "ProductName" : "Original Frankfurter grüne Soße",
+ "SupplierID" : 12,
+ "CategoryID" : 2,
+ "QuantityPerUnit" : "12 boxes",
+ "UnitPrice" : 13.0000,
+ "UnitsInStock" : 32,
+ "UnitsOnOrder" : 0,
+ "ReorderLevel" : 15,
+ "Discontinued" : false,
+ "Category" : {
+ "CategoryID" : 2,
+ "CategoryName" : "Condiments",
+ "Description" : "Sweet and savory sauces, relishes, spreads, and seasonings"
+ }
+}]
+;
diff --git a/src/components/ChartPage.jsx b/src/components/ChartPage.jsx
new file mode 100644
index 0000000..857045d
--- /dev/null
+++ b/src/components/ChartPage.jsx
@@ -0,0 +1,69 @@
+import React, { useState } from 'react';
+import {
+ Chart,
+ ChartLegend,
+ ChartSeries,
+ ChartSeriesItem,
+ ChartTitle,
+ ChartValueAxis,
+ ChartValueAxisItem
+} from '@progress/kendo-react-charts'
+import ThemeChooser from './ThemeChooser';
+
+const series = [
+ { category: 'EUROPE', value: 0.3 },
+ { category: 'NORTH AMERICA', value: 0.23 },
+ { category: 'AUSTRALIA', value: 0.18 },
+ { category: 'ASIA', value: 0.15 },
+ { category: 'SOUTH AMERICA', value: 0.09 },
+ { category: 'AFRICA', value: 0.05 }
+];
+const loadingPanel = (
+
+);
+
+const ChartPage = (props) => {
+ const [theme, setTheme] = useState(props.theme);
+ const [loading, setLoading] = useState(false)
+ if (props.theme !== theme) {
+ setTheme(props.theme);
+ setLoading(true)
+ setTimeout(() => {
+ setLoading(false)
+ }, 100);
+ }
+ return (
+
+
+
+
+ {loading && loadingPanel}
+ {!loading &&
+ {/* uncomment to enable Tooltips */}
+
+
+
+
+
+
+
+ }
+ }
+
+
+
KendoReact Chart
+
The KendoReact Charts provide high quality graphical data visualization options.
+
They include a variety of chart types and styles that have extensive configuration options. This flexibility allows you to quickly and easily create the exact chart you need to fit your specific requirements for functionality and appearance.
+
The KendoReact Chart Components are built from the ground up, specifically for React, so that you get high performance chart components that integrate with your React app and with the rest of your React UI components.
+
For documentation and demos of all available Chart types (Bar, Line, Donut, Sparkline, StockChart etc), please visit the KendoReact Chart documentation page.
+
+
+
+ )
+}
+
+export default ChartPage;
\ No newline at end of file
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
new file mode 100644
index 0000000..3a8775b
--- /dev/null
+++ b/src/components/Footer.jsx
@@ -0,0 +1,29 @@
+import React from 'react';
+
+const span = ( | )
+const Footer = (props) => {
+ return (
+
+
+
+
+
+ Copyright © 2019 Software Corporation and/or its subsidiaries or affiliates. All Rights Reserved.
+
+
+
+
+
+ )
+}
+
+export default Footer;
\ No newline at end of file
diff --git a/src/components/FormsPage.jsx b/src/components/FormsPage.jsx
new file mode 100644
index 0000000..2cd1d6b
--- /dev/null
+++ b/src/components/FormsPage.jsx
@@ -0,0 +1,123 @@
+import React, { useState } from 'react';
+import { Input } from '@progress/kendo-react-inputs';
+import { DatePicker } from '@progress/kendo-react-dateinputs';
+import { Dialog, DialogActionsBar } from '@progress/kendo-react-dialogs';
+import ThemeChooser from './ThemeChooser';
+const FormsPage = (props) => {
+ const [formData, setFormData] = useState({
+ firstName: '',
+ lastName: '',
+ dateOfBirth: new Date(),
+ email: '',
+ company: '',
+ userName: '',
+ password: '',
+ twoFactor: false
+ });
+ const [showDialog, setShowDialog ] = useState(false)
+ const clearForm = () => {
+ setFormData({
+ firstName: '',
+ lastName: '',
+ dateOfBirth: new Date(),
+ email: '',
+ company: '',
+ userName: '',
+ password: '',
+ twoFactor: false
+ });
+ }
+
+ const onFormFieldChange = (e, field) => {
+ setFormData({ ...formData, [field]: e.target.value });
+ }
+
+ const toggleDialog = () => {
+ setShowDialog(!showDialog);
+ }
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ clearForm();
+ setShowDialog(!showDialog);
+ }
+
+ return (
+
+
+ {showDialog &&
+ The form is successfully submitted!
+
+ OK
+
+ }
+
+
+
+
KendoReact Forms
+
KendoReact includes a wide offering of UI components that can be used to build forms, including CSS classes to easily create and structure gorgeous forms.
+
The required inputs get validated upon form submission and if the validation fails, the form submission is prevented. Out of the box, KendoReact delivers components which support the HTML5 form validation and also provide props for configuring a set of minimal requirements for a component to be in a valid state.
+
For documentation and demos of the many form friendly components please visit their documentation(Date Inputs , DropDowns , Inputs etc).
+
+
+
+ )
+}
+
+export default FormsPage;
\ No newline at end of file
diff --git a/src/components/GridPage.jsx b/src/components/GridPage.jsx
new file mode 100644
index 0000000..ae6a427
--- /dev/null
+++ b/src/components/GridPage.jsx
@@ -0,0 +1,157 @@
+import React, { useState } from 'react';
+import { sampleProducts } from '../common/sample-products';
+import { MyCommandCell } from './MyCommandCell.jsx';
+import { Grid, GridColumn as Column, GridToolbar } from '@progress/kendo-react-grid';
+import { process } from '@progress/kendo-data-query';
+import ThemeChooser from './ThemeChooser';
+
+const GridPage = (props) => {
+ const editField = "inEdit";
+ const [data, setData] = useState(sampleProducts);
+ const [dataState, setDataState ] = useState({skip: 0, take: 10 })
+
+ const generateId = data => data.reduce((acc, current) => Math.max(acc, current.ProductID), 0) + 1;
+
+ const removeItem = (data, item) => {
+ let index = data.findIndex(p => p === item || item.ProductID && p.ProductID === item.ProductID);
+ if (index >= 0) {
+ data.splice(index, 1);
+ }
+ }
+
+
+ const enterEdit = (dataItem) => {
+ setData(data.map(item =>
+ item.ProductID === dataItem.ProductID ?
+ { ...item, inEdit: true } : item
+ ));
+ }
+
+ const remove = (dataItem) => {
+
+ const newData = [...data];
+ removeItem(newData, dataItem);
+ removeItem(sampleProducts, dataItem);
+ setData([...newData]);
+ }
+
+ const add = (dataItem) => {
+ dataItem.inEdit = undefined;
+ dataItem.ProductID = generateId(sampleProducts);
+
+ sampleProducts.unshift(dataItem);
+ setData([...data])
+ }
+
+ const discard = (dataItem) => {
+ const newData = [data];
+ removeItem(newData, dataItem);
+
+ setData(newData);
+ }
+
+ const update = (dataItem) => {
+ const newData = [...data]
+ const updatedItem = { ...dataItem, inEdit: undefined };
+
+ updateItem(newData, updatedItem);
+ updateItem(sampleProducts, updatedItem);
+
+ setData(newData);
+ }
+
+ const cancel = (dataItem) => {
+ const originalItem = sampleProducts.find(p => p.ProductID === dataItem.ProductID);
+ const newData = data.map(item => item.ProductID === originalItem.ProductID ? originalItem : item);
+
+ setData(newData);
+ }
+
+ const updateItem = (data, item) => {
+ let index = data.findIndex(p => p === item || (item.ProductID && p.ProductID === item.ProductID));
+ if (index >= 0) {
+ data[index] = { ...item };
+ }
+ }
+
+ const itemChange = (event) => {
+ const newData = data.map(item =>
+ item.ProductID === event.dataItem.ProductID ?
+ { ...item, [event.field]: event.value } : item
+ );
+ setData(newData);
+ }
+
+ const addNew = () => {
+ const newDataItem = { inEdit: true, Discontinued: false };
+ setData([newDataItem, ...data]);
+ }
+
+ const cancelCurrentChanges = () => {
+ setData([...sampleProducts]);
+ }
+ let CommandCell = MyCommandCell({
+ edit: enterEdit,
+ remove: remove,
+
+ add: add,
+ discard: discard,
+
+ update: update,
+ cancel: cancel,
+
+ editField: editField
+ });
+ const hasEditedItem = data.some(p => p.inEdit);
+ return (
+
+
+
+
+ setDataState(e.data)} // uncomment to enable data operations
+ // {...dataState} // uncomment to enable data operations
+ >
+
+
+ Add new
+
+ {hasEditedItem && (
+
+ Cancel current changes
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
KendoReact Grid
+
The KendoReact Data Grid (Table) provides 100+ ready-to-use features covering everything from paging, sorting, filtering, editing, and grouping to row and column virtualization, export to PDF and Excel and accessibility.
+
For documentation and demos of all available Grid features (filtering, sorting, paging, editing etc), please visit the KendoReact Grid documentation page.
+
+
+
+ );
+}
+
+export default GridPage;
\ No newline at end of file
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
new file mode 100644
index 0000000..9ca4705
--- /dev/null
+++ b/src/components/Header.jsx
@@ -0,0 +1,21 @@
+import React from 'react'
+import MenuNavContainer from './MenuNavContainer.jsx'
+
+export const Header = (props) => {
+ return (
+
+
+
+
+
+ {props.projectName}
+
+
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Home.jsx b/src/components/Home.jsx
new file mode 100644
index 0000000..9f616a5
--- /dev/null
+++ b/src/components/Home.jsx
@@ -0,0 +1,46 @@
+import React from 'react';
+
+const Home = (props) => {
+ return (
+
+
+
+
Welcome to KendoReact
+ This is a sample application built with KendoReact - a set of over 60 UI components built from the ground-up specifically for React.
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Home;
\ No newline at end of file
diff --git a/src/components/MenuNavContainer.jsx b/src/components/MenuNavContainer.jsx
new file mode 100644
index 0000000..ce34667
--- /dev/null
+++ b/src/components/MenuNavContainer.jsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import { Link } from 'react-router-dom';
+import { Menu, MenuItem } from '@progress/kendo-react-layout';
+
+
+const MenuNavContainer = (props) => {
+ return (
+
+ Home}/>
+ Grid}/>
+ Chart}/>
+ Forms}/>
+
+ );
+}
+
+export default MenuNavContainer;
\ No newline at end of file
diff --git a/src/components/MyCommandCell.jsx b/src/components/MyCommandCell.jsx
new file mode 100644
index 0000000..4fdd015
--- /dev/null
+++ b/src/components/MyCommandCell.jsx
@@ -0,0 +1,47 @@
+
+import React from 'react';
+import { GridCell } from '@progress/kendo-react-grid';
+
+export function MyCommandCell({ edit, remove, add, update, discard, cancel, editField }) {
+ return class extends GridCell {
+ render() {
+ const { dataItem } = this.props;
+ const inEdit = dataItem[editField];
+ const isNewItem = dataItem.ProductID === undefined;
+
+ return inEdit ? (
+
+ isNewItem ? add(dataItem) : update(dataItem)}
+ >
+ {isNewItem ? 'Add' : 'Update'}
+
+ isNewItem ? discard(dataItem) : cancel(dataItem)}
+ >
+ {isNewItem ? 'Discard' : 'Cancel'}
+
+
+ ) : (
+
+ edit(dataItem)}
+ >
+ Edit
+
+
+ remove(dataItem)
+ }
+ >
+ Remove
+
+
+ );
+ }
+ }
+};
diff --git a/src/components/ThemeChooser.jsx b/src/components/ThemeChooser.jsx
new file mode 100644
index 0000000..e5ff914
--- /dev/null
+++ b/src/components/ThemeChooser.jsx
@@ -0,0 +1,57 @@
+import React, { useRef } from 'react';
+import { DropDownList } from '@progress/kendo-react-dropdowns';
+import { Tooltip } from '@progress/kendo-react-tooltip';
+
+const valueRender = (element, value) => {
+ if (!value) {
+ return element;
+ }
+
+ const children = [
+
+
+ ,
+ {element.props.children}
+ ];
+
+ return React.cloneElement(element, { ...element.props }, children);
+}
+
+const ThemeChooser = (props) => {
+ let tooltip = useRef(null);
+ const themes = [
+ { id: 1, text: 'default', link: "https://unpkg.com/@progress/kendo-theme-default@latest/dist/all.css" },
+ { id: 2, text: 'material', link: "https://unpkg.com/@progress/kendo-theme-material@latest/dist/all.css" },
+ { id: 3, text: 'bootstrap', link: "https://unpkg.com/@progress/kendo-theme-bootstrap@latest/dist/all.css" }
+ ]
+ return (
+
+
+
+
+
{tooltip && tooltip.current.handleMouseOver(event)}}
+ onMouseOut={event => tooltip && tooltip.current.handleMouseOut(event)}>
+ Change theme
+
+
x.link === props.theme)}
+ textField={'text'} data={themes}
+ onChange={(e) => props.changeTheme(e.target.value.link)}
+ valueRender={valueRender}
+ className="d-block my-auto"
+ />
+
+
+
+ )
+}
+
+export default ThemeChooser;
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..8fec994
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import './index.scss';
+import App from './App';
+import * as serviceWorker from './serviceWorker';
+
+ReactDOM.render( , document.getElementById('root'));
+
+// If you want your app to work offline and load faster, you can change
+// unregister() to register() below. Note this comes with some pitfalls.
+// Learn more about service workers: https://bit.ly/CRA-PWA
+serviceWorker.unregister();
diff --git a/src/index.scss b/src/index.scss
new file mode 100644
index 0000000..20856c7
--- /dev/null
+++ b/src/index.scss
@@ -0,0 +1,17 @@
+body {
+ margin: 0;
+ font-family: "Roboto",-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+ "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
+ monospace;
+}
+body, html, #root {
+ height: 100%;
+}
+
diff --git a/src/logo.svg b/src/logo.svg
new file mode 100644
index 0000000..6b60c10
--- /dev/null
+++ b/src/logo.svg
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/serviceWorker.js b/src/serviceWorker.js
new file mode 100644
index 0000000..f8c7e50
--- /dev/null
+++ b/src/serviceWorker.js
@@ -0,0 +1,135 @@
+// This optional code is used to register a service worker.
+// register() is not called by default.
+
+// This lets the app load faster on subsequent visits in production, and gives
+// it offline capabilities. However, it also means that developers (and users)
+// will only see deployed updates on subsequent visits to a page, after all the
+// existing tabs open on the page have been closed, since previously cached
+// resources are updated in the background.
+
+// To learn more about the benefits of this model and instructions on how to
+// opt-in, read https://bit.ly/CRA-PWA
+
+const isLocalhost = Boolean(
+ window.location.hostname === 'localhost' ||
+ // [::1] is the IPv6 localhost address.
+ window.location.hostname === '[::1]' ||
+ // 127.0.0.1/8 is considered localhost for IPv4.
+ window.location.hostname.match(
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+ )
+);
+
+export function register(config) {
+ if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
+ // The URL constructor is available in all browsers that support SW.
+ const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
+ if (publicUrl.origin !== window.location.origin) {
+ // Our service worker won't work if PUBLIC_URL is on a different origin
+ // from what our page is served on. This might happen if a CDN is used to
+ // serve assets; see https://github.com/facebook/create-react-app/issues/2374
+ return;
+ }
+
+ window.addEventListener('load', () => {
+ const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+
+ if (isLocalhost) {
+ // This is running on localhost. Let's check if a service worker still exists or not.
+ checkValidServiceWorker(swUrl, config);
+
+ // Add some additional logging to localhost, pointing developers to the
+ // service worker/PWA documentation.
+ navigator.serviceWorker.ready.then(() => {
+ console.log(
+ 'This web app is being served cache-first by a service ' +
+ 'worker. To learn more, visit https://bit.ly/CRA-PWA'
+ );
+ });
+ } else {
+ // Is not localhost. Just register service worker
+ registerValidSW(swUrl, config);
+ }
+ });
+ }
+}
+
+function registerValidSW(swUrl, config) {
+ navigator.serviceWorker
+ .register(swUrl)
+ .then(registration => {
+ registration.onupdatefound = () => {
+ const installingWorker = registration.installing;
+ if (installingWorker == null) {
+ return;
+ }
+ installingWorker.onstatechange = () => {
+ if (installingWorker.state === 'installed') {
+ if (navigator.serviceWorker.controller) {
+ // At this point, the updated precached content has been fetched,
+ // but the previous service worker will still serve the older
+ // content until all client tabs are closed.
+ console.log(
+ 'New content is available and will be used when all ' +
+ 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
+ );
+
+ // Execute callback
+ if (config && config.onUpdate) {
+ config.onUpdate(registration);
+ }
+ } else {
+ // At this point, everything has been precached.
+ // It's the perfect time to display a
+ // "Content is cached for offline use." message.
+ console.log('Content is cached for offline use.');
+
+ // Execute callback
+ if (config && config.onSuccess) {
+ config.onSuccess(registration);
+ }
+ }
+ }
+ };
+ };
+ })
+ .catch(error => {
+ console.error('Error during service worker registration:', error);
+ });
+}
+
+function checkValidServiceWorker(swUrl, config) {
+ // Check if the service worker can be found. If it can't reload the page.
+ fetch(swUrl)
+ .then(response => {
+ // Ensure service worker exists, and that we really are getting a JS file.
+ const contentType = response.headers.get('content-type');
+ if (
+ response.status === 404 ||
+ (contentType != null && contentType.indexOf('javascript') === -1)
+ ) {
+ // No service worker found. Probably a different app. Reload the page.
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister().then(() => {
+ window.location.reload();
+ });
+ });
+ } else {
+ // Service worker found. Proceed as normal.
+ registerValidSW(swUrl, config);
+ }
+ })
+ .catch(() => {
+ console.log(
+ 'No internet connection found. App is running in offline mode.'
+ );
+ });
+}
+
+export function unregister() {
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister();
+ });
+ }
+}
diff --git a/src/styles/bootstrap-custom.scss b/src/styles/bootstrap-custom.scss
new file mode 100644
index 0000000..7752d85
--- /dev/null
+++ b/src/styles/bootstrap-custom.scss
@@ -0,0 +1,29 @@
+@import "~bootstrap/scss/functions";
+@import "~bootstrap/scss/variables";
+@import "~bootstrap/scss/mixins";
+
+@import "~bootstrap/scss/reboot";
+@import "~bootstrap/scss/utilities";
+@import "~bootstrap/scss/card";
+
+
+$grid-columns: 12;
+$grid-gutter-width: 48px;
+$grid-column-width: 48px;
+
+$grid-breakpoints: (
+ xs: 0,
+ sm: 576px,
+ md: 768px,
+ lg: 992px,
+ xl: 1200px
+);
+
+$container-max-widths: (
+ sm: 540px,
+ md: 720px,
+ lg: 960px,
+ xl: 1140px
+);
+
+@import "~bootstrap/scss/grid";
\ No newline at end of file