Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
47488b6
LPD-9465 - Refactor. Move component to TS
juanjofgliferay Dec 5, 2025
ca3c5b3
LPD-9465 - Feat. Update model to store FDS Custom Views
juanjofgliferay Dec 5, 2025
2a11ed9
LPD-9465 - Feat. Serialize snapshots
juanjofgliferay Dec 5, 2025
f4f766c
LPD-9465 - Feat. Add deeClone utility
juanjofgliferay Dec 5, 2025
4375b89
LPD-9465 - Feat. Retrieve and handle user views/snapshots in FDS
juanjofgliferay Dec 5, 2025
dff3b58
LPD-9465 - Refactor. Remove Portalpreferences requests
juanjofgliferay Dec 5, 2025
5aaf6b9
LPD-9465 - Refactor. Update taglib
juanjofgliferay Dec 5, 2025
f441e0b
LPD-9465 - Refactor. Update table to handle visible columns properly
juanjofgliferay Dec 5, 2025
302dca8
LPD-9465 - Feat. Block ActiveViewSettings while working with User Vie…
juanjofgliferay Dec 5, 2025
5ddc364
LPD-9465 - Refactor. Update exclude prop when applying snapshot
juanjofgliferay Dec 5, 2025
d65fc99
LPD-9465 - Refactor. Prevent filter mutation on activate/deactivate f…
juanjofgliferay Dec 5, 2025
2f5a4ca
LPD-9465 - Feat. Include action that update filters without changing …
juanjofgliferay Dec 5, 2025
79ba2ce
LPD-9465 - Feat. Display table after loading CX
juanjofgliferay Dec 5, 2025
0e854d7
LPD-9465 - Add tests
juanjofgliferay Dec 5, 2025
1b397ba
LPD-9465 - Add feature flag
juanjofgliferay Dec 5, 2025
18513da
LPD-9465 - Feat. Add DSM UI to enable User Views
juanjofgliferay Dec 5, 2025
6af2438
LPD-9465 - Refactor. Update FDS Sample
juanjofgliferay Dec 5, 2025
1aa40c2
LPD-9465 - Refactor. Remove deprecation comment
juanjofgliferay Dec 5, 2025
871c681
LPD-9465 - Refactor. Rename property
juanjofgliferay Dec 5, 2025
9a392f7
LPD-9465 - Feat. Safe check
juanjofgliferay Dec 5, 2025
829a07a
LPD-9465 - Feat. Ensure defaultSnapshot has an empty array if no filt…
juanjofgliferay Dec 9, 2025
e1bdc1f
LPD-9465 - SF
juanjofgliferay Dec 9, 2025
f288af6
LPD-9465 - Baseline
juanjofgliferay Dec 9, 2025
2275e65
LPD-9465 - Refactor. Fix condition to avoid infinite spinner
juanjofgliferay Dec 9, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -183,13 +184,17 @@ public void render(
return;
}

Map<String, Object> properties = dataSetObjectEntry.getProperties();

if (!FeatureFlagManagerUtil.isEnabled(
_portal.getCompanyId(httpServletRequest), "LPD-38564")) {

_fdsRenderer.render(
HashMapBuilder.<String, Object>put(
"namespace",
fragmentRendererContext.getFragmentElementId()
).put(
"snapshotsEnabled", properties.get("snapshotsEnabled")
).put(
"style", "fluid"
).build(),
Expand Down Expand Up @@ -230,6 +235,8 @@ public void render(
HashMapBuilder.<String, Object>put(
"namespace",
fragmentRendererContext.getFragmentElementId()
).put(
"snapshotsEnabled", properties.get("snapshotsEnabled")
).put(
"style", "fluid"
).put(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const Settings = ({
onDataSetUpdate,
spritemap,
}: IDataSetSectionProps) => {
const [snapshotsEnabled, setSnapshotsEnabled] = useState<boolean>(
dataSet.snapshotsEnabled
);
const [defaultVisualizationMode, setDefaultVisualizationMode] = useState<
string | undefined
>(NOT_CONFIGURED_VISUALIZATION_MODE.type);
Expand All @@ -57,6 +60,7 @@ const Settings = ({
const body = {
defaultVisualizationMode,
hideManagementBarInEmptyState,
snapshotsEnabled,
};

const url = getDataSetResourceURL({
Expand Down Expand Up @@ -350,8 +354,8 @@ const Settings = ({
{Liferay.Language.get('user-customization')}
</h3>

<ClayLayout.Row className="align-items-center justify-content-between">
<ClayLayout.Col size={8}>
<ClayLayout.Row className="align-items-center justify-content-between mb-4">
<ClayLayout.Col size={11}>
<div>
<label
htmlFor="hide-management-bar-in-empty-state"
Expand All @@ -370,7 +374,7 @@ const Settings = ({
</div>
</ClayLayout.Col>

<ClayLayout.Col size={4}>
<ClayLayout.Col size={1}>
<div className="d-flex form-group justify-content-end mr-2">
<ClayToggle
disabled={loading}
Expand All @@ -380,6 +384,35 @@ const Settings = ({
</div>
</ClayLayout.Col>
</ClayLayout.Row>

{Liferay.FeatureFlags['LPD-10683'] && (
<ClayLayout.Row className="align-items-center justify-content-between mb-4">
<ClayLayout.Col size={11}>
<div>
<label htmlFor="user-views-toggle">
{Liferay.Language.get(
'enable-user-views'
)}
</label>
</div>

<div>
{Liferay.Language.get('user-views-help')}
</div>
</ClayLayout.Col>

<ClayLayout.Col
className="align-self-start"
size={1}
>
<ClayToggle
id="user-views-toggle"
onToggle={setSnapshotsEnabled}
toggled={snapshotsEnabled}
/>
</ClayLayout.Col>
</ClayLayout.Row>
)}
</ClayLayout.SheetSection>

<ClayLayout.SheetFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export interface IDataSet {
restApplication: string;
restEndpoint: string;
restSchema: string;
snapshotsEnabled: boolean;
sortsOrder?: string;
tableSectionsOrder?: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Bundle-Name: Liferay Frontend Data Set API
Bundle-SymbolicName: com.liferay.frontend.data.set.api
Bundle-Version: 24.0.1
Bundle-Version: 24.1.0
Export-Package:\
com.liferay.frontend.data.set,\
com.liferay.frontend.data.set.action,\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ public JSONObject serializePagination(
public String serializePropsTransformer(
String fdsName, HttpServletRequest httpServletRequest);

public JSONArray serializeSnapshots(
String fdsName, HttpServletRequest httpServletRequest);

public List<FDSSortItem> serializeSorts(
String fdsName, HttpServletRequest httpServletRequest);

Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version 4.2.0
version 4.3.0
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@
import com.liferay.portal.kernel.json.JSONUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.HashMapBuilder;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.template.react.renderer.ComponentDescriptor;
import com.liferay.portal.template.react.renderer.ReactRenderer;

Expand Down Expand Up @@ -110,6 +112,21 @@ public void render(
}
}
else {
Boolean snapshotsEnabled;

ThemeDisplay themeDisplay =
(ThemeDisplay)httpServletRequest.getAttribute(
WebKeys.THEME_DISPLAY);

if (Validator.isNull(props.get("snapshotsEnabled")) ||
!themeDisplay.isSignedIn()) {

snapshotsEnabled = false;
}
else {
snapshotsEnabled = (boolean)props.get("snapshotsEnabled");
}

props.putAll(
HashMapBuilder.<String, Object>put(
"additionalAPIURLParameters",
Expand Down Expand Up @@ -211,6 +228,25 @@ public void render(

return paginationJSONObject;
}
).put(
"snapshots",
() -> {
if (!snapshotsEnabled) {
return null;
}

JSONArray snapshotsJSONArray =
fdsSerializer.serializeSnapshots(
fdsName, httpServletRequest);

if (JSONUtil.isEmpty(snapshotsJSONArray)) {
return null;
}

return snapshotsJSONArray;
}
).put(
"snapshotsEnabled", snapshotsEnabled
).put(
"sorts",
() -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,30 @@

import com.liferay.frontend.data.set.internal.url.FDSAPIURLBuilder;
import com.liferay.frontend.data.set.url.FDSAPIURLResolverRegistry;
import com.liferay.object.entry.util.ObjectEntryThreadLocal;
import com.liferay.object.model.ObjectDefinition;
import com.liferay.object.rest.dto.v1_0.ObjectEntry;
import com.liferay.object.rest.manager.v1_0.DefaultObjectEntryManagerProvider;
import com.liferay.object.rest.manager.v1_0.ObjectEntryManager;
import com.liferay.object.rest.manager.v1_0.ObjectEntryManagerRegistry;
import com.liferay.object.service.ObjectDefinitionLocalService;
import com.liferay.petra.string.StringBundler;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.theme.ThemeDisplay;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.WebKeys;
import com.liferay.portal.vulcan.dto.converter.DefaultDTOConverterContext;
import com.liferay.portal.vulcan.pagination.Page;

import jakarta.servlet.http.HttpServletRequest;

import java.util.Collection;
import java.util.Map;

import org.osgi.service.component.annotations.Reference;

/**
Expand All @@ -26,7 +47,79 @@ public FDSAPIURLBuilder createFDSAPIURLBuilder(
restEndpoint, restSchema);
}

protected JSONArray serializeSnapshots(
String fdsName, HttpServletRequest httpServletRequest,
ObjectDefinitionLocalService objectDefinitionLocalService,
ObjectEntryManagerRegistry objectEntryManagerRegistry)
throws Exception {

ThemeDisplay themeDisplay =
(ThemeDisplay)httpServletRequest.getAttribute(
WebKeys.THEME_DISPLAY);

String filterExpression = StringBundler.concat(
"(fdsName eq '", fdsName, "' and creatorId eq ",
themeDisplay.getUserId(), ")");

ObjectEntryThreadLocal.setSkipObjectEntryResourcePermission(true);

JSONArray jsonArray = JSONUtil.putAll();

try {
ObjectDefinition objectDefinition =
objectDefinitionLocalService.fetchObjectDefinition(
PortalUtil.getCompanyId(httpServletRequest),
"DataSetSnapshot");

ObjectEntryManager objectEntryManager =
DefaultObjectEntryManagerProvider.provide(
objectEntryManagerRegistry.getObjectEntryManager(
objectDefinition.getCompanyId(),
objectDefinition.getStorageType()));

Page<ObjectEntry> page = objectEntryManager.getObjectEntries(
PortalUtil.getCompanyId(httpServletRequest), objectDefinition,
null, null,
new DefaultDTOConverterContext(
false, null, null, null, null,
LocaleUtil.getMostRelevantLocale(), null, null),
filterExpression, null, null, null);

Collection<ObjectEntry> objectEntries = page.getItems();

jsonArray = JSONUtil.toJSONArray(
objectEntries,
(ObjectEntry objectEntry) -> {
Map<String, Object> properties =
objectEntry.getProperties();

return JSONUtil.put(
"configuration", properties.get("viewConfig")
).put(
"erc", objectEntry.getExternalReferenceCode()
).put(
"label", String.valueOf(properties.get("label"))

Choose a reason for hiding this comment

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

medium

Using String.valueOf() on a potentially null object will result in the string literal "null". This is likely not what the frontend expects. It's better to pass the raw object from properties.get("label") to JSONUtil.put(), which will correctly serialize a null value to JSON null.

Suggested change
"label", String.valueOf(properties.get("label"))
"label", properties.get("label")

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

🤔 Not sure. I'm using the same pattern used in other FDS places

);
});
}
catch (Exception exception) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to get snapshot FDS config object entries",
exception);
}
}
finally {
ObjectEntryThreadLocal.setSkipObjectEntryResourcePermission(false);
}

return jsonArray;
}

@Reference
protected FDSAPIURLResolverRegistry fdsAPIURLResolverRegistry;

private static final Log _log = LogFactoryUtil.getLog(
BaseFDSSerializer.class);

}
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,22 @@ public String serializePropsTransformer(
return String.valueOf(properties.get("propsTransformer"));
}

@Override
public JSONArray serializeSnapshots(
String fdsName, HttpServletRequest httpServletRequest) {

try {
return serializeSnapshots(
fdsName, httpServletRequest, _objectDefinitionLocalService,
_objectEntryManagerRegistry);
}
catch (Exception exception) {
_log.error("Unable to serialize snapshots", exception);

return _jsonFactory.createJSONArray();
}
}

@Override
public List<FDSSortItem> serializeSorts(
String fdsName, HttpServletRequest httpServletRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,14 @@
import com.liferay.frontend.data.set.view.FDSViewContextContributorRegistry;
import com.liferay.frontend.data.set.view.FDSViewRegistry;
import com.liferay.frontend.taglib.clay.servlet.taglib.util.CreationMenu;
import com.liferay.object.rest.manager.v1_0.ObjectEntryManagerRegistry;
import com.liferay.object.service.ObjectDefinitionLocalService;
import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.json.JSONUtil;
import com.liferay.portal.kernel.language.LanguageUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.PortalUtil;
Expand Down Expand Up @@ -254,6 +258,22 @@ public String serializePropsTransformer(
return systemFDSEntry.getPropsTransformer();
}

@Override
public JSONArray serializeSnapshots(
String fdsName, HttpServletRequest httpServletRequest) {

try {
return serializeSnapshots(
fdsName, httpServletRequest, _objectDefinitionLocalService,
_objectEntryManagerRegistry);
}
catch (Exception exception) {
_log.error("Unable to serialize snapshots", exception);

return JSONUtil.putAll();
}
}

@Override
public List<FDSSortItem> serializeSorts(
String fdsName, HttpServletRequest httpServletRequest) {
Expand Down Expand Up @@ -400,6 +420,9 @@ private void _serializeFilters(
}
}

private static final Log _log = LogFactoryUtil.getLog(
SystemFDSSerializer.class);

private static final SystemFDSEntry _systemFDSEntry = new SystemFDSEntry() {

public int getDefaultItemsPerPage() {
Expand Down Expand Up @@ -442,4 +465,10 @@ public String getTitle() {

};

@Reference
private ObjectDefinitionLocalService _objectDefinitionLocalService;

@Reference
private ObjectEntryManagerRegistry _objectEntryManagerRegistry;

}
Loading