feat: add search functionality for id, host, and description fields (#2750)

Co-authored-by: Anil Durmus <anil.durmus@trendyol.com>
diff --git a/api/internal/handler/route/route.go b/api/internal/handler/route/route.go
index fae4429..d100c85 100644
--- a/api/internal/handler/route/route.go
+++ b/api/internal/handler/route/route.go
@@ -194,6 +194,9 @@
 	URI    string `auto_read:"uri,query"`
 	Label  string `auto_read:"label,query"`
 	Status string `auto_read:"status,query"`
+	Host string `auto_read:"host,query"`
+	ID string `auto_read:"id,query"`
+	Desc string `auto_read:"desc,query"`
 	store.Pagination
 }
 
@@ -236,6 +239,20 @@
 				return false
 			}
 
+			if input.Host != "" && !strings.Contains(obj.(*entity.Route).Host, input.Host) {
+				return false
+			}
+
+			if input.Desc != "" && !strings.Contains(obj.(*entity.Route).Desc, input.Desc) {
+				return false
+			}
+
+			if obj != nil && obj.(*entity.Route) != nil && obj.(*entity.Route).ID != nil && input.ID != "" {
+				if !strings.Contains(utils.InterfaceToString(obj.(*entity.Route).ID), input.ID) {
+					return false // IDs do not match, so object should not be included in the filtered result
+				}
+			}
+
 			return true
 		},
 		Format: func(obj interface{}) interface{} {
diff --git a/api/internal/handler/service/service.go b/api/internal/handler/service/service.go
index fe382b0..ab94bfd 100644
--- a/api/internal/handler/service/service.go
+++ b/api/internal/handler/service/service.go
@@ -90,6 +90,8 @@
 
 type ListInput struct {
 	Name string `auto_read:"name,query"`
+	ID string `auto_read:"id,query"`
+	Desc string `auto_read:"desc,query"`
 	store.Pagination
 }
 
@@ -135,6 +137,14 @@
 			if input.Name != "" {
 				return strings.Contains(obj.(*entity.Service).Name, input.Name)
 			}
+
+			if input.Desc != "" {
+				return strings.Contains(obj.(*entity.Service).Desc, input.Desc)
+			}
+
+			if input.ID != "" {
+				return strings.Contains(utils.InterfaceToString(obj.(*entity.Service).ID), input.ID)
+			}
 			return true
 		},
 		Format: func(obj interface{}) interface{} {
diff --git a/api/internal/handler/upstream/upstream.go b/api/internal/handler/upstream/upstream.go
index 3157fdd..55c08a5 100644
--- a/api/internal/handler/upstream/upstream.go
+++ b/api/internal/handler/upstream/upstream.go
@@ -96,6 +96,8 @@
 
 type ListInput struct {
 	Name string `auto_read:"name,query"`
+	ID string `auto_read:"id,query"`
+	Desc string `auto_read:"desc,query"`
 	store.Pagination
 }
 
@@ -141,6 +143,13 @@
 			if input.Name != "" {
 				return strings.Contains(obj.(*entity.Upstream).Name, input.Name)
 			}
+
+			if input.Desc != "" {
+				return strings.Contains(obj.(*entity.Upstream).Desc, input.Desc)
+			}
+			if input.ID != "" {
+				return strings.Contains(utils.InterfaceToString(obj.(*entity.Upstream).ID), input.ID)
+			}
 			return true
 		},
 		Format: func(obj interface{}) interface{} {
diff --git a/web/cypress/e2e/route/search-route.cy.js b/web/cypress/e2e/route/search-route.cy.js
index d947d97..6228814 100644
--- a/web/cypress/e2e/route/search-route.cy.js
+++ b/web/cypress/e2e/route/search-route.cy.js
@@ -148,6 +148,8 @@
     cy.contains('Route').click();
     cy.wait(timeout);
     // full match
+    // expand search
+    cy.get(selector.expandSearch).click();
     cy.get(selector.pathSearchInput).type(data.uris1);
     cy.contains('Search').click();
     cy.contains(data.uris1).should('contain', data.uris1);
@@ -197,6 +199,7 @@
         force: true,
         multiple: true,
       });
+      cy.wait(timeout);
     }
   });
 });
diff --git a/web/src/pages/Route/List.tsx b/web/src/pages/Route/List.tsx
index cbacd4f..7ff4d7d 100755
--- a/web/src/pages/Route/List.tsx
+++ b/web/src/pages/Route/List.tsx
@@ -322,13 +322,12 @@
     },
     {
       title: formatMessage({ id: 'component.global.id' }),
-      hideInSearch: true,
       dataIndex: 'id',
       width: 200,
     },
     {
       title: formatMessage({ id: 'page.route.host' }),
-      hideInSearch: true,
+      dataIndex: 'host',
       width: 224,
       render: (_, record) => {
         const list = record.hosts || (record.host && [record.host]) || [];
@@ -361,7 +360,6 @@
     {
       title: formatMessage({ id: 'component.global.description' }),
       dataIndex: 'desc',
-      hideInSearch: true,
       ellipsis: true,
       width: 200,
     },
diff --git a/web/src/pages/Route/service.ts b/web/src/pages/Route/service.ts
index dbd182a..794db91 100644
--- a/web/src/pages/Route/service.ts
+++ b/web/src/pages/Route/service.ts
@@ -41,7 +41,7 @@
   request(`/routes/${rid}`).then((data) => transformRouteData(data.data));
 
 export const fetchList = ({ current = 1, pageSize = 10, ...res }) => {
-  const { labels = [], API_VERSION = [], status } = res;
+  const { labels = [], API_VERSION = [], host = "", id = "", desc = "", status} = res;
 
   return request<Res<ResListData<RouteModule.ResponseBody>>>('/routes', {
     params: {
@@ -51,6 +51,9 @@
       page: current,
       page_size: pageSize,
       status,
+      host,
+      desc,
+      id,
     },
   }).then(({ data }) => {
     return {
diff --git a/web/src/pages/Service/List.tsx b/web/src/pages/Service/List.tsx
index c509a95..05feb47 100644
--- a/web/src/pages/Service/List.tsx
+++ b/web/src/pages/Service/List.tsx
@@ -42,9 +42,8 @@
 
   const columns: ProColumns<ServiceModule.ResponseBody>[] = [
     {
-      title: 'ID',
+      title: formatMessage({ id: 'component.global.id' }),
       dataIndex: 'id',
-      hideInSearch: true,
     },
     {
       title: formatMessage({ id: 'component.global.name' }),
@@ -53,7 +52,6 @@
     {
       title: formatMessage({ id: 'component.global.description' }),
       dataIndex: 'desc',
-      hideInSearch: true,
     },
     {
       title: formatMessage({ id: 'component.global.operation' }),
diff --git a/web/src/pages/Service/service.ts b/web/src/pages/Service/service.ts
index b652335..def2860 100644
--- a/web/src/pages/Service/service.ts
+++ b/web/src/pages/Service/service.ts
@@ -21,6 +21,8 @@
 export const fetchList = ({ current = 1, pageSize = 10, ...res }) =>
   request('/services', {
     params: {
+      id: res.id || '',
+      desc: res.desc || '',
       name: res.name,
       page: current,
       page_size: pageSize,
diff --git a/web/src/pages/Upstream/List.tsx b/web/src/pages/Upstream/List.tsx
index c593b1e..5c31749 100644
--- a/web/src/pages/Upstream/List.tsx
+++ b/web/src/pages/Upstream/List.tsx
@@ -45,7 +45,6 @@
     {
       title: formatMessage({ id: 'page.upstream.list.id' }),
       dataIndex: 'id',
-      hideInSearch: true,
     },
     {
       title: formatMessage({ id: 'page.upstream.list.name' }),
@@ -59,7 +58,6 @@
     {
       title: formatMessage({ id: 'page.upstream.list.description' }),
       dataIndex: 'desc',
-      hideInSearch: true,
     },
     {
       title: formatMessage({ id: 'page.upstream.list.edit.time' }),
diff --git a/web/src/pages/Upstream/service.ts b/web/src/pages/Upstream/service.ts
index a04925f..a4d5ffe 100644
--- a/web/src/pages/Upstream/service.ts
+++ b/web/src/pages/Upstream/service.ts
@@ -21,6 +21,8 @@
 export const fetchList = ({ current = 1, pageSize = 10, ...res }) => {
   return request<Res<ResListData<UpstreamModule.RequestBody>>>('/upstreams', {
     params: {
+      id: res.id || '',
+      desc: res.desc || '',
       name: res.name,
       page: current,
       page_size: pageSize,