Skip to content

Commit fb91a07

Browse files
authored
implement view column sorting and field based searches (#134)
1 parent 0a9a94d commit fb91a07

File tree

19 files changed

+370
-196
lines changed

19 files changed

+370
-196
lines changed

Makefile

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -327,14 +327,6 @@ run-unit-tests: ## run unit tests
327327
build-integration-tests-docker:
328328
@cd selenium-tests && docker build -t "${IMG_REPO}:test" . && cd ..
329329

330-
.PHONY: run-smoke-tests-docker-only
331-
run-smoke-tests-docker-only: build-integration-tests-docker
332-
@cd selenium-tests && docker run -e URL_BASE=http://selenium-tests-nginx-1 -e CP_URL="http://selenium-tests-nuodb-cp-1:8080" -e MVN_TEST=${MVN_TEST} --net kind -it "${IMG_REPO}:test" && cd ..
333-
334-
.PHONY: run-smoke-tests-docker
335-
run-smoke-tests-docker: setup-integration-tests ## integration tests without setup/teardown (docker version)
336-
@${MAKE} run-smoke-tests-docker-only teardown-integration-tests || (${MAKE} teardown-integration-tests && exit 1)
337-
338330
.PHONY: run-integration-tests
339331
run-integration-tests: build-image setup-integration-tests ## run integration tests (+setup)
340332
${MAKE} run-integration-tests-only teardown-integration-tests || (${MAKE} teardown-integration-tests && exit 1)

README.md

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,23 +46,3 @@ make teardown-integration-tests
4646
The Integration tests are regular JUnit tests going against the Selenium container, which can be run in debug mode in your IDE as well. Location: `selenium-tests/src/test/java/com/nuodb/selenium`. Make sure you run `make setup-integration-tests` beforehand.
4747

4848
To monitor the UI while the tests are running, go to this URL: `http://localhost:7900/?autoconnect=1&resize=scale&password=secret⁠`
49-
50-
# Run embedded Integration Tests in a Selenium Docker container (Production tests)
51-
52-
Run tests like this:
53-
54-
```
55-
MVN_TEST="com/nuodb/selenium/basic/**" make run-smoke-tests-docker
56-
```
57-
58-
Following environment variables can be modifed (showing the default):
59-
60-
```
61-
TEST_ORGANIZATION=integrationtest
62-
TEST_ADMIN_USER=admin
63-
TEST_ADMIN_PASSWORD=passw0rd
64-
65-
Following environment variables are required when running the docker container directly:
66-
CP_URL - URL to the NuoDB DBaaS Control Plane, i.e. http://localhost:8081
67-
URL_Base - URL to the NuoDB WebUI, i.e. http://localhost
68-
```

build_utils.sh

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
# (C) Copyright 2024-2025 Dassault Systemes SE. All Rights Reserved.
2+
# (C) Copyright 2024-2026 Dassault Systemes SE. All Rights Reserved.
33
REPOSITORY="nuodbaas-webui"
44
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
55
CHART_FILE="charts/${REPOSITORY}/Chart.yaml"
@@ -8,10 +8,8 @@ APP_VERSION="$(sed -n -E 's/^appVersion: *"?([^ "]*)"?.*/\1/p' "$CHART_FILE")"
88
VERSION="$(sed -n -E 's/^version: *"?([^ "]*)"?.*/\1/p' "$CHART_FILE")"
99
GIT_HASH="$(git rev-parse --short HEAD)"
1010
GIT_DOCKER_IMAGE_RELEASE="ghcr.io/nuodb/${REPOSITORY}:${VERSION}"
11-
GIT_DOCKER_IMAGE_TEST="ghcr.io/nuodb/${REPOSITORY}-test:${VERSION}-${GIT_HASH}"
1211
GIT_DOCKER_IMAGE_SHA="${GIT_DOCKER_IMAGE_RELEASE}-${GIT_HASH}"
1312
AWS_DOCKER_IMAGE_RELEASE="${ECR_ACCOUNT_URL}/${REPOSITORY}-docker:${VERSION}"
14-
AWS_DOCKER_IMAGE_TEST="${ECR_ACCOUNT_URL}/${REPOSITORY}-test:${VERSION}-${GIT_HASH}"
1513
AWS_DOCKER_IMAGE_SHA="${AWS_DOCKER_IMAGE_RELEASE}-${GIT_HASH}"
1614

1715
if [[ "${BRANCH}" == rel/* ]] ; then
@@ -135,10 +133,8 @@ if [ "$1" == "deployDockerImages" ] ; then
135133
else
136134
docker tag "${REPOSITORY}:latest" "${AWS_DOCKER_IMAGE_SHA}" && \
137135
docker push "${AWS_DOCKER_IMAGE_SHA}" && \
138-
docker tag "${REPOSITORY}:test" "${AWS_DOCKER_IMAGE_TEST}" && \
139-
docker push "${AWS_DOCKER_IMAGE_TEST}" && \
140-
docker tag "${REPOSITORY}:test" "${GIT_DOCKER_IMAGE_TEST}" && \
141-
docker push "${GIT_DOCKER_IMAGE_TEST}" && \
136+
docker tag "${REPOSITORY}:latest" "${GIT_DOCKER_IMAGE_SHA}" && \
137+
docker push "${GIT_DOCKER_IMAGE_SHA}" && \
142138

143139
# use this last - the github docker image is used to determine a prior
144140
# successful build succeeded (to avoid rebuilding and ensuring an identical
@@ -194,6 +190,10 @@ if [ "$1" == "createRelease" ] && [ "$2" != "" ] ; then
194190
fi
195191
fi
196192

193+
if [ "$1" != "" ] ; then
194+
echo "Invalid first argument: \"$1\""
195+
fi
196+
197197
echo "$0 doesImageExist"
198198
echo "$0 createAndUploadHelmPackage"
199199
echo "$0 deployDockerImages"

charts/nuodbaas-webui/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ maintainers:
1212
email: support@nuodb.com
1313
icon: https://raw.githubusercontent.com/nuodb/nuodb-helm-charts/master/images/nuodb.svg
1414
type: application
15-
version: "1.2.4"
16-
appVersion: "1.2.4"
15+
version: "1.3.0"
16+
appVersion: "1.3.0"

selenium-tests/pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- (C) Copyright 2024 Dassault Systemes SE. All Rights Reserved. -->
1+
<!-- (C) Copyright 2024-2026 Dassault Systemes SE. All Rights Reserved. -->
22

33
<project xmlns="http://maven.apache.org/POM/4.0.0"
44
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -33,17 +33,17 @@
3333
<dependency>
3434
<groupId>org.apache.logging.log4j</groupId>
3535
<artifactId>log4j-api</artifactId>
36-
<version>2.23.1</version>
36+
<version>2.25.3</version>
3737
</dependency>
3838
<dependency>
3939
<groupId>org.apache.logging.log4j</groupId>
4040
<artifactId>log4j-core</artifactId>
41-
<version>2.23.1</version>
41+
<version>2.25.3</version>
4242
</dependency>
4343
<dependency>
4444
<groupId>org.apache.logging.log4j</groupId>
4545
<artifactId>log4j-slf4j-impl</artifactId>
46-
<version>2.23.1</version>
46+
<version>2.25.3</version>
4747
</dependency>
4848
<dependency>
4949
<groupId>org.apache.httpcomponents.client5</groupId>

selenium-tests/src/test/java/com/nuodb/selenium/basic/SearchTest.java

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// (C) Copyright 2024-2025 Dassault Systemes SE. All Rights Reserved.
1+
// (C) Copyright 2024-2026 Dassault Systemes SE. All Rights Reserved.
22

33
package com.nuodb.selenium.basic;
44

@@ -31,9 +31,10 @@ public void testSearch() throws IOException {
3131

3232
// Setup users
3333
String name = shortUnique("u");
34+
String labelName = "l" + name.substring(1);
3435
for(int i=10; i<=99; i++) {
3536
System.out.println("Creating user /" + TEST_ORGANIZATION + "/" + (name + i));
36-
createResourceRest(Resource.users, "/" + TEST_ORGANIZATION + "/" + (name + i), body.replaceAll("%%%NAME%%%", name + i).replaceAll("%%%VALUE2%%%", (name + (i%10))));
37+
createResourceRest(Resource.users, "/" + TEST_ORGANIZATION + "/" + (name + i), body.replaceAll("%%%NAME%%%", name + i).replaceAll("%%%VALUE2%%%", (labelName + (i%10))));
3738
}
3839

3940
// verify we have full page of users
@@ -46,7 +47,7 @@ public void testSearch() throws IOException {
4647
});
4748

4849
// search users starting with "1" index and check that 10 users are returned
49-
replaceInputElementByName("search", name + "1");
50+
replaceInputElementByName("search", name + "1*");
5051
waitInputElementByName("search").sendKeys(Keys.RETURN);
5152
waitRestComplete();
5253
retry(()-> {
@@ -55,7 +56,7 @@ public void testSearch() throws IOException {
5556
});
5657

5758
// search users by label existence
58-
replaceInputElementByName("search", "label=label1");
59+
replaceInputElementByName("search", "labels=label1");
5960
waitInputElementByName("search").sendKeys(Keys.RETURN);
6061
waitRestComplete();
6162
retry(()-> {
@@ -64,7 +65,7 @@ public void testSearch() throws IOException {
6465
});
6566

6667
// search users by label value
67-
replaceInputElementByName("search", "label=label2=" + name + "8");
68+
replaceInputElementByName("search", "labels=label2=" + labelName + "8");
6869
waitInputElementByName("search").sendKeys(Keys.RETURN);
6970
waitRestComplete();
7071
retry(()->{
@@ -73,23 +74,48 @@ public void testSearch() throws IOException {
7374
});
7475

7576
// search users by label value and name
76-
replaceInputElementByName("search", "label=label2=" + name + "8" + " name=" + name + "1");
77+
replaceInputElementByName("search", "labels=label2=" + labelName + "8" + " name=" + name + "1*");
7778
waitInputElementByName("search").sendKeys(Keys.RETURN);
7879
waitRestComplete();
7980
retry(()-> {
8081
var nc = waitTableElements("list_resource__table", "name", null, "name");
8182
assertEquals(1, nc.size());
8283
});
8384

85+
// search all users by name=*
86+
replaceInputElementByName("search", "name=" + name + "*");
87+
waitInputElementByName("search").sendKeys(Keys.RETURN);
88+
waitRestComplete();
89+
retry(()->{
90+
var nc = waitTableElements("list_resource__table", "name", null, "name");
91+
assertEquals(20, nc.size());
92+
});
93+
8494
// search users by partial name
85-
replaceInputElementByName("search", "name=" + name + "1");
95+
replaceInputElementByName("search", "name=" + name + "1*");
8696
waitInputElementByName("search").sendKeys(Keys.RETURN);
8797
waitRestComplete();
8898
retry(()->{
8999
var nc = waitTableElements("list_resource__table", "name", null, "name");
90100
assertEquals(10, nc.size());
91101
});
92102

103+
replaceInputElementByName("search", "name=*" + name.substring(1) + "1*");
104+
waitInputElementByName("search").sendKeys(Keys.RETURN);
105+
waitRestComplete();
106+
retry(()->{
107+
var nc = waitTableElements("list_resource__table", "name", null, "name");
108+
assertEquals(10, nc.size());
109+
});
110+
111+
replaceInputElementByName("search", "name=*" + name.substring(2) + "18");
112+
waitInputElementByName("search").sendKeys(Keys.RETURN);
113+
waitRestComplete();
114+
retry(()->{
115+
var nc = waitTableElements("list_resource__table", "name", null, "name");
116+
assertEquals(1, nc.size());
117+
});
118+
93119
// search users by full name
94120
replaceInputElementByName("search", "name=" + name + "19");
95121
waitInputElementByName("search").sendKeys(Keys.RETURN);

ui/public/theme/base.json

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
{
22
"copyright": "(C) Copyright 2024-2026 Dassault Systemes SE. All Rights Reserved.",
33
"views": {
4-
"/databases?/{organization}?/{project}?/{name}": {
4+
"/databases": {
55
"columns": [
6+
"name",
67
"organization",
78
"project",
8-
"name",
99
"labels",
1010
"tier",
1111
"properties",
12-
"state",
12+
"status.state",
1313
"status"
1414
],
15-
"fields": {
16-
"state": {
17-
"value": "status.state"
18-
}
19-
},
2015
"menu": [
2116
{
2217
"label": "button.db.connection.info",
@@ -79,10 +74,10 @@
7974
}
8075
]
8176
},
82-
"/backuppolicies?/{organization}?/{name}": {
77+
"/backuppolicies": {
8378
"columns": [
84-
"organization",
8579
"name",
80+
"organization",
8681
"labels",
8782
"frequency",
8883
"selector",
@@ -100,7 +95,7 @@
10095
}
10196
]
10297
},
103-
"/projects?/{organization}?/{name}": {
98+
"/projects": {
10499
"menu": [
105100
{
106101
"label": "button.show.databases",
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// (C) Copyright 2026 Dassault Systemes SE. All Rights Reserved.
2+
3+
import { ReactNode } from "react";
4+
5+
export type SortIconProps = {
6+
sort: "none"|"asc"|"desc";
7+
setSort: (sort: "asc"|"desc") => void;
8+
}
9+
10+
export default function SortIcon({sort, setSort}: SortIconProps) : ReactNode {
11+
return (
12+
<div className="NuoRow" style={{alignItems: "center"}} onClick={(event)=>{
13+
if(sort === "none") {
14+
const rect = event.currentTarget.getBoundingClientRect();
15+
const isBottomHalf = (event.clientY - rect.top) > rect.height / 2;
16+
setSort(isBottomHalf ? "desc" : "asc");
17+
}
18+
else {
19+
setSort(sort === "asc" ? "desc" : "asc");
20+
}
21+
}}>
22+
<svg focusable="true" viewBox="0 0 24 24" style={{width: "20px", height: "20px"}}>
23+
<path d="M7.41 10.41 12 5.83l4.59 4.58L18 9l-6-6l-6 6Z" opacity={sort === "asc" ? 1 : 0.3}></path>
24+
<path d="M7.41 13.59 12 18.17l4.59-4.58L18 15l-6 6l-6-6Z" opacity={sort === "desc" ? 1 : 0.3}></path>
25+
</svg>
26+
</div>
27+
)
28+
}

0 commit comments

Comments
 (0)