Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.11.x] closes #1312 with updated UIService api #1316

Merged
merged 1 commit into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions docs/site/content/en/openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1956,6 +1956,43 @@ paths:
default: true
type: boolean
example: false
- name: filter
in: query
description: either a required json sub-document or path expression
schema:
default: "{}"
type: string
example:
key: requiredValue
- name: sort
in: query
description: label name for sorting
schema:
default: ""
type: string
- name: direction
in: query
description: either Ascending or Descending
schema:
default: Ascending
type: string
example: count
- name: limit
in: query
description: the maximum number of results to include
schema:
format: int32
default: 2147483647
type: integer
example: 10
- name: page
in: query
description: which page to skip to when using a limit
schema:
format: int32
default: 0
type: integer
example: 2
responses:
"200":
description: OK
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public interface UIService {

@POST
@Path("view")
int updateView(@RequestBody(required = true) View view);
View updateView(@RequestBody(required = true) View view);

@POST
@Path("views")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class UIServiceImpl implements UIService {
@RolesAllowed("tester")
@WithRoles
@Transactional
public int updateView(View dto) {
public View updateView(View dto) {
if (dto.testId <= 0) {
throw ServiceException.badRequest("Missing test id on view");
}
Expand All @@ -49,7 +49,7 @@ public void createViews(List<View> views) {
}
}

private int doUpdate(TestDAO test, ViewDAO view) {
private View doUpdate(TestDAO test, ViewDAO view) {
view.ensureLinked();
view.test = test;
if (view.id == null || view.id < 0) {
Expand All @@ -63,7 +63,7 @@ private int doUpdate(TestDAO test, ViewDAO view) {
test.views.add(view);
test.persist();
em.flush();
return view.id;
return ViewMapper.from(view);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -388,12 +388,12 @@ protected void createViews(List<View> views) {
.statusCode(204);
}

protected int createView(View view) {
protected View createView(View view) {
return jsonRequest()
.body(view)
.post("/api/ui/view")
.then()
.statusCode(200).extract().body().as(Integer.class);
.statusCode(200).extract().body().as(View.class);
}

protected List<View> getViews(int testId) {
Expand Down Expand Up @@ -875,7 +875,7 @@ protected void populateDataFromFiles() throws IOException {
readFile(p.resolve("roadrunner_view.json").toFile()), View.class);
assertEquals("Default", view.name);
view.testId = t.id;
view.id = createView(view);
view = createView(view);

Schema s = new ObjectMapper().readValue(
readFile(p.resolve("acme_benchmark_schema.json").toFile()), Schema.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,10 @@ public void testUpdateView(TestInfo info) throws InterruptedException {
}

private void updateView(View view) {
Integer viewId = jsonRequest().body(view).post("/api/ui/view")
.then().statusCode(200).extract().body().as(Integer.class);
View newView = jsonRequest().body(view).post("/api/ui/view")
.then().statusCode(200).extract().body().as(View.class);
if (view.id != null) {
assertEquals(view.id, viewId);
assertEquals(view.id, newView.id);
}
}

Expand Down
2 changes: 1 addition & 1 deletion horreum-web/src/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ export function fetchViews(testId: number, alerting: AlertContextType): Promise<
export function updateAccess(id: number, owner: string, access: Access, alerting: AlertContextType) : Promise<void> {
return apiCall(testApi.updateAccess(id, access, owner), alerting, "UPDATE_ACCESS", "Failed to update test access");
}
export function updateView(alerting: AlertContextType, testId: number, view: View): Promise<number> {
export function updateView(alerting: AlertContextType, testId: number, view: View): Promise<View> {
for (const c of view.components) {
if (c.labels.length === 0) {
alerting.dispatchError(
Expand Down
43 changes: 30 additions & 13 deletions horreum-web/src/domain/tests/Views.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ export default function Views({ testId, testOwner, funcsRef, onModified, ...prop
const [views, setViews] = useState<ViewExtended[]>([])
const [deleted, setDeleted] = useState<number[]>([])
const [selectedView, setSelectedView] = useState<ViewExtended>()

useEffect(() => {
// Perform a deep copy of the view object to prevent modifying store
const copy = deepCopy(props.views)
Expand All @@ -123,21 +122,39 @@ export default function Views({ testId, testOwner, funcsRef, onModified, ...prop
}, [props.views])

funcsRef.current = {
save: () =>
Promise.all([
save: () =>{
return Promise.all([
...views
.filter(v => v.modified)
.map(view => updateView(alerting, testId, view).then(id => (view.id = id))),
...deleted.map(id => deleteView(alerting, testId, id)),
]).then(() => {
.map(async view => {
return updateView(alerting, testId, view)
}),
...deleted.map(id => { deleteView(alerting, testId, id); return null})
])
//removes the output of the ...deleted.map to satisfy TypeScript type check
.then(hasNulls => hasNulls.filter(v => v !=null) as View[])
.then((updatedViews) => {
//A better solution is for the parent to provide updated views props whenever views change
const newViews = [...updatedViews]
//add any existing views that were not updated and have valid ids
views
.filter(oldView => oldView.id >= 0)//exclude any local temporary views
.forEach(oldView => (
newViews.some((newView : ViewExtended) => oldView.id == newView.id)
? null : newViews.unshift(oldView) //use unshift to preserve view order
)
)
setDeleted([])
setViews(
views.map(v => {
delete v.modified
return v
})
)
}),
//have to update selectedView because if it was a new view (id < 0) it will no longer be in views
if(selectedView && 'id' in selectedView){
const found = newViews.filter(v => v.id === selectedView.id)
if(found && found.length === 1){
setSelectedView(found[0]);
}
}
setViews(newViews);
})
},
reset: () => {
setDeleted([])
setViews(deepCopy(props.views))
Expand Down
Loading