mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-12-03 11:05:08 +00:00
Fixes 23497: Added Search and Sort Functionality at Schema Level (#23907)
* Feat: Added search functionality for schema tables and stored procedures * Fix: memoize the searchProps of the table component * Fix: fixed the table pagination issue * Fix: Added search funtionality in service page * Playwright: Added test for service page search * Fix: Fixed the falling unit tests * Fix: Fixed code smells * fix: Fixed the current page reset issue * fix: removed the getSearchPlaceholderKey util function * fix: fixed the merge conflicts * "fix: Added sorter on name column in all the tables" * fix: Added search field in data models and api endpoint tab * fix: Added search field in files and spreadsheets table * playwright: Added e2e test for table search * fix: fixed the failed unit test * add new field service.fullyQualifiedName.keyword in index mapping * fix: fixed the table search and sort playwright * fix: fixed the api endpoint schema playwright test * fix: fixed tha table search and sort playwright * fix: removed serial from the table search and sort tests --------- Co-authored-by: sonikashah <sonikashah94@gmail.com> Co-authored-by: Aniket Katkar <aniketkatkar97@gmail.com>
This commit is contained in:
parent
d1d2e69d3d
commit
3a9918d23d
@ -410,7 +410,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -542,7 +542,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -318,7 +318,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -557,7 +557,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
|
||||
@ -356,7 +356,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -538,7 +538,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -413,7 +413,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -350,7 +350,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -175,7 +175,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -175,7 +175,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -277,7 +277,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -534,7 +534,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -479,7 +479,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -151,7 +151,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -425,7 +425,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -175,7 +175,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -242,7 +242,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -338,7 +345,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -274,7 +274,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -370,7 +377,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -405,7 +405,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -175,7 +175,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -395,7 +395,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -523,7 +523,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -327,7 +327,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -528,7 +528,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -449,7 +449,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -523,7 +523,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -406,7 +406,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -344,7 +344,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -228,7 +228,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -240,7 +240,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -249,7 +249,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -516,7 +516,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -442,7 +442,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -116,7 +116,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -300,7 +300,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -228,7 +228,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -236,7 +236,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -332,7 +339,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -244,7 +244,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -340,7 +347,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -449,7 +449,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -298,7 +298,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -427,7 +427,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -560,7 +560,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -336,7 +336,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -567,7 +567,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
|
||||
@ -373,7 +373,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -556,7 +556,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -424,7 +424,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -362,7 +362,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -174,7 +174,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -174,7 +174,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -296,7 +296,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -552,7 +552,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -497,7 +497,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -164,7 +164,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -447,7 +447,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -174,7 +174,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -260,7 +260,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -356,7 +363,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -284,7 +284,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -380,7 +387,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -423,7 +423,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -174,7 +174,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -388,7 +388,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -518,7 +518,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -327,7 +327,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -530,7 +530,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -449,7 +449,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -480,7 +480,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -401,7 +401,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -336,7 +336,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -213,7 +213,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -225,7 +225,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -252,7 +252,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
|
||||
@ -510,7 +510,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -441,7 +441,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
|
||||
@ -121,7 +121,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -296,7 +296,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -213,7 +213,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -222,7 +222,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
@ -318,7 +325,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -398,7 +398,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
@ -498,7 +505,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -338,7 +338,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text",
|
||||
|
||||
@ -285,7 +285,14 @@
|
||||
}
|
||||
},
|
||||
"fullyQualifiedName": {
|
||||
"type": "text"
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"normalizer": "lowercase_normalizer",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
|
||||
@ -0,0 +1,330 @@
|
||||
/*
|
||||
* Copyright 2025 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ApiEndpointClass } from '../../support/entity/ApiEndpointClass';
|
||||
import { DashboardDataModelClass } from '../../support/entity/DashboardDataModelClass';
|
||||
import { DirectoryClass } from '../../support/entity/DirectoryClass';
|
||||
import { EntityTypeEndpoint } from '../../support/entity/Entity.interface';
|
||||
import { EntityDataClass } from '../../support/entity/EntityDataClass';
|
||||
import { FileClass } from '../../support/entity/FileClass';
|
||||
import { SpreadsheetClass } from '../../support/entity/SpreadsheetClass';
|
||||
import { StoredProcedureClass } from '../../support/entity/StoredProcedureClass';
|
||||
import { TableClass } from '../../support/entity/TableClass';
|
||||
import { TopicClass } from '../../support/entity/TopicClass';
|
||||
import {
|
||||
getApiContext,
|
||||
redirectToHomePage,
|
||||
testTableSearch,
|
||||
} from '../../utils/common';
|
||||
import { test } from '../fixtures/pages';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
test.describe('Table Search', () => {
|
||||
test.describe('Services page', () => {
|
||||
test('Services page should have search functionality', async ({ page }) => {
|
||||
const service1 = EntityDataClass.databaseService.get();
|
||||
const service2 = EntityDataClass.storedProcedure1.get().service;
|
||||
|
||||
await page.goto('/settings/services/databases');
|
||||
await testTableSearch(
|
||||
page,
|
||||
'database_service_search_index',
|
||||
service1.name,
|
||||
service2.name
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('API Collection page', () => {
|
||||
test('API Collection page should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const apiEndpoint1 = EntityDataClass.apiEndpoint1.get();
|
||||
const apiEndpoint2 = new ApiEndpointClass();
|
||||
|
||||
apiEndpoint2.service.name = apiEndpoint1.service.name;
|
||||
apiEndpoint2.apiCollection.name = apiEndpoint1.apiCollection.name;
|
||||
apiEndpoint2.apiCollection.service = apiEndpoint1.service.name;
|
||||
apiEndpoint2.entity.apiCollection = `${apiEndpoint1.service.name}.${apiEndpoint1.apiCollection.name}`;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.API_ENDPOINT}`,
|
||||
{
|
||||
data: apiEndpoint2.entity,
|
||||
}
|
||||
);
|
||||
apiEndpoint2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(
|
||||
`/apiCollection/${apiEndpoint1.apiCollection.fullyQualifiedName}`
|
||||
);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'api_endpoint_search_index',
|
||||
apiEndpoint1.entity.name,
|
||||
apiEndpoint2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Database Schema Tables tab', () => {
|
||||
test('Database Schema Tables tab should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const table1 = EntityDataClass.table1.get();
|
||||
const table2 = new TableClass();
|
||||
|
||||
table2.service.name = table1.service.name;
|
||||
table2.database.name = table1.database.name;
|
||||
table2.database.service = table1.service.name;
|
||||
table2.schema.name = table1.schema.name;
|
||||
table2.schema.database = `${table1.service.name}.${table1.database.name}`;
|
||||
table2.entity.databaseSchema = table1.schema.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Table}`,
|
||||
{
|
||||
data: table2.entity,
|
||||
}
|
||||
);
|
||||
table2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(`/databaseSchema/${table1.schema.fullyQualifiedName}`);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'table_search_index',
|
||||
table1.entity.name,
|
||||
table2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Data Models Table', () => {
|
||||
test('Data Models Table should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const dataModel1 = EntityDataClass.dashboardDataModel1.get();
|
||||
const dataModel2 = new DashboardDataModelClass();
|
||||
|
||||
dataModel2.service.name = dataModel1.service.name;
|
||||
dataModel2.entity.service = dataModel1.service.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.DataModel}`,
|
||||
{
|
||||
data: dataModel2.entity,
|
||||
}
|
||||
);
|
||||
dataModel2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/dashboardServices/${dataModel1.service.name}/data-model`
|
||||
);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'dashboard_data_model_search_index',
|
||||
dataModel1.entity.name,
|
||||
dataModel2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Stored Procedure Table', () => {
|
||||
test('Stored Procedure Table should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const storedProcedure1 = EntityDataClass.storedProcedure1.get();
|
||||
const storedProcedure2 = new StoredProcedureClass();
|
||||
|
||||
storedProcedure2.service.name = storedProcedure1.service.name;
|
||||
storedProcedure2.database.name = storedProcedure1.database.name;
|
||||
storedProcedure2.database.service = storedProcedure1.service.name;
|
||||
storedProcedure2.schema.name = storedProcedure1.schema.name;
|
||||
storedProcedure2.schema.database = `${storedProcedure1.service.name}.${storedProcedure1.database.name}`;
|
||||
storedProcedure2.entity.databaseSchema =
|
||||
storedProcedure1.schema.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.StoreProcedure}`,
|
||||
{
|
||||
data: storedProcedure2.entity,
|
||||
}
|
||||
);
|
||||
storedProcedure2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(
|
||||
`/databaseSchema/${storedProcedure1.schema.fullyQualifiedName}/stored_procedure`
|
||||
);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'stored_procedure_search_index',
|
||||
storedProcedure1.entity.name,
|
||||
storedProcedure2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Topics Table', () => {
|
||||
test('Topics Table should have search functionality', async ({ page }) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const topic1 = EntityDataClass.topic1.get();
|
||||
const topic2 = new TopicClass();
|
||||
|
||||
topic2.service.name = topic1.service.name;
|
||||
topic2.entity.service = topic1.service.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Topic}`,
|
||||
{
|
||||
data: topic2.entity,
|
||||
}
|
||||
);
|
||||
topic2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/messagingServices/${topic1.service.name}/topics`
|
||||
);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'topic_search_index',
|
||||
topic1.entity.name,
|
||||
topic2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Drives Service Directories Table', () => {
|
||||
test('Drives Service Directories Table should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const directory1 = EntityDataClass.directory1.get();
|
||||
const directory2 = new DirectoryClass();
|
||||
|
||||
directory2.service.name = directory1.service.name;
|
||||
directory2.entity.service = directory1.service.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Directory}`,
|
||||
{
|
||||
data: {
|
||||
name: directory2.entity.name,
|
||||
description: directory2.entity.description,
|
||||
service: directory2.entity.service,
|
||||
},
|
||||
}
|
||||
);
|
||||
directory2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/driveServices/${directory1.service.name}/directories`
|
||||
);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'directory_search_index',
|
||||
directory1.entity.name,
|
||||
directory2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Drives Service Files Table', () => {
|
||||
test('Drives Service Files Table should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const file1 = EntityDataClass.file1.get();
|
||||
const file2 = new FileClass();
|
||||
|
||||
file2.service.name = file1.service.name;
|
||||
file2.entity.service = file1.service.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.File}`,
|
||||
{
|
||||
data: {
|
||||
name: file2.entity.name,
|
||||
description: file2.entity.description,
|
||||
service: file2.entity.service,
|
||||
},
|
||||
}
|
||||
);
|
||||
file2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(`/service/driveServices/${file1.service.name}/files`);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'file_search_index',
|
||||
file1.entity.name,
|
||||
file2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Drives Service Spreadsheets Table', () => {
|
||||
test('Drives Service Spreadsheets Table should have search functionality', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const spreadsheet1 = EntityDataClass.spreadsheet1.get();
|
||||
const spreadsheet2 = new SpreadsheetClass();
|
||||
|
||||
spreadsheet2.service.name = spreadsheet1.service.name;
|
||||
spreadsheet2.entity.service = spreadsheet1.service.fullyQualifiedName;
|
||||
|
||||
const response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Spreadsheet}`,
|
||||
{
|
||||
data: {
|
||||
name: spreadsheet2.entity.name,
|
||||
description: spreadsheet2.entity.description,
|
||||
service: spreadsheet2.entity.service,
|
||||
},
|
||||
}
|
||||
);
|
||||
spreadsheet2.entityResponseData = await response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/driveServices/${spreadsheet1.service.name}/spreadsheets`
|
||||
);
|
||||
await testTableSearch(
|
||||
page,
|
||||
'spreadsheet_search_index',
|
||||
spreadsheet1.entity.name,
|
||||
spreadsheet2.entity.name
|
||||
);
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright 2025 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { ApiEndpointClass } from '../../support/entity/ApiEndpointClass';
|
||||
import { DashboardDataModelClass } from '../../support/entity/DashboardDataModelClass';
|
||||
import { DatabaseSchemaClass } from '../../support/entity/DatabaseSchemaClass';
|
||||
import { EntityTypeEndpoint } from '../../support/entity/Entity.interface';
|
||||
import { EntityDataClass } from '../../support/entity/EntityDataClass';
|
||||
import { FileClass } from '../../support/entity/FileClass';
|
||||
import { SpreadsheetClass } from '../../support/entity/SpreadsheetClass';
|
||||
import { StoredProcedureClass } from '../../support/entity/StoredProcedureClass';
|
||||
import { TableClass } from '../../support/entity/TableClass';
|
||||
import { TopicClass } from '../../support/entity/TopicClass';
|
||||
import {
|
||||
getApiContext,
|
||||
redirectToHomePage,
|
||||
testTableSorting,
|
||||
} from '../../utils/common';
|
||||
import { test } from '../fixtures/pages';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await redirectToHomePage(page);
|
||||
});
|
||||
|
||||
test.describe('Table Sorting', () => {
|
||||
test.describe('Database Schema page', () => {
|
||||
test('Database Schema page should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const database = EntityDataClass.database.get();
|
||||
const schema = new DatabaseSchemaClass();
|
||||
|
||||
schema.service.name = database.service.name;
|
||||
schema.database.name = database.entity.name;
|
||||
schema.database.service = database.service.name;
|
||||
schema.entity.database = database.entity.fullyQualifiedName;
|
||||
|
||||
const schemaResponse = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.DatabaseSchema}`,
|
||||
{
|
||||
data: schema.entity,
|
||||
}
|
||||
);
|
||||
schema.entityResponseData = await schemaResponse.json();
|
||||
|
||||
await page.goto(`/database/${database.entity.fullyQualifiedName}`);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test('Services page should have sorting on name column', async ({ page }) => {
|
||||
await page.goto('/settings/services/databases');
|
||||
await testTableSorting(page, 'Name');
|
||||
});
|
||||
|
||||
test.describe('API Endpoint page', () => {
|
||||
test('API Endpoint page should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const apiEndpoint1 = EntityDataClass.apiEndpoint1.get();
|
||||
const apiEndpoint2 = new ApiEndpointClass();
|
||||
|
||||
apiEndpoint2.service.name = apiEndpoint1.service.name;
|
||||
apiEndpoint2.apiCollection.name = apiEndpoint1.apiCollection.name;
|
||||
apiEndpoint2.apiCollection.service = apiEndpoint1.service.name;
|
||||
apiEndpoint2.entity.apiCollection = `${apiEndpoint1.service.name}.${apiEndpoint1.apiCollection.name}`;
|
||||
|
||||
const apiEndpoint2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.API_ENDPOINT}`,
|
||||
{
|
||||
data: apiEndpoint2.entity,
|
||||
}
|
||||
);
|
||||
apiEndpoint2.entityResponseData = await apiEndpoint2Response.json();
|
||||
|
||||
await page.goto(
|
||||
`/apiCollection/${apiEndpoint1.apiCollection.fullyQualifiedName}`
|
||||
);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('API Endpoint schema', () => {
|
||||
test('API Endpoint schema should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const apiEndpoint = EntityDataClass.apiEndpoint1.get();
|
||||
|
||||
await page.goto(`/apiEndpoint/${apiEndpoint.entity.fullyQualifiedName}`);
|
||||
await testTableSorting(page, 'Name');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Database Schema Tables tab', () => {
|
||||
test('Database Schema Tables tab should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const table1 = EntityDataClass.table1.get();
|
||||
const table2 = new TableClass();
|
||||
|
||||
table2.service.name = table1.service.name;
|
||||
table2.database.name = table1.database.name;
|
||||
table2.database.service = table1.service.name;
|
||||
table2.schema.name = table1.schema.name;
|
||||
table2.schema.database = `${table1.service.name}.${table1.database.name}`;
|
||||
table2.entity.databaseSchema = table1.schema.fullyQualifiedName;
|
||||
|
||||
const table2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Table}`,
|
||||
{
|
||||
data: table2.entity,
|
||||
}
|
||||
);
|
||||
table2.entityResponseData = await table2Response.json();
|
||||
|
||||
await page.goto(`/databaseSchema/${table1.schema.fullyQualifiedName}`);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test('Data Observability services page should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.goto('/settings/services/dataObservability?tab=pipelines');
|
||||
await testTableSorting(page, 'Name');
|
||||
});
|
||||
|
||||
test.describe('Data Models Table', () => {
|
||||
test('Data Models Table should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const dataModel1 = EntityDataClass.dashboardDataModel1.get();
|
||||
const dataModel2 = new DashboardDataModelClass();
|
||||
|
||||
dataModel2.service.name = dataModel1.service.name;
|
||||
dataModel2.entity.service = dataModel1.service.fullyQualifiedName;
|
||||
|
||||
const dataModel2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.DataModel}`,
|
||||
{
|
||||
data: dataModel2.entity,
|
||||
}
|
||||
);
|
||||
dataModel2.entityResponseData = await dataModel2Response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/dashboardServices/${dataModel1.service.name}/data-model`
|
||||
);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Stored Procedure Table', () => {
|
||||
test('Stored Procedure Table should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const storedProcedure1 = EntityDataClass.storedProcedure1.get();
|
||||
const storedProcedure2 = new StoredProcedureClass();
|
||||
|
||||
storedProcedure2.service.name = storedProcedure1.service.name;
|
||||
storedProcedure2.database.name = storedProcedure1.database.name;
|
||||
storedProcedure2.database.service = storedProcedure1.service.name;
|
||||
storedProcedure2.schema.name = storedProcedure1.schema.name;
|
||||
storedProcedure2.schema.database = `${storedProcedure1.service.name}.${storedProcedure1.database.name}`;
|
||||
storedProcedure2.entity.databaseSchema =
|
||||
storedProcedure1.schema.fullyQualifiedName;
|
||||
|
||||
const storedProcedure2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.StoreProcedure}`,
|
||||
{
|
||||
data: storedProcedure2.entity,
|
||||
}
|
||||
);
|
||||
storedProcedure2.entityResponseData =
|
||||
await storedProcedure2Response.json();
|
||||
|
||||
await page.goto(
|
||||
`/databaseSchema/${storedProcedure1.schema.fullyQualifiedName}/stored_procedure`
|
||||
);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Topics Table', () => {
|
||||
test('Topics Table should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const topic1 = EntityDataClass.topic1.get();
|
||||
const topic2 = new TopicClass();
|
||||
|
||||
topic2.service.name = topic1.service.name;
|
||||
topic2.entity.service = topic1.service.fullyQualifiedName;
|
||||
|
||||
const topic2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Topic}`,
|
||||
{
|
||||
data: topic2.entity,
|
||||
}
|
||||
);
|
||||
topic2.entityResponseData = await topic2Response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/messagingServices/${topic1.service.name}/topics`
|
||||
);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Drives Service Files Table', () => {
|
||||
test('Drives Service Files Table should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const file1 = EntityDataClass.file1.get();
|
||||
const file2 = new FileClass();
|
||||
|
||||
file2.service.name = file1.service.name;
|
||||
file2.entity.service = file1.service.fullyQualifiedName;
|
||||
|
||||
const file2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.File}`,
|
||||
{
|
||||
data: {
|
||||
name: file2.entity.name,
|
||||
description: file2.entity.description,
|
||||
service: file2.entity.service,
|
||||
},
|
||||
}
|
||||
);
|
||||
file2.entityResponseData = await file2Response.json();
|
||||
|
||||
await page.goto(`/service/driveServices/${file1.service.name}/files`);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Drives Service Spreadsheets Table', () => {
|
||||
test('Drives Service Spreadsheets Table should have sorting on name column', async ({
|
||||
page,
|
||||
}) => {
|
||||
const { afterAction, apiContext } = await getApiContext(page);
|
||||
const spreadsheet1 = EntityDataClass.spreadsheet1.get();
|
||||
const spreadsheet2 = new SpreadsheetClass();
|
||||
|
||||
spreadsheet2.service.name = spreadsheet1.service.name;
|
||||
spreadsheet2.entity.service = spreadsheet1.service.fullyQualifiedName;
|
||||
|
||||
const spreadsheet2Response = await apiContext.post(
|
||||
`/api/v1/${EntityTypeEndpoint.Spreadsheet}`,
|
||||
{
|
||||
data: {
|
||||
name: spreadsheet2.entity.name,
|
||||
description: spreadsheet2.entity.description,
|
||||
service: spreadsheet2.entity.service,
|
||||
},
|
||||
}
|
||||
);
|
||||
spreadsheet2.entityResponseData = await spreadsheet2Response.json();
|
||||
|
||||
await page.goto(
|
||||
`/service/driveServices/${spreadsheet1.service.name}/spreadsheets`
|
||||
);
|
||||
await testTableSorting(page, 'Name');
|
||||
|
||||
await afterAction();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -116,7 +116,7 @@ export class ApiEndpointClass extends EntityClass {
|
||||
};
|
||||
|
||||
this.apiEndpointName = `pw-api-endpoint-${uuid()}`;
|
||||
this.fqn = `${this.service.name}.${this.apiCollection.name}.${this.apiEndpointName}`;
|
||||
this.fqn = `${this.service.name}.${this.apiCollection.name}.${this.apiEndpointName}.requestSchema`;
|
||||
|
||||
this.children = [
|
||||
{
|
||||
@ -223,7 +223,7 @@ export class ApiEndpointClass extends EntityClass {
|
||||
this.serviceType = ServiceTypes.API_SERVICES;
|
||||
this.type = 'ApiEndpoint';
|
||||
this.childrenTabId = 'schema';
|
||||
this.childrenSelectorId = this.children[0].name;
|
||||
this.childrenSelectorId = this.children[0].fullyQualifiedName;
|
||||
}
|
||||
|
||||
async create(apiContext: APIRequestContext) {
|
||||
|
||||
@ -186,9 +186,13 @@ export class StoredProcedureClass extends EntityClass {
|
||||
public set(data: {
|
||||
entity: ResponseDataWithServiceType;
|
||||
service: ResponseDataType;
|
||||
database: ResponseDataWithServiceType;
|
||||
schema: ResponseDataWithServiceType;
|
||||
}): void {
|
||||
this.entityResponseData = data.entity;
|
||||
this.serviceResponseData = data.service;
|
||||
this.databaseResponseData = data.database;
|
||||
this.schemaResponseData = data.schema;
|
||||
}
|
||||
|
||||
async visitEntityPage(page: Page) {
|
||||
|
||||
@ -74,6 +74,10 @@ export class ApiServiceClass extends EntityClass {
|
||||
return this.entityResponseData;
|
||||
}
|
||||
|
||||
set(data: ResponseDataType) {
|
||||
this.entityResponseData = data;
|
||||
}
|
||||
|
||||
async visitEntityPage(page: Page) {
|
||||
await visitServiceDetailsPage(
|
||||
page,
|
||||
|
||||
@ -133,6 +133,10 @@ export class DashboardServiceClass extends EntityClass {
|
||||
return this.entityResponseData;
|
||||
}
|
||||
|
||||
set(data: ResponseDataType) {
|
||||
this.entityResponseData = data;
|
||||
}
|
||||
|
||||
async visitEntityPage(page: Page) {
|
||||
await visitServiceDetailsPage(
|
||||
page,
|
||||
|
||||
@ -89,6 +89,10 @@ export class DatabaseServiceClass extends EntityClass {
|
||||
return this.entityResponseData;
|
||||
}
|
||||
|
||||
set(data: ResponseDataType) {
|
||||
this.entityResponseData = data;
|
||||
}
|
||||
|
||||
async visitEntityPage(page: Page) {
|
||||
await visitServiceDetailsPage(
|
||||
page,
|
||||
|
||||
@ -92,6 +92,10 @@ export class DriveServiceClass extends EntityClass {
|
||||
return this.entityResponseData;
|
||||
}
|
||||
|
||||
set(data: ResponseDataType) {
|
||||
this.entityResponseData = data;
|
||||
}
|
||||
|
||||
async visitEntityPage(page: Page) {
|
||||
await visitServiceDetailsPage(
|
||||
page,
|
||||
|
||||
@ -79,6 +79,10 @@ export class MessagingServiceClass extends EntityClass {
|
||||
return this.entityResponseData;
|
||||
}
|
||||
|
||||
set(data: ResponseDataType) {
|
||||
this.entityResponseData = data;
|
||||
}
|
||||
|
||||
async visitEntityPage(page: Page) {
|
||||
await visitServiceDetailsPage(
|
||||
page,
|
||||
|
||||
@ -708,3 +708,64 @@ export const testPaginationNavigation = async (
|
||||
|
||||
expect(paginationTextContent).toMatch(/2\s*of\s*\d+/);
|
||||
};
|
||||
|
||||
export const testTableSorting = async (page: Page, columnHeader: string) => {
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
const header = page.locator(`th:has-text("${columnHeader}")`).first();
|
||||
const visibleRowSelector = `tbody tr:not([aria-hidden="true"])`;
|
||||
|
||||
const getFirstCellValue = async () => {
|
||||
const firstCell = page.locator(`${visibleRowSelector} td`).first();
|
||||
await firstCell.waitFor({ state: 'visible' });
|
||||
|
||||
return (await firstCell.textContent())?.trim();
|
||||
};
|
||||
|
||||
const rowCount = await page.locator(visibleRowSelector).count();
|
||||
if (rowCount <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const initialValue = await getFirstCellValue();
|
||||
|
||||
await header.click();
|
||||
await header.click();
|
||||
|
||||
const afterFirstClickValue = await getFirstCellValue();
|
||||
|
||||
expect(afterFirstClickValue).not.toBe(initialValue);
|
||||
|
||||
await header.click();
|
||||
|
||||
const afterSecondClickValue = await getFirstCellValue();
|
||||
|
||||
expect(afterSecondClickValue).not.toBe(afterFirstClickValue);
|
||||
};
|
||||
|
||||
export const testTableSearch = async (
|
||||
page: Page,
|
||||
searchIndex: string,
|
||||
searchTerm: string,
|
||||
notVisibleText: string
|
||||
) => {
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await expect(page.getByText(searchTerm).first()).toBeVisible();
|
||||
await expect(page.getByText(notVisibleText).first()).toBeVisible();
|
||||
|
||||
const waitForSearchResponse = page.waitForResponse(
|
||||
`/api/v1/search/query?q=*index=${searchIndex}*`
|
||||
);
|
||||
|
||||
await page.getByTestId('searchbar').fill(searchTerm);
|
||||
await waitForSearchResponse;
|
||||
await waitForAllLoadersToDisappear(page);
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
await expect(page.getByText(searchTerm).first()).toBeVisible();
|
||||
|
||||
await expect(page.getByText(notVisibleText).first()).not.toBeVisible();
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ import {
|
||||
import { APISchema } from '../../../generated/type/apiSchema';
|
||||
import { TagLabel } from '../../../generated/type/tagLabel';
|
||||
import { useApplicationStore } from '../../../hooks/useApplicationStore';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getColumnSorter, getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getVersionedSchema } from '../../../utils/SchemaVersionUtils';
|
||||
import { columnFilterIcon } from '../../../utils/TableColumn.util';
|
||||
import {
|
||||
@ -285,6 +285,7 @@ const APIEndpointSchema: FC<APIEndpointSchemaProps> = ({
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
fixed: 'left',
|
||||
width: 220,
|
||||
sorter: getColumnSorter<Field, 'name'>('name'),
|
||||
render: renderSchemaName,
|
||||
},
|
||||
{
|
||||
@ -417,7 +418,7 @@ const APIEndpointSchema: FC<APIEndpointSchemaProps> = ({
|
||||
}
|
||||
key={viewType}
|
||||
pagination={false}
|
||||
rowKey="name"
|
||||
rowKey="fullyQualifiedName"
|
||||
scroll={TABLE_SCROLL_VALUE}
|
||||
size="small"
|
||||
staticVisibleColumns={COMMON_STATIC_TABLE_VISIBLE_COLUMNS}
|
||||
|
||||
@ -14,12 +14,14 @@
|
||||
import { Switch, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import QueryString from 'qs';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
INITIAL_PAGING_VALUE,
|
||||
PAGE_SIZE,
|
||||
PAGE_SIZE_BASE,
|
||||
pagingObject,
|
||||
} from '../../../../constants/constants';
|
||||
@ -30,15 +32,25 @@ import {
|
||||
TABLE_COLUMNS_KEYS,
|
||||
} from '../../../../constants/TableKeys.constants';
|
||||
import { EntityType } from '../../../../enums/entity.enum';
|
||||
import { SearchIndex } from '../../../../enums/search.enum';
|
||||
import { Include } from '../../../../generated/type/include';
|
||||
import { Paging } from '../../../../generated/type/paging';
|
||||
import { usePaging } from '../../../../hooks/paging/usePaging';
|
||||
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
|
||||
import { useFqn } from '../../../../hooks/useFqn';
|
||||
import { useTableFilters } from '../../../../hooks/useTableFilters';
|
||||
import { ServicePageData } from '../../../../pages/ServiceDetailsPage/ServiceDetailsPage.interface';
|
||||
import { getDataModels } from '../../../../rest/dashboardAPI';
|
||||
import { searchQuery } from '../../../../rest/searchAPI';
|
||||
import { buildSchemaQueryFilter } from '../../../../utils/DatabaseSchemaDetailsUtils';
|
||||
import { commonTableFields } from '../../../../utils/DatasetDetailsUtils';
|
||||
import { getEntityName } from '../../../../utils/EntityUtils';
|
||||
import {
|
||||
getColumnSorter,
|
||||
getEntityName,
|
||||
highlightSearchText,
|
||||
} from '../../../../utils/EntityUtils';
|
||||
import { getEntityDetailsPath } from '../../../../utils/RouterUtils';
|
||||
import { stringToHTML } from '../../../../utils/StringsUtils';
|
||||
import {
|
||||
dataProductTableObject,
|
||||
domainTableObject,
|
||||
@ -57,6 +69,7 @@ const DataModelTable = ({
|
||||
handleShowDeleted,
|
||||
}: DataModelTableProps) => {
|
||||
const { t } = useTranslation();
|
||||
const location = useCustomLocation();
|
||||
const { fqn } = useFqn();
|
||||
const [dataModels, setDataModels] = useState<Array<ServicePageData>>();
|
||||
const {
|
||||
@ -70,6 +83,50 @@ const DataModelTable = ({
|
||||
showPagination,
|
||||
} = usePaging();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const { setFilters } = useTableFilters({});
|
||||
|
||||
const searchValue = useMemo(() => {
|
||||
const param = location.search;
|
||||
const searchData = QueryString.parse(
|
||||
param.startsWith('?') ? param.substring(1) : param
|
||||
);
|
||||
|
||||
return searchData.dataModel as string | undefined;
|
||||
}, [location.search]);
|
||||
|
||||
const searchDataModels = useCallback(
|
||||
async (searchValue: string, pageNumber = INITIAL_PAGING_VALUE) => {
|
||||
setIsLoading(true);
|
||||
handlePageChange(pageNumber, {
|
||||
cursorType: null,
|
||||
cursorValue: undefined,
|
||||
});
|
||||
try {
|
||||
const response = await searchQuery({
|
||||
query: '',
|
||||
pageNumber,
|
||||
pageSize: PAGE_SIZE,
|
||||
queryFilter: buildSchemaQueryFilter(
|
||||
'service.fullyQualifiedName.keyword',
|
||||
fqn,
|
||||
searchValue
|
||||
),
|
||||
searchIndex: SearchIndex.DASHBOARD_DATA_MODEL,
|
||||
includeDeleted: showDeleted,
|
||||
trackTotalHits: true,
|
||||
});
|
||||
const data = response.hits.hits.map((model) => model._source);
|
||||
const total = response.hits.total.value;
|
||||
setDataModels(data);
|
||||
handlePagingChange({ total });
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[fqn, showDeleted, handlePagingChange]
|
||||
);
|
||||
|
||||
const tableColumn: ColumnsType<ServicePageData> = useMemo(
|
||||
() => [
|
||||
@ -78,6 +135,7 @@ const DataModelTable = ({
|
||||
dataIndex: TABLE_COLUMNS_KEYS.NAME,
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
width: 300,
|
||||
sorter: getColumnSorter<ServicePageData, 'name'>('name'),
|
||||
render: (_, record: ServicePageData) => {
|
||||
const dataModelDisplayName = getEntityName(record);
|
||||
|
||||
@ -90,7 +148,9 @@ const DataModelTable = ({
|
||||
EntityType.DASHBOARD_DATA_MODEL,
|
||||
record.fullyQualifiedName || ''
|
||||
)}>
|
||||
{dataModelDisplayName}
|
||||
{stringToHTML(
|
||||
highlightSearchText(dataModelDisplayName, searchValue)
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
@ -123,7 +183,7 @@ const DataModelTable = ({
|
||||
...dataProductTableObject<ServicePageData>(),
|
||||
...tagTableObject<ServicePageData>(),
|
||||
],
|
||||
[]
|
||||
[searchValue, t]
|
||||
);
|
||||
|
||||
const fetchDashboardsDataModel = useCallback(
|
||||
@ -154,7 +214,10 @@ const DataModelTable = ({
|
||||
cursorType,
|
||||
currentPage,
|
||||
}) => {
|
||||
if (cursorType) {
|
||||
if (searchValue) {
|
||||
searchDataModels(searchValue, currentPage);
|
||||
handlePageChange(currentPage);
|
||||
} else if (cursorType) {
|
||||
fetchDashboardsDataModel({ [cursorType]: paging[cursorType] });
|
||||
handlePageChange(
|
||||
currentPage,
|
||||
@ -164,6 +227,19 @@ const DataModelTable = ({
|
||||
}
|
||||
};
|
||||
|
||||
const onDataModelSearch = useCallback(
|
||||
(value: string) => {
|
||||
setFilters({ dataModel: isEmpty(value) ? undefined : value });
|
||||
if (value) {
|
||||
searchDataModels(value);
|
||||
} else {
|
||||
fetchDashboardsDataModel();
|
||||
handlePageChange(INITIAL_PAGING_VALUE);
|
||||
}
|
||||
},
|
||||
[searchDataModels, fetchDashboardsDataModel]
|
||||
);
|
||||
|
||||
const handleShowDeletedChange = (checked: boolean) => {
|
||||
handleShowDeleted(checked);
|
||||
handlePageChange(
|
||||
@ -183,12 +259,25 @@ const DataModelTable = ({
|
||||
}
|
||||
}, [pageSize, showDeleted, pagingCursor]);
|
||||
|
||||
const searchProps = useMemo(
|
||||
() => ({
|
||||
placeholder: t('label.search-for-type', {
|
||||
type: t('label.data-model'),
|
||||
}),
|
||||
typingInterval: 500,
|
||||
searchValue: searchValue,
|
||||
onSearch: onDataModelSearch,
|
||||
}),
|
||||
[onDataModelSearch, searchValue, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={tableColumn}
|
||||
customPaginationProps={{
|
||||
currentPage,
|
||||
isLoading,
|
||||
isNumberBased: Boolean(searchValue),
|
||||
pageSize,
|
||||
paging,
|
||||
pagingHandler: handleDataModelPageChange,
|
||||
@ -218,6 +307,7 @@ const DataModelTable = ({
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
scroll={TABLE_SCROLL_VALUE}
|
||||
searchProps={searchProps}
|
||||
size="small"
|
||||
staticVisibleColumns={COMMON_STATIC_TABLE_VISIBLE_COLUMNS}
|
||||
/>
|
||||
|
||||
@ -21,6 +21,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import {
|
||||
INITIAL_PAGING_VALUE,
|
||||
INITIAL_TABLE_FILTERS,
|
||||
PAGE_SIZE,
|
||||
} from '../../../../constants/constants';
|
||||
import { DATABASE_SCHEMAS_DUMMY_DATA } from '../../../../constants/Database.constants';
|
||||
@ -41,20 +42,22 @@ import { Paging } from '../../../../generated/type/paging';
|
||||
import { usePaging } from '../../../../hooks/paging/usePaging';
|
||||
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
|
||||
import { useFqn } from '../../../../hooks/useFqn';
|
||||
import { useTableFilters } from '../../../../hooks/useTableFilters';
|
||||
import {
|
||||
getDatabaseSchemas,
|
||||
patchDatabaseSchemaDetails,
|
||||
} from '../../../../rest/databaseAPI';
|
||||
import { searchQuery } from '../../../../rest/searchAPI';
|
||||
import { buildSchemaQueryFilter } from '../../../../utils/DatabaseSchemaDetailsUtils';
|
||||
import { commonTableFields } from '../../../../utils/DatasetDetailsUtils';
|
||||
import { getBulkEditButton } from '../../../../utils/EntityBulkEdit/EntityBulkEditUtils';
|
||||
import {
|
||||
getColumnSorter,
|
||||
getEntityBulkEditPath,
|
||||
highlightSearchText,
|
||||
} from '../../../../utils/EntityUtils';
|
||||
import { t } from '../../../../utils/i18next/LocalUtil';
|
||||
import { getEntityDetailsPath } from '../../../../utils/RouterUtils';
|
||||
import { getTermQuery } from '../../../../utils/SearchUtils';
|
||||
import { stringToHTML } from '../../../../utils/StringsUtils';
|
||||
import {
|
||||
dataProductTableObject,
|
||||
@ -83,8 +86,12 @@ export const DatabaseSchemaTable = ({
|
||||
const { permissions } = usePermissionProvider();
|
||||
const [schemas, setSchemas] = useState<DatabaseSchema[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [showDeletedSchemas, setShowDeletedSchemas] = useState<boolean>(false);
|
||||
|
||||
const { data } = useGenericContext<Database>();
|
||||
const { filters: tableFilters, setFilters } = useTableFilters(
|
||||
INITIAL_TABLE_FILTERS
|
||||
);
|
||||
const { showDeletedTables: showDeletedSchemas } = tableFilters;
|
||||
|
||||
const { deleted: isDatabaseDeleted } = data ?? {};
|
||||
|
||||
@ -143,50 +150,42 @@ export const DatabaseSchemaTable = ({
|
||||
[pageSize, decodedDatabaseFQN, showDeletedSchemas]
|
||||
);
|
||||
|
||||
const searchSchema = async (
|
||||
searchValue: string,
|
||||
pageNumber = INITIAL_PAGING_VALUE
|
||||
) => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
handlePageChange(INITIAL_PAGING_VALUE, {
|
||||
const searchSchema = useCallback(
|
||||
async (searchValue: string, pageNumber = INITIAL_PAGING_VALUE) => {
|
||||
setIsLoading(true);
|
||||
handlePageChange(pageNumber, {
|
||||
cursorType: null,
|
||||
cursorValue: undefined,
|
||||
});
|
||||
const response = await searchQuery({
|
||||
query: '',
|
||||
pageNumber,
|
||||
pageSize: PAGE_SIZE,
|
||||
queryFilter: getTermQuery(
|
||||
{ 'database.fullyQualifiedName': decodedDatabaseFQN },
|
||||
'must',
|
||||
undefined,
|
||||
searchValue
|
||||
? {
|
||||
wildcardShouldQueries: {
|
||||
'name.keyword': `*${searchValue}*`,
|
||||
'description.keyword': `*${searchValue}*`,
|
||||
},
|
||||
}
|
||||
: undefined
|
||||
),
|
||||
searchIndex: SearchIndex.DATABASE_SCHEMA,
|
||||
includeDeleted: showDeletedSchemas,
|
||||
trackTotalHits: true,
|
||||
});
|
||||
const data = response.hits.hits.map((schema) => schema._source);
|
||||
const total = response.hits.total.value;
|
||||
setSchemas(data);
|
||||
handlePagingChange({ total });
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
try {
|
||||
const response = await searchQuery({
|
||||
query: '',
|
||||
pageNumber,
|
||||
pageSize: PAGE_SIZE,
|
||||
queryFilter: buildSchemaQueryFilter(
|
||||
'database.fullyQualifiedName',
|
||||
decodedDatabaseFQN,
|
||||
searchValue
|
||||
),
|
||||
searchIndex: SearchIndex.DATABASE_SCHEMA,
|
||||
includeDeleted: showDeletedSchemas,
|
||||
trackTotalHits: true,
|
||||
});
|
||||
const data = response.hits.hits.map((schema) => schema._source);
|
||||
const total = response.hits.total.value;
|
||||
setSchemas(data);
|
||||
handlePagingChange({ total });
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[decodedDatabaseFQN, showDeletedSchemas, handlePagingChange]
|
||||
);
|
||||
|
||||
const handleShowDeletedSchemas = useCallback((value: boolean) => {
|
||||
setShowDeletedSchemas(value);
|
||||
setFilters({ showDeletedTables: value });
|
||||
handlePageChange(INITIAL_PAGING_VALUE, {
|
||||
cursorType: null,
|
||||
cursorValue: undefined,
|
||||
@ -210,18 +209,18 @@ export const DatabaseSchemaTable = ({
|
||||
[paging, fetchDatabaseSchema, searchSchema, searchValue]
|
||||
);
|
||||
|
||||
const onSchemaSearch = (value: string) => {
|
||||
navigate({
|
||||
search: QueryString.stringify({
|
||||
schema: isEmpty(value) ? undefined : value,
|
||||
}),
|
||||
});
|
||||
if (value) {
|
||||
searchSchema(value);
|
||||
} else {
|
||||
fetchDatabaseSchema();
|
||||
}
|
||||
};
|
||||
const onSchemaSearch = useCallback(
|
||||
(value: string) => {
|
||||
setFilters({ schema: isEmpty(value) ? undefined : value });
|
||||
if (value) {
|
||||
searchSchema(value);
|
||||
} else {
|
||||
fetchDatabaseSchema();
|
||||
handlePageChange(INITIAL_PAGING_VALUE);
|
||||
}
|
||||
},
|
||||
[setFilters, searchSchema, fetchDatabaseSchema]
|
||||
);
|
||||
|
||||
const handleDisplayNameUpdate = useCallback(
|
||||
async (data: EntityName, id?: string) => {
|
||||
@ -256,6 +255,7 @@ export const DatabaseSchemaTable = ({
|
||||
dataIndex: TABLE_COLUMNS_KEYS.NAME,
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
width: 250,
|
||||
sorter: getColumnSorter<DatabaseSchema, 'name'>('name'),
|
||||
render: (_, record: DatabaseSchema) => (
|
||||
<DisplayName
|
||||
displayName={stringToHTML(
|
||||
@ -336,6 +336,18 @@ export const DatabaseSchemaTable = ({
|
||||
pagingCursor,
|
||||
]);
|
||||
|
||||
const searchProps = useMemo(
|
||||
() => ({
|
||||
placeholder: t('label.search-for-type', {
|
||||
type: t('label.schema'),
|
||||
}),
|
||||
typingInterval: 500,
|
||||
searchValue: searchValue,
|
||||
onSearch: onSchemaSearch,
|
||||
}),
|
||||
[onSchemaSearch, searchValue]
|
||||
);
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={schemaTableColumns}
|
||||
@ -377,14 +389,7 @@ export const DatabaseSchemaTable = ({
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
scroll={TABLE_SCROLL_VALUE}
|
||||
searchProps={{
|
||||
placeholder: t('label.search-for-type', {
|
||||
type: t('label.schema'),
|
||||
}),
|
||||
searchValue: searchValue,
|
||||
typingInterval: 500,
|
||||
onSearch: onSchemaSearch,
|
||||
}}
|
||||
searchProps={searchProps}
|
||||
size="small"
|
||||
staticVisibleColumns={COMMON_STATIC_TABLE_VISIBLE_COLUMNS}
|
||||
/>
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { PagingWithoutTotal } from 'Models';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { File } from '../../../../generated/entity/data/file';
|
||||
import { UsePagingInterface } from '../../../../hooks/paging/usePaging';
|
||||
import { PagingHandlerParams } from '../../../common/NextPrevious/NextPrevious.interface';
|
||||
@ -21,4 +23,8 @@ export interface FilesTableProps {
|
||||
handlePageChange: (data: PagingHandlerParams) => void;
|
||||
files: File[];
|
||||
isLoading: boolean;
|
||||
fetchFiles: (paging?: PagingWithoutTotal) => void;
|
||||
setFiles: Dispatch<SetStateAction<File[]>>;
|
||||
setIsLoading: Dispatch<SetStateAction<boolean>>;
|
||||
serviceFqn: string;
|
||||
}
|
||||
|
||||
@ -12,12 +12,15 @@
|
||||
*/
|
||||
import { Switch, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import QueryString from 'qs';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
INITIAL_PAGING_VALUE,
|
||||
PAGE_SIZE,
|
||||
PAGE_SIZE_BASE,
|
||||
} from '../../../../constants/constants';
|
||||
import { TABLE_SCROLL_VALUE } from '../../../../constants/Table.constants';
|
||||
@ -27,10 +30,21 @@ import {
|
||||
TABLE_COLUMNS_KEYS,
|
||||
} from '../../../../constants/TableKeys.constants';
|
||||
import { EntityType } from '../../../../enums/entity.enum';
|
||||
import { SearchIndex } from '../../../../enums/search.enum';
|
||||
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
|
||||
import { useTableFilters } from '../../../../hooks/useTableFilters';
|
||||
import { ServicePageData } from '../../../../pages/ServiceDetailsPage/ServiceDetailsPage.interface';
|
||||
import { getEntityName } from '../../../../utils/EntityUtils';
|
||||
import { searchQuery } from '../../../../rest/searchAPI';
|
||||
import { buildSchemaQueryFilter } from '../../../../utils/DatabaseSchemaDetailsUtils';
|
||||
import {
|
||||
getColumnSorter,
|
||||
getEntityName,
|
||||
highlightSearchText,
|
||||
} from '../../../../utils/EntityUtils';
|
||||
import { getEntityDetailsPath } from '../../../../utils/RouterUtils';
|
||||
import { stringToHTML } from '../../../../utils/StringsUtils';
|
||||
import { tagTableObject } from '../../../../utils/TableColumn.util';
|
||||
import { showErrorToast } from '../../../../utils/ToastUtils';
|
||||
import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import RichTextEditorPreviewerNew from '../../../common/RichTextEditor/RichTextEditorPreviewNew';
|
||||
import Table from '../../../common/Table/Table';
|
||||
@ -43,8 +57,70 @@ function FilesTable({
|
||||
handlePageChange,
|
||||
files,
|
||||
isLoading,
|
||||
setFiles,
|
||||
setIsLoading,
|
||||
serviceFqn,
|
||||
fetchFiles,
|
||||
}: Readonly<FilesTableProps>) {
|
||||
const { t } = useTranslation();
|
||||
const location = useCustomLocation();
|
||||
const { setFilters } = useTableFilters({});
|
||||
|
||||
const searchValue = useMemo(() => {
|
||||
const param = location.search;
|
||||
const searchData = QueryString.parse(
|
||||
param.startsWith('?') ? param.substring(1) : param
|
||||
);
|
||||
|
||||
return searchData.file as string | undefined;
|
||||
}, [location.search]);
|
||||
|
||||
const searchFiles = useCallback(
|
||||
async (searchValue: string, pageNumber = INITIAL_PAGING_VALUE) => {
|
||||
setIsLoading(true);
|
||||
paging.handlePageChange(pageNumber, {
|
||||
cursorType: null,
|
||||
cursorValue: undefined,
|
||||
});
|
||||
try {
|
||||
const response = await searchQuery({
|
||||
query: '',
|
||||
pageNumber,
|
||||
pageSize: PAGE_SIZE,
|
||||
queryFilter: buildSchemaQueryFilter(
|
||||
'service.fullyQualifiedName.keyword',
|
||||
serviceFqn,
|
||||
searchValue
|
||||
),
|
||||
searchIndex: SearchIndex.FILE_SEARCH_INDEX,
|
||||
includeDeleted: showDeleted,
|
||||
trackTotalHits: true,
|
||||
});
|
||||
const data = response.hits.hits.map((file) => file._source);
|
||||
const total = response.hits.total.value;
|
||||
setFiles(data);
|
||||
paging.handlePagingChange({ total });
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[serviceFqn, showDeleted, paging, setFiles, setIsLoading]
|
||||
);
|
||||
|
||||
const onFileSearch = useCallback(
|
||||
(value: string) => {
|
||||
setFilters({ file: isEmpty(value) ? undefined : value });
|
||||
if (value) {
|
||||
searchFiles(value);
|
||||
} else {
|
||||
fetchFiles();
|
||||
paging.handlePageChange(INITIAL_PAGING_VALUE);
|
||||
}
|
||||
},
|
||||
[searchFiles, paging]
|
||||
);
|
||||
|
||||
const tableColumn: ColumnsType<ServicePageData> = useMemo(
|
||||
() => [
|
||||
@ -53,6 +129,7 @@ function FilesTable({
|
||||
dataIndex: TABLE_COLUMNS_KEYS.NAME,
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
width: 300,
|
||||
sorter: getColumnSorter<ServicePageData, 'name'>('name'),
|
||||
render: (_, record: ServicePageData) => {
|
||||
const fileDisplayName = getEntityName(record);
|
||||
|
||||
@ -65,7 +142,9 @@ function FilesTable({
|
||||
EntityType.FILE,
|
||||
record.fullyQualifiedName || ''
|
||||
)}>
|
||||
{fileDisplayName}
|
||||
{stringToHTML(
|
||||
highlightSearchText(fileDisplayName, searchValue)
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
@ -89,7 +168,7 @@ function FilesTable({
|
||||
},
|
||||
...tagTableObject<ServicePageData>(),
|
||||
],
|
||||
[]
|
||||
[searchValue, t]
|
||||
);
|
||||
|
||||
const handleShowDeletedChange = (checked: boolean) => {
|
||||
@ -98,12 +177,25 @@ function FilesTable({
|
||||
paging.handlePageSizeChange(PAGE_SIZE_BASE);
|
||||
};
|
||||
|
||||
const searchProps = useMemo(
|
||||
() => ({
|
||||
placeholder: t('label.search-for-type', {
|
||||
type: t('label.file'),
|
||||
}),
|
||||
typingInterval: 500,
|
||||
searchValue: searchValue,
|
||||
onSearch: onFileSearch,
|
||||
}),
|
||||
[onFileSearch, searchValue, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={tableColumn}
|
||||
customPaginationProps={{
|
||||
currentPage: paging.currentPage,
|
||||
isLoading,
|
||||
isNumberBased: Boolean(searchValue),
|
||||
pageSize: paging.pageSize,
|
||||
paging: paging.paging,
|
||||
pagingHandler: handlePageChange,
|
||||
@ -133,6 +225,7 @@ function FilesTable({
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
scroll={TABLE_SCROLL_VALUE}
|
||||
searchProps={searchProps}
|
||||
size="small"
|
||||
staticVisibleColumns={COMMON_STATIC_TABLE_VISIBLE_COLUMNS}
|
||||
/>
|
||||
|
||||
@ -10,6 +10,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { PagingWithoutTotal } from 'Models';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Spreadsheet } from '../../../../generated/entity/data/spreadsheet';
|
||||
import { UsePagingInterface } from '../../../../hooks/paging/usePaging';
|
||||
import { PagingHandlerParams } from '../../../common/NextPrevious/NextPrevious.interface';
|
||||
@ -21,4 +23,8 @@ export interface SpreadsheetsTableProps {
|
||||
handlePageChange: (data: PagingHandlerParams) => void;
|
||||
spreadsheets: Spreadsheet[];
|
||||
isLoading: boolean;
|
||||
setSpreadsheets: Dispatch<SetStateAction<Spreadsheet[]>>;
|
||||
setIsLoading: Dispatch<SetStateAction<boolean>>;
|
||||
serviceFqn: string;
|
||||
fetchSpreadsheets: (paging?: PagingWithoutTotal) => void;
|
||||
}
|
||||
|
||||
@ -12,12 +12,15 @@
|
||||
*/
|
||||
import { Switch, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isEmpty, isUndefined } from 'lodash';
|
||||
import QueryString from 'qs';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
INITIAL_PAGING_VALUE,
|
||||
PAGE_SIZE,
|
||||
PAGE_SIZE_BASE,
|
||||
} from '../../../../constants/constants';
|
||||
import { TABLE_SCROLL_VALUE } from '../../../../constants/Table.constants';
|
||||
@ -27,10 +30,21 @@ import {
|
||||
TABLE_COLUMNS_KEYS,
|
||||
} from '../../../../constants/TableKeys.constants';
|
||||
import { EntityType } from '../../../../enums/entity.enum';
|
||||
import { SearchIndex } from '../../../../enums/search.enum';
|
||||
import useCustomLocation from '../../../../hooks/useCustomLocation/useCustomLocation';
|
||||
import { useTableFilters } from '../../../../hooks/useTableFilters';
|
||||
import { ServicePageData } from '../../../../pages/ServiceDetailsPage/ServiceDetailsPage.interface';
|
||||
import { getEntityName } from '../../../../utils/EntityUtils';
|
||||
import { searchQuery } from '../../../../rest/searchAPI';
|
||||
import { buildSchemaQueryFilter } from '../../../../utils/DatabaseSchemaDetailsUtils';
|
||||
import {
|
||||
getColumnSorter,
|
||||
getEntityName,
|
||||
highlightSearchText,
|
||||
} from '../../../../utils/EntityUtils';
|
||||
import { getEntityDetailsPath } from '../../../../utils/RouterUtils';
|
||||
import { stringToHTML } from '../../../../utils/StringsUtils';
|
||||
import { tagTableObject } from '../../../../utils/TableColumn.util';
|
||||
import { showErrorToast } from '../../../../utils/ToastUtils';
|
||||
import ErrorPlaceHolder from '../../../common/ErrorWithPlaceholder/ErrorPlaceHolder';
|
||||
import RichTextEditorPreviewerNew from '../../../common/RichTextEditor/RichTextEditorPreviewNew';
|
||||
import Table from '../../../common/Table/Table';
|
||||
@ -43,8 +57,72 @@ function SpreadsheetsTable({
|
||||
handlePageChange,
|
||||
spreadsheets,
|
||||
isLoading,
|
||||
setSpreadsheets,
|
||||
setIsLoading,
|
||||
serviceFqn,
|
||||
fetchSpreadsheets,
|
||||
}: Readonly<SpreadsheetsTableProps>) {
|
||||
const { t } = useTranslation();
|
||||
const location = useCustomLocation();
|
||||
const { setFilters } = useTableFilters({});
|
||||
|
||||
const searchValue = useMemo(() => {
|
||||
const param = location.search;
|
||||
const searchData = QueryString.parse(
|
||||
param.startsWith('?') ? param.substring(1) : param
|
||||
);
|
||||
|
||||
return searchData.spreadsheet as string | undefined;
|
||||
}, [location.search]);
|
||||
|
||||
const searchSpreadsheets = useCallback(
|
||||
async (searchValue: string, pageNumber = INITIAL_PAGING_VALUE) => {
|
||||
setIsLoading(true);
|
||||
paging.handlePageChange(pageNumber, {
|
||||
cursorType: null,
|
||||
cursorValue: undefined,
|
||||
});
|
||||
try {
|
||||
const response = await searchQuery({
|
||||
query: '',
|
||||
pageNumber,
|
||||
pageSize: PAGE_SIZE,
|
||||
queryFilter: buildSchemaQueryFilter(
|
||||
'service.fullyQualifiedName.keyword',
|
||||
serviceFqn,
|
||||
searchValue
|
||||
),
|
||||
searchIndex: SearchIndex.SPREADSHEET_SEARCH_INDEX,
|
||||
includeDeleted: showDeleted,
|
||||
trackTotalHits: true,
|
||||
});
|
||||
const data = response.hits.hits.map(
|
||||
(spreadsheet) => spreadsheet._source
|
||||
);
|
||||
const total = response.hits.total.value;
|
||||
setSpreadsheets(data);
|
||||
paging.handlePagingChange({ total });
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[serviceFqn, showDeleted, paging, setSpreadsheets, setIsLoading]
|
||||
);
|
||||
|
||||
const onSpreadsheetSearch = useCallback(
|
||||
(value: string) => {
|
||||
setFilters({ spreadsheet: isEmpty(value) ? undefined : value });
|
||||
if (value) {
|
||||
searchSpreadsheets(value);
|
||||
} else {
|
||||
fetchSpreadsheets();
|
||||
paging.handlePageChange(INITIAL_PAGING_VALUE);
|
||||
}
|
||||
},
|
||||
[searchSpreadsheets, paging]
|
||||
);
|
||||
|
||||
const tableColumn: ColumnsType<ServicePageData> = useMemo(
|
||||
() => [
|
||||
@ -53,6 +131,7 @@ function SpreadsheetsTable({
|
||||
dataIndex: TABLE_COLUMNS_KEYS.NAME,
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
width: 300,
|
||||
sorter: getColumnSorter<ServicePageData, 'name'>('name'),
|
||||
render: (_, record: ServicePageData) => {
|
||||
const spreadsheetDisplayName = getEntityName(record);
|
||||
|
||||
@ -65,7 +144,9 @@ function SpreadsheetsTable({
|
||||
EntityType.SPREADSHEET,
|
||||
record.fullyQualifiedName || ''
|
||||
)}>
|
||||
{spreadsheetDisplayName}
|
||||
{stringToHTML(
|
||||
highlightSearchText(spreadsheetDisplayName, searchValue)
|
||||
)}
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
@ -89,7 +170,7 @@ function SpreadsheetsTable({
|
||||
},
|
||||
...tagTableObject<ServicePageData>(),
|
||||
],
|
||||
[]
|
||||
[searchValue, t]
|
||||
);
|
||||
|
||||
const handleShowDeletedChange = (checked: boolean) => {
|
||||
@ -98,6 +179,18 @@ function SpreadsheetsTable({
|
||||
paging.handlePageSizeChange(PAGE_SIZE_BASE);
|
||||
};
|
||||
|
||||
const searchProps = useMemo(
|
||||
() => ({
|
||||
placeholder: t('label.search-for-type', {
|
||||
type: t('label.spreadsheet'),
|
||||
}),
|
||||
typingInterval: 500,
|
||||
searchValue: searchValue,
|
||||
onSearch: onSpreadsheetSearch,
|
||||
}),
|
||||
[onSpreadsheetSearch, searchValue, t]
|
||||
);
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={tableColumn}
|
||||
@ -106,6 +199,7 @@ function SpreadsheetsTable({
|
||||
isLoading,
|
||||
pageSize: paging.pageSize,
|
||||
paging: paging.paging,
|
||||
isNumberBased: Boolean(searchValue),
|
||||
pagingHandler: handlePageChange,
|
||||
onShowSizeChange: paging.handlePageSizeChange,
|
||||
showPagination: paging.showPagination,
|
||||
@ -133,6 +227,7 @@ function SpreadsheetsTable({
|
||||
pagination={false}
|
||||
rowKey="id"
|
||||
scroll={TABLE_SCROLL_VALUE}
|
||||
searchProps={searchProps}
|
||||
size="small"
|
||||
staticVisibleColumns={COMMON_STATIC_TABLE_VISIBLE_COLUMNS}
|
||||
/>
|
||||
|
||||
@ -46,6 +46,7 @@ import {
|
||||
getEpochMillisForPastDays,
|
||||
} from '../../../../../utils/date-time/DateTimeUtils';
|
||||
import {
|
||||
getColumnSorter,
|
||||
getEntityName,
|
||||
highlightSearchText,
|
||||
} from '../../../../../utils/EntityUtils';
|
||||
@ -325,6 +326,7 @@ function IngestionListTable({
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
fixed: 'left' as FixedType,
|
||||
sorter: getColumnSorter<IngestionPipeline, 'name'>('name'),
|
||||
render: customRenderNameField ?? renderNameField(searchText),
|
||||
},
|
||||
...(showDescriptionCol
|
||||
|
||||
@ -43,7 +43,11 @@ import { DatabaseServiceSearchSource } from '../../../interface/search.interface
|
||||
import { ServicesType } from '../../../interface/service.interface';
|
||||
import { getServices, searchService } from '../../../rest/serviceAPI';
|
||||
import { getServiceLogo } from '../../../utils/CommonUtils';
|
||||
import { getEntityName, highlightSearchText } from '../../../utils/EntityUtils';
|
||||
import {
|
||||
getColumnSorter,
|
||||
getEntityName,
|
||||
highlightSearchText,
|
||||
} from '../../../utils/EntityUtils';
|
||||
import { checkPermission } from '../../../utils/PermissionsUtils';
|
||||
import {
|
||||
getAddServicePath,
|
||||
@ -327,6 +331,7 @@ const Services = ({ serviceName }: ServicesProps) => {
|
||||
dataIndex: TABLE_COLUMNS_KEYS.NAME,
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
width: 200,
|
||||
sorter: getColumnSorter<ServicesType, 'name'>('name'),
|
||||
render: (name, record) => (
|
||||
<div className="d-flex gap-2 items-center">
|
||||
{getServiceLogo(record.serviceType || '', 'w-4')}
|
||||
|
||||
@ -35,7 +35,7 @@ import {
|
||||
} from '../../../generated/entity/data/topic';
|
||||
import { TagLabel, TagSource } from '../../../generated/type/tagLabel';
|
||||
import { useFqn } from '../../../hooks/useFqn';
|
||||
import { getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getColumnSorter, getEntityName } from '../../../utils/EntityUtils';
|
||||
import { getVersionedSchema } from '../../../utils/SchemaVersionUtils';
|
||||
import { columnFilterIcon } from '../../../utils/TableColumn.util';
|
||||
import {
|
||||
@ -294,6 +294,7 @@ const TopicSchemaFields: FC<TopicSchemaFieldsProps> = ({
|
||||
key: TABLE_COLUMNS_KEYS.NAME,
|
||||
fixed: 'left',
|
||||
width: 220,
|
||||
sorter: getColumnSorter<Field, 'name'>('name'),
|
||||
render: renderSchemaName,
|
||||
},
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user