Skip to content
Open
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
8 changes: 4 additions & 4 deletions assay/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion assay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lint-fix": "eslint --fix"
},
"dependencies": {
"@labkey/components": "7.58.1"
"@labkey/components": "7.58.6-fb-saveView899.1"
},
"devDependencies": {
"@labkey/build": "10.1.2",
Expand Down
8 changes: 4 additions & 4 deletions core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"lint-branch-fix": "node lint.diff.mjs --currentBranch --fix"
},
"dependencies": {
"@labkey/components": "7.58.1",
"@labkey/components": "7.58.6-fb-saveView899.1",
"@labkey/themes": "1.9.5"
},
"devDependencies": {
Expand Down
8 changes: 4 additions & 4 deletions experiment/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion experiment/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"test-integration": "cross-env NODE_ENV=test jest --ci --runInBand -c test/js/jest.config.integration.js"
},
"dependencies": {
"@labkey/components": "7.58.1"
"@labkey/components": "7.58.6-fb-saveView899.1"
},
"devDependencies": {
"@labkey/build": "10.1.2",
Expand Down
8 changes: 4 additions & 4 deletions pipeline/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pipeline/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"build-prod": "npm run clean && cross-env NODE_ENV=production rspack build --config node_modules/@labkey/build/configs/prod.config.js"
},
"dependencies": {
"@labkey/components": "7.58.1"
"@labkey/components": "7.58.6-fb-saveView899.1"
},
"devDependencies": {
"@labkey/build": "10.1.2",
Expand Down
44 changes: 36 additions & 8 deletions query/src/org/labkey/query/controllers/QueryController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2534,7 +2534,7 @@ public void addNavTrail(NavTree root)
// Uck. Supports the old and new view designer.
protected JSONObject saveCustomView(Container container, QueryDefinition queryDef,
String regionName, String viewName, boolean replaceExisting,
boolean share, boolean inherit,
boolean share, boolean inherit, boolean inheritToTargetContainer,
boolean session, boolean saveFilter,
boolean hidden, JSONObject jsonView,
ActionURL returnUrl,
Expand All @@ -2558,8 +2558,19 @@ protected JSONObject saveCustomView(Container container, QueryDefinition queryDe
else
view = queryDef.getCustomView(owner, getViewContext().getRequest(), name);

// GitHub Issue #899: the lookups above also resolve views inherited from ancestor folders. Absent an explicit

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment at the top of this function is right. "Uck.".

// target folder, shadow that view with a new local one rather than editing (and relocating) the ancestor's.
CustomView inheritedView = null;
if (view != null && !inheritToTargetContainer && view.getContainer() != null && !container.equals(view.getContainer()))
{
inheritedView = view;
view = null;
}

if (view != null && !replaceExisting && !StringUtils.isEmpty(name))
errors.reject(ERROR_MSG, "A saved view by the name \"" + viewName + "\" already exists. ");
if (inheritedView != null && !replaceExisting && !StringUtils.isEmpty(name))
errors.reject(ERROR_MSG, "A saved view by the name \"" + viewName + "\" is already inherited from folder \"" + inheritedView.getContainer().getPath() + "\". ");

// 11179: Allow editing the view if we're saving to session.
// NOTE: Check for session flag first otherwise the call to canEdit() will add errors to the errors collection.
Expand Down Expand Up @@ -2625,7 +2636,7 @@ else if (session != view.isSession())
try
{
view.delete(getUser(), getViewContext().getRequest());
JSONObject ret = saveCustomView(container, queryDef, regionName, viewName, replaceExisting, share, inherit, session, saveFilter, hidden, jsonView, returnUrl, errors);
JSONObject ret = saveCustomView(container, queryDef, regionName, viewName, replaceExisting, share, inherit, inheritToTargetContainer, session, saveFilter, hidden, jsonView, returnUrl, errors);
success = !errors.hasErrors() && ret != null;
return success ? ret : null;
}
Expand Down Expand Up @@ -2770,9 +2781,10 @@ public ApiResponse execute(SimpleApiJsonForm form, BindException errors)
boolean session = jsonView.optBoolean("session", false);
boolean hidden = jsonView.optBoolean("hidden", false);
// Users may save views to a location other than the current container
String containerPath = jsonView.optString("containerPath", getContainer().getPath());
String containerPath = jsonView.optString("containerPath", null);
boolean inheritToTargetContainer = inherit && containerPath != null;
Container container;
if (inherit)
if (inheritToTargetContainer)
{
// Only respect this request if it's a view that is inheritable in subfolders
container = ContainerManager.getForPath(containerPath);
Expand All @@ -2788,9 +2800,12 @@ public ApiResponse execute(SimpleApiJsonForm form, BindException errors)
throw new NotFoundException("No such container: " + containerPath);
}

if (inheritToTargetContainer && !container.hasPermission(getUser(), EditSharedViewPermission.class))
throw new UnauthorizedException();

JSONObject savedView = saveCustomView(
container, queryDef, QueryView.DATAREGIONNAME_DEFAULT, viewName, replace,
shared, inherit, session, true, hidden, jsonView, null, errors);
shared, inherit, inheritToTargetContainer, session, true, hidden, jsonView, null, errors);

if (savedView != null)
{
Expand Down Expand Up @@ -6220,8 +6235,9 @@ public ApiResponse execute(SaveSessionViewForm form, BindException errors)

// Users may save views to a location other than the current container
String containerPath = form.getContainerPath();
boolean inheritToTargetContainer = form.isInherit() && containerPath != null;
Container container;
if (form.isInherit() && containerPath != null)
if (inheritToTargetContainer)
{
// Only respect this request if it's a view that is inheritable in subfolders
container = ContainerManager.getForPath(containerPath);
Expand Down Expand Up @@ -6265,6 +6281,19 @@ public ApiResponse execute(SaveSessionViewForm form, BindException errors)
existingView = null;
}

// GitHub Issue #899: getCustomView() also resolves views inherited from ancestor folders. Absent an explicit
// target folder, shadow that view with a new local one instead of rewriting (and un-inheriting) the ancestor's.
CustomView inheritedView = null;
if (existingView != null && !inheritToTargetContainer && existingView.getContainer() != null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Seems like some logical consolidation is in order with aligned logic in saveCustomView().

&& !container.equals(existingView.getContainer()))
{
inheritedView = existingView;
existingView = null;
}

if (inheritedView != null && !form.isReplace() && !StringUtils.isEmpty(form.getNewName()))
throw new IllegalArgumentException("A saved view by the name \"" + form.getNewName() + "\" is already inherited from folder \"" + inheritedView.getContainer().getPath() + "\". ");

if (existingView != null && !form.isReplace() && !StringUtils.isEmpty(form.getNewName()))
throw new IllegalArgumentException("A saved view by the name \"" + form.getNewName() + "\" already exists. ");

Expand All @@ -6278,8 +6307,7 @@ public ApiResponse execute(SaveSessionViewForm form, BindException errors)
viewCopy.setFilterAndSort(view.getFilterAndSort());
viewCopy.setColumnProperties(view.getColumnProperties());
viewCopy.setIsHidden(form.isHidden());
if (form.isInherit())
viewCopy.setContainer(container);
viewCopy.setContainer(container);

viewCopy.save(getUser(), getViewContext().getRequest());
}
Expand Down