| undefined;
+ e.editorOptions.onValueChanged = (args: { value: string }) => {
+ clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(() => {
+ searchValueRef.current = args.value;
+ e.component.getDataSource().reload();
+ }, e.updateValueTimeout);
+ };
+ e.editorOptions.placeholder = 'Try: clothing';
+ }
+ }, []);
+
+ return (
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ );
+};
+
+export default App;
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/React/index.html b/apps/demos/Demos/DataGrid/SemanticSearch/React/index.html
new file mode 100644
index 000000000000..ee451f8288ff
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/React/index.html
@@ -0,0 +1,24 @@
+
+
+
+ DevExtreme Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/React/index.tsx b/apps/demos/Demos/DataGrid/SemanticSearch/React/index.tsx
new file mode 100644
index 000000000000..8acbec4b6179
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/React/index.tsx
@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+
+import App from './App.tsx';
+
+ReactDOM.render(
+ ,
+ document.getElementById('app'),
+);
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/React/styles.css b/apps/demos/Demos/DataGrid/SemanticSearch/React/styles.css
new file mode 100644
index 000000000000..49409f518a7b
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/React/styles.css
@@ -0,0 +1,3 @@
+.align-bottom.dx-toolbar-item {
+ vertical-align: bottom;
+}
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/App.js b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/App.js
new file mode 100644
index 000000000000..3784c7084244
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/App.js
@@ -0,0 +1,99 @@
+import React, { useCallback, useRef, useMemo } from 'react';
+import DataGrid, {
+ Column,
+ Scrolling,
+ SearchPanel,
+ Toolbar,
+ Item,
+} from 'devextreme-react/data-grid';
+import NumberBox from 'devextreme-react/number-box';
+import DataSource from 'devextreme/data/data_source';
+import { createStore } from 'devextreme-aspnet-data-nojquery';
+
+const url = 'https://js.devexpress.com/Demos/NetCore/api/DataGridSemanticSearch';
+const App = () => {
+ const searchValueRef = useRef('');
+ const similarityFactorRef = useRef(0.31);
+ const dataSource = useMemo(
+ () =>
+ new DataSource({
+ store: createStore({
+ key: 'ID',
+ loadUrl: `${url}/Get`,
+ loadParams: {
+ searchValue: () => searchValueRef.current,
+ similarityFactor: () => similarityFactorRef.current,
+ },
+ onBeforeSend(method, ajaxOptions) {
+ ajaxOptions.xhrFields = { withCredentials: true };
+ },
+ }),
+ }),
+ [],
+ );
+ const onSimilarityFactorChanged = useCallback(({ value }) => {
+ similarityFactorRef.current = value;
+ if (searchValueRef.current !== '') {
+ dataSource.reload();
+ }
+ }, []);
+ const onEditorPreparing = useCallback((e) => {
+ if (e.parentType === 'searchPanel') {
+ let searchTimeout;
+ e.editorOptions.onValueChanged = (args) => {
+ clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(() => {
+ searchValueRef.current = args.value;
+ e.component.getDataSource().reload();
+ }, e.updateValueTimeout);
+ };
+ e.editorOptions.placeholder = 'Try: clothing';
+ }
+ }, []);
+ return (
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+ );
+};
+export default App;
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/index.html b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/index.html
new file mode 100644
index 000000000000..db31b0fd60c6
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/index.html
@@ -0,0 +1,44 @@
+
+
+
+ DevExtreme Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/index.js b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/index.js
new file mode 100644
index 000000000000..b853e0be8242
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/index.js
@@ -0,0 +1,5 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './App.js';
+
+ReactDOM.render(, document.getElementById('app'));
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/styles.css b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/styles.css
new file mode 100644
index 000000000000..49409f518a7b
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/ReactJs/styles.css
@@ -0,0 +1,3 @@
+.align-bottom.dx-toolbar-item {
+ vertical-align: bottom;
+}
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/Vue/App.vue b/apps/demos/Demos/DataGrid/SemanticSearch/Vue/App.vue
new file mode 100644
index 000000000000..64fd7e83915b
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/Vue/App.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/Vue/index.html b/apps/demos/Demos/DataGrid/SemanticSearch/Vue/index.html
new file mode 100644
index 000000000000..b21c5e373a7a
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/Vue/index.html
@@ -0,0 +1,29 @@
+
+
+
+ DevExtreme Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/Vue/index.ts b/apps/demos/Demos/DataGrid/SemanticSearch/Vue/index.ts
new file mode 100644
index 000000000000..684d04215d72
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/Vue/index.ts
@@ -0,0 +1,4 @@
+import { createApp } from 'vue';
+import App from './App.vue';
+
+createApp(App).mount('#app');
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/index.html b/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/index.html
new file mode 100644
index 000000000000..5bfc9fb29a7c
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/index.html
@@ -0,0 +1,20 @@
+
+
+
+ DevExtreme Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/index.js b/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/index.js
new file mode 100644
index 000000000000..2dd62a5bcb18
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/index.js
@@ -0,0 +1,74 @@
+$(() => {
+ const url = 'https://js.devexpress.com/Demos/NetCore/api/DataGridSemanticSearch';
+
+ let searchValue = '';
+ let similarityFactor = 0.31;
+
+ const dataGrid = $('#gridContainer').dxDataGrid({
+ dataSource: DevExpress.data.AspNet.createStore({
+ key: 'ID',
+ loadUrl: `${url}/Get`,
+ loadParams: {
+ searchValue: () => searchValue,
+ similarityFactor: () => similarityFactor,
+ },
+ onBeforeSend(method, ajaxOptions) {
+ ajaxOptions.xhrFields = { withCredentials: true };
+ },
+ }),
+ showBorders: true,
+ remoteOperations: true,
+ height: 600,
+ columns: ['ID', 'Name', 'Description'],
+ scrolling: {
+ mode: 'virtual',
+ },
+ searchPanel: {
+ visible: true,
+ },
+ toolbar: {
+ items: [
+ {
+ location: 'after',
+ cssClass: 'align-bottom',
+ template: function (data, container) {
+ $('')
+ .appendTo(container)
+ .dxNumberBox({
+ label: 'Similarity Factor',
+ labelMode: 'floating',
+ value: similarityFactor,
+ min: 0,
+ max: 1,
+ format: '0.00',
+ step: 0.05,
+ onValueChanged(e) {
+ similarityFactor = e.value;
+ if (searchValue !== '') {
+ dataGrid.getDataSource().reload();
+ }
+ },
+ });
+ }
+ },
+ {
+ name: 'searchPanel',
+ cssClass: 'align-bottom',
+ },
+ ],
+ },
+ onEditorPreparing(e) {
+ if (e.parentType === 'searchPanel') {
+ let searchTimeout;
+ e.editorOptions.onValueChanged = (args) => {
+ clearTimeout(searchTimeout);
+ searchTimeout = setTimeout(() => {
+ searchValue = args.value;
+ e.component.getDataSource().reload();
+ }, e.updateValueTimeout);
+ };
+ e.editorOptions.placeholder = 'Try: clothing';
+ }
+ },
+ }).dxDataGrid('instance');
+});
diff --git a/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/styles.css b/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/styles.css
new file mode 100644
index 000000000000..49409f518a7b
--- /dev/null
+++ b/apps/demos/Demos/DataGrid/SemanticSearch/jQuery/styles.css
@@ -0,0 +1,3 @@
+.align-bottom.dx-toolbar-item {
+ vertical-align: bottom;
+}
diff --git a/apps/demos/menuMeta.json b/apps/demos/menuMeta.json
index bb9175e74ef8..ccc66e33ea50 100644
--- a/apps/demos/menuMeta.json
+++ b/apps/demos/menuMeta.json
@@ -38,6 +38,29 @@
"Modules": "openai"
}
]
+ },
+ {
+ "Name": "Semantic Search",
+ "Equivalents": "",
+ "Demos": [
+ {
+ "Title": "Semantic Search",
+ "Name": "SemanticSearch",
+ "Widget": "DataGrid",
+ "Badge": "AI",
+ "DemoType": "Web",
+ "Modules": "devextreme-aspnet-data-nojquery",
+ "MvcAdditionalFiles": [
+ "/DataProviders/SmartFilterProvider.cs",
+ "/Controllers/ApiControllers/DataGridSemanticSearchController.cs",
+ "/Services/EmbeddingsInitializerService.cs",
+ "/Models/DataGrid/DictionaryItem.cs",
+ "/Models/SampleData/DictionaryItems.cs"
+ ],
+ "TopLevel": true,
+ "Equivalents": "AI-Powered Search, Smart Search, Context-Aware Search, Natural Language Search, AI Search, Semantic Retrieval, Similarity Search"
+ }
+ ]
}
]
},
@@ -315,6 +338,22 @@
"/Models/SampleData/DataGridEmployees.cs"
],
"DemoType": "Web"
+ },
+ {
+ "Title": "Semantic Search",
+ "Name": "SemanticSearch",
+ "Widget": "DataGrid",
+ "Badge": "AI",
+ "DemoType": "Web",
+ "Modules": "devextreme-aspnet-data-nojquery",
+ "MvcAdditionalFiles": [
+ "/DataProviders/SmartFilterProvider.cs",
+ "/Controllers/ApiControllers/DataGridSemanticSearchController.cs",
+ "/Services/EmbeddingsInitializerService.cs",
+ "/Models/DataGrid/DictionaryItem.cs",
+ "/Models/SampleData/DictionaryItems.cs"
+ ],
+ "Equivalents": "AI-Powered Search, Smart Search, Context-Aware Search, Natural Language Search, AI Search, Semantic Retrieval, Similarity Search"
}
]
},