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

JNG-5742 fix eager table action lifecycle #407

Merged
merged 22 commits into from
Jun 4, 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
130 changes: 65 additions & 65 deletions judo-ui-react-itest/ActionGroupTest/model/ActionGroupTest-ui.model

Large diffs are not rendered by default.

Large diffs are not rendered by default.

484 changes: 242 additions & 242 deletions judo-ui-react-itest/CRUDActionsTest/model/CRUDActionsTest-ui.model

Large diffs are not rendered by default.

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions judo-ui-react/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@
<artifactId>judo-ui-typescript-rest-commons</artifactId>
<version>${judo-ui-typescript-rest-version}</version>
</dependency>

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.5.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,11 @@ public static String getDialogOpenParameters(PageDefinition pageDefinition) {
result.add("data: " + classDataName(getReferenceClassType(pageDefinition), ""));
}
if (!pageDefinition.getContainer().isIsSelector()) {
result.add("templateDataOverride?: Partial<" + classDataName(getReferenceClassType(pageDefinition), ">"));
if (pageDefinition.getContainer().isView()) {
result.add("templateDataOverride?: " + classDataName(getReferenceClassType(pageDefinition), "Stored"));
} else {
result.add("templateDataOverride?: Partial<" + classDataName(getReferenceClassType(pageDefinition), ">"));
}
} else if (pageDefinition.getContainer().isIsRelationSelector()) {
result.add("alreadySelected: " + classDataName(getReferenceClassType(pageDefinition), "Stored") + "[]");
}
Expand Down Expand Up @@ -267,6 +271,12 @@ public static String getFormOpenParameters(PageDefinition pageDefinition, Action
}
} else {
tokens.add("data");
if (isRelationOpenCreateActionOnEagerView(pageDefinition, action)) {
if (tokens.size() < 2) {
tokens.add("undefined");
}
tokens.add("true");
}
}
}
if (isRelationOpenCreateActionOnForm(pageDefinition, action)) {
Expand Down Expand Up @@ -386,6 +396,13 @@ public static boolean isRelationOpenCreateActionOnForm(PageDefinition pageDefini
&& relationType.isIsInlineCreatable();
}

public static boolean isRelationOpenCreateActionOnEagerView(PageDefinition pageDefinition, Action action) {
return pageDefinition.getContainer().isView()
&& action.getIsOpenFormAction()
&& action.getTargetDataElement() instanceof RelationType relationType
&& relationType.isIsInlineCreatable();
}
noherczeg marked this conversation as resolved.
Show resolved Hide resolved

public static String postCallOperationActionParams(PageDefinition page, ActionDefinition actionDefinition) {
List<String> tokens = new ArrayList<>();
if (actionDefinition.getTargetType() != null) {
Expand Down Expand Up @@ -477,15 +494,15 @@ public static String actionTargetPageName(Action action) {
}

public static boolean createNestedValidation(RelationType relationType, PageDefinition pageDefinition) {
return pageDefinition.getContainer().isForm() && relationType != null && (relationType.isIsInlineCreatable() || relationType.getIsCreateValidatable() || (relationType.getIsMemberTypeTransient() && !relationType.getTarget().isIsMapped()));
return relationType != null && !pageDefinition.getContainer().isTable() && (relationType.getIsCreateValidatable() || relationType.getIsUpdateValidatable());
}

public static boolean skipNestedValidationBody(PageDefinition pageDefinition) {
return pageDefinition.getDataElement() instanceof OperationParameterType operationParameterType && !operationParameterType.getTarget().isIsMapped();
}

public static boolean isRowActionCRUD(ActionDefinition actionDefinition) {
return actionDefinition.getIsRemoveAction() || actionDefinition.getIsDeleteAction();
return actionDefinition.getIsRemoveAction() || actionDefinition.getIsRowDeleteAction();
}

public static boolean allowRefreshAfterOperationCall(Action action) {
Expand Down Expand Up @@ -514,4 +531,16 @@ public static Action getRowViewActionForCreateOpenAction(Action action) {
}
return null;
}

public static boolean isActionParentEagerElement(Action action) {
Table table = getTableParentForActionDefinition(action.getActionDefinition());
Link link = getLinkParentForActionDefinition(action.getActionDefinition());
if (table != null) {
return table.isIsEager();
}
if (link != null) {
return link.isIsEager();
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import hu.blackbelt.judo.meta.ui.*;
import hu.blackbelt.judo.meta.ui.data.ClassType;
import hu.blackbelt.judo.meta.ui.data.EnumerationType;
import hu.blackbelt.judo.ui.generator.react.mask.MaskEntry;
import hu.blackbelt.judo.ui.generator.typescript.rest.commons.UiCommonsHelper;
import lombok.extern.java.Log;

Expand Down Expand Up @@ -149,32 +150,80 @@ public static String containerButtonAvailable(Button button) {
tokens.add("editMode");
} else if (button.getActionDefinition().getIsCancelAction() || button.getActionDefinition().getIsUpdateAction()) {
tokens.add("editMode");
} else if (button.getActionDefinition().getIsRefreshAction()) {
// In case of dialogs that are open in draft mode, we should consider checking actions
// because it could be possible that there are no valid use cases where these actions
// should be generated in the first place.
tokens.add("!isDraft");
} else {
tokens.add("!editMode");
}
return String.join(" && ", tokens);
}

public static String getMaskForTable(Table table) {
public static MaskEntry getMaskForTable(Table table, PageDefinition pageDefinition, Integer counter) {
MaskEntry mask = new MaskEntry(Set.of(), null);
Set<String> columnAttributeNames = table.getColumns().stream()
.map(c -> c.getAttributeType().getName())
.collect(Collectors.toSet());
columnAttributeNames.addAll(table.getAdditionalMaskAttributes().stream().map(NamedElement::getName).collect(Collectors.toSet()));
String tableColumns = String.join(",", columnAttributeNames.stream().sorted().toList());
mask.addPrimitives(columnAttributeNames);
if (table.isIsEager() && counter < 5) {
// table items can be potentially opened, therefore we need the target's attributes as well
Button openPageButton = table.getRowActionButtonGroup().getButtons().stream()
.filter(b -> b.getActionDefinition().getIsOpenPageAction())
.findFirst().orElse(null);
if (openPageButton != null) {
OpenPageActionDefinition def = (OpenPageActionDefinition) openPageButton.getActionDefinition();
Action openAction = pageDefinition.getActions().stream().filter(a -> a.getActionDefinition().equals(def)).findFirst().orElse(null);
if (openAction != null && openAction.getTargetPageDefinition() != null) {
MaskEntry viewMask = getMaskForView(openAction.getTargetPageDefinition(), counter + 1);
mask.addPrimitives(viewMask.getPrimitives());
mask.addRelations(viewMask.getRelations());
}
}
}

return mask;
}
noherczeg marked this conversation as resolved.
Show resolved Hide resolved

return "{" + tableColumns + "}";
public static String serializeMaskForTable(Table table, PageDefinition pageDefinition) {
return "{" + getMaskForTable(table, pageDefinition, 0).serialize() + "}";
noherczeg marked this conversation as resolved.
Show resolved Hide resolved
}

public static String getMaskForLink(Link link) {
public static MaskEntry getMaskForLink(Link link, PageDefinition pageDefinition, Integer counter) {
MaskEntry mask = new MaskEntry(Set.of(), null);
Set<String> columnAttributeNames = ((List<Column>) link.getColumns()).stream().map(c -> c.getAttributeType().getName()).collect(Collectors.toSet());
columnAttributeNames.addAll(link.getAdditionalMaskAttributes().stream().map(NamedElement::getName).collect(Collectors.toSet()));
String linkColumns = String.join(",", columnAttributeNames.stream().sorted().toList());
mask.addPrimitives(columnAttributeNames);

return "{" + linkColumns + "}";
if (link.isIsEager() && counter < 5) {
// link items can be potentially opened, therefore we need the target's attributes as well
Button openPageButton = link.getActionButtonGroup().getButtons().stream()
.filter(b -> b.getActionDefinition().getIsOpenPageAction())
.findFirst().orElse(null);
if (openPageButton != null) {
OpenPageActionDefinition def = (OpenPageActionDefinition) openPageButton.getActionDefinition();
Action openAction = pageDefinition.getActions().stream().filter(a -> a.getActionDefinition().equals(def)).findFirst().orElse(null);
if (openAction != null && openAction.getTargetPageDefinition() != null) {
MaskEntry viewMask = getMaskForView(openAction.getTargetPageDefinition(), counter + 1);
mask.addPrimitives(viewMask.getPrimitives());
mask.addRelations(viewMask.getRelations());
}
}
}

return mask;
}

public static String serializeMaskForLink(Link link, PageDefinition pageDefinition) {
return "{" + getMaskForLink(link, pageDefinition, 0).serialize() + "}";
}

public static String getMaskForView(PageContainer container) {
Set<String> mask = new LinkedHashSet<>();
public static MaskEntry getMaskForView(PageDefinition pageDefinition, Integer counter) {
MaskEntry mask = new MaskEntry(Set.of(), null);
PageContainer container = pageDefinition.getContainer();
Set<String> tokens = new LinkedHashSet<>();

Set<VisualElement> inputs = new HashSet<>();
collectVisualElementsMatchingCondition(container, (VisualElement element) -> element instanceof AttributeBased, inputs);
Expand All @@ -193,17 +242,30 @@ public static String getMaskForView(PageContainer container) {
attributeNames.add(container.getTitleAttribute().getName());
}

mask.addAll(attributeNames.stream().sorted().toList());
mask.addPrimitives(attributeNames);

for (Table table: ((List<Table>) container.getTables()).stream().filter(t -> t.getRelationType().getIsRelationKindComposition() || t.getRelationType().getIsRelationKindAggregation()).toList()) {
mask.add(table.getDataElement().getName() + getMaskForTable(table));
MaskEntry tableMask = getMaskForTable(table, pageDefinition, counter + 1);
tableMask.setRelationName(table.getDataElement().getName());
mask.addRelations(tableMask);
}

for (Link link: ((List<Link>) container.getLinks()).stream().filter(t -> t.getRelationType().getIsRelationKindComposition() || t.getRelationType().getIsRelationKindAggregation()).toList()) {
mask.add(link.getDataElement().getName() + getMaskForLink(link));
MaskEntry linkMask = getMaskForLink(link, pageDefinition, counter + 1);
linkMask.setRelationName(link.getDataElement().getName());
mask.addRelations(linkMask);
}

return "{" + String.join(",", mask) + "}";
return mask;
}

public static String serializeMaskForView(PageDefinition pageDefinition) {
try {
return "{" + getMaskForView(pageDefinition, 0).serialize() + "}";
} catch (StackOverflowError e) {
// keeping this for debugging purposes
throw e;
}
}

public static boolean containerHasDateInput(PageContainer container) {
Expand All @@ -222,6 +284,10 @@ public static boolean containerHasTable(PageContainer container) {
return !container.getTables().isEmpty();
}

public static Table getFirstTableForContainer(PageContainer container) {
return (Table) container.getTables().stream().findFirst().orElse(null);
}

public static boolean containerHasNumericInput(PageContainer container) {
return !collectElementsOfType(container, new ArrayList<>(), NumericInput.class).isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,4 +457,15 @@ public static String calculateNavigationRoute(PageDefinition pageDefinition) {
public static boolean hasExportAction(PageDefinition pageDefinition) {
return pageDefinition.getActions().stream().anyMatch(page -> page.getIsExportAction());
}

public static boolean isDialogValidationSupported(PageDefinition pageDefinition) {
if (pageDefinition.getRelationType() != null) {
if (pageDefinition.getContainer().isView() && pageDefinition.getRelationType().getIsUpdateValidatable()) {
return true;
} else if (pageDefinition.getContainer().isForm() && pageDefinition.getRelationType().getIsCreateValidatable()) {
return true;
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -377,20 +377,21 @@ public static String tableRowButtonDisabledConditions(Button button, Table table
if (container.isView()) {
result += "(isFormUpdateable ? !isFormUpdateable() : false) || ";
}
} else if (button.getActionDefinition().getIsDeleteAction()) {
} else if (button.getActionDefinition().getIsRowDeleteAction()) {
if (!container.isTable()) {
result += "editMode || ";
if (!table.isIsEager()) {
result += "editMode || ";
}

if (table.getEnabledBy() != null) {
result += "(ownerData ? !ownerData." + table.getEnabledBy().getName() + " : false) || ";
}
}
result += "(typeof row.__deleteable === 'boolean' && !row.__deleteable) || ";

if (container.isView()) {
result += "(isFormUpdateable ? !isFormUpdateable() : false) || ";
}

result += "!row.__deleteable || ";
} else if (!container.isTable()) {
result += "editMode || ";
}
Expand Down Expand Up @@ -444,5 +445,6 @@ public static boolean isLinkAssociation(Link link) {

public static boolean displayTableHeading(Table table, PageContainer container) {
return elementHasIconOrLabel(table) && !container.isIsSelector() && !container.isTable();

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package hu.blackbelt.judo.ui.generator.react.mask;

import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

public class MaskEntry {
private final Set<String> primitives = new LinkedHashSet<>();
private String relationName;
private final Set<MaskEntry> relations = new LinkedHashSet<>();

public MaskEntry(Set<String> primitives, String relationName) {
if (primitives != null && !primitives.isEmpty()) {
this.primitives.addAll(primitives);
}
if (relationName != null) {
this.relationName = relationName;
}
}

public String getRelationName() {
return relationName;
}

public MaskEntry setRelationName(String rn) {
relationName = rn;
return this;
}

public Set<String> getPrimitives() {
return primitives;
}

public Set<MaskEntry> getRelations() {
return relations;
}

public MaskEntry addPrimitives(String... p) {
primitives.addAll(Set.of(p));
return this;
}

public MaskEntry addPrimitives(Set<String> ps) {
primitives.addAll(ps);
return this;
}

public MaskEntry addRelations(MaskEntry... r) {
relations.addAll(Set.of(r));
return this;
}

public MaskEntry addRelations(Set<MaskEntry> rs) {
relations.addAll(rs);
return this;
}

public String serialize() {
String p = primitives.stream()
.sorted()
.collect(Collectors.joining(","));
p += (!p.isEmpty() && !relations.isEmpty()) ? "," : "";
String r = relations.stream()
.sorted(Comparator.comparing(MaskEntry::getRelationName))
.map(MaskEntry::serialize)
.collect(Collectors.joining(","));
if (relationName != null) {
return relationName + "{" + p + r + "}";
}
return p + r;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ interface EagerTableProps<T extends GridValidRowModel, TStored extends GridValid
tableColumns: GridColDef<TStored>[];
tableRowActions: TableRowAction<T, TStored>[];
tableFilterOptions: FilterOption[];
mask: string;
isOwnerLoading?: boolean;
validationError?: string;
actions: any;
Expand All @@ -80,7 +79,7 @@ interface EagerTableProps<T extends GridValidRowModel, TStored extends GridValid
toolBarActions: ToolBarActionProps<T>[];
additionalToolbarButtons?: (...args: any[]) => Record<string, ElementType>;
tableHasSelectorColumn?: boolean;
maskAction?: () => string;
maskAction: () => string;
ownerData?: any;
checkboxSelection?: boolean;
isFormUpdateable?: () => boolean;
Expand All @@ -101,7 +100,6 @@ export function EagerTable<T extends GridValidRowModel, TStored extends T, S ext
tableColumns,
tableRowActions,
tableFilterOptions,
mask,
isOwnerLoading,
validationError,
actions,
Expand Down Expand Up @@ -162,7 +160,7 @@ export function EagerTable<T extends GridValidRowModel, TStored extends T, S ext
});

const [queryCustomizer, setQueryCustomizer] = useState<S | QueryCustomizer<T>>({
_mask: mask,
_mask: maskAction(),
_seek: {
limit: rowsPerPage + 1,
},
Expand Down
Loading
Loading