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 eager relations #411

Merged
merged 13 commits into from
Jun 12, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -222,113 +222,18 @@ public static String getServiceMethodSuffix(Action action) {
return suffix;
}

public static String getDialogOpenParameters(PageDefinition pageDefinition) {
List<String> result = new ArrayList<>();
result.add("ownerData: any");
if (pageDefinition.getContainer().isView() && isPageDataElementUnmappedSingle(pageDefinition)) {
result.add("data: " + classDataName(getReferenceClassType(pageDefinition), ""));
}
if (!pageDefinition.getContainer().isIsSelector()) {
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") + "[]");
}
result.add("isDraft?: boolean");
if (!pageDefinition.getContainer().isIsSelector()) {
result.add("ownerValidation?: (data: " + classDataName(getReferenceClassType(pageDefinition), "") + ") => Promise<void>");
}
if (pageDefinition.getContainer().isForm()) {
result.add("maskRequest?: string");
}
return String.join(", ", result);
}

public static boolean isPageDataElementUnmappedSingle(PageDefinition pageDefinition) {
return pageHasOutputTarget(pageDefinition)
&& !getPageOutputTarget(pageDefinition).isIsMapped()
&& pageDefinition.getDataElement() instanceof OperationParameterType parameterType &&
!parameterType.isIsCollection();
}

public static String getFormOpenParameters(PageDefinition pageDefinition, Action action) {
List<String> tokens = new ArrayList<>();

if (action.getActionDefinition().getIsOpenFormAction() && pageDefinition.getContainer().isIsRelationSelector()) {
return "ownerData";
}
if (action.getActionDefinition().getTargetType() != null) {
tokens.add("target");
} else {
if (pageDefinition.getContainer().isTable()) {
if (pageDefinition.getRelationType() != null && !pageDefinition.getRelationType().isIsAccess()) {
tokens.add("{ __signedIdentifier: signedIdentifier } as JudoIdentifiable<any>");
} else {
tokens.add("null as any");
}
} else {
tokens.add("data");
if (isRelationOpenCreateActionOnEagerView(pageDefinition, action)) {
if (tokens.size() < 2) {
tokens.add("undefined");
}
tokens.add("true");
}
}
}
if (isRelationOpenCreateActionOnForm(pageDefinition, action)) {
if (tokens.size() < 2) {
tokens.add("undefined");
}
tokens.add("true");
tokens.add("validate" + firstToUpper(action.getTargetDataElement().getName()));

Link link = getLinkParentForActionDefinition(action.getActionDefinition());

if (link != null) {
var col = getFirstAutocompleteColumnForLink(link);
tokens.add("'{" + (col != null ? col.getAttributeType().getName() : "") + "}'");
}
public static RelationType getRelationTypeForActionTarget(Action action) {
if (action.getTargetDataElement() instanceof RelationType check) {
return check;
}

return String.join(", ", tokens);
}

public static String getSelectorOpenActionParameters(Action action, PageContainer container) {
List<String> tokens = new ArrayList<>();
if (container.isTable()) {
if (action.getTargetPageDefinition().getContainer().isIsRelationSelector()) {
tokens.add("{ __signedIdentifier: signedIdentifier }");
} else {
tokens.add("[]");
}
} else {
if (action.getActionDefinition().getTargetType() != null) {
tokens.add("target!");
} else {
tokens.add("data");
}
}

if (action.getTargetPageDefinition().getContainer().isIsRelationSelector()) {
if (action.getTargetDataElement() instanceof RelationType check) {
if (container.isTable()) {
tokens.add("[]");
} else {
String result = "data." + check.getName();
boolean isCollection = check.isIsCollection();
if (isCollection) {
tokens.add(result + " ?? []");
} else {
tokens.add(result + "? [" + result + "] : []");
}
}
}
}
return String.join(", ", tokens);
return null;
}

public static boolean isActionAddOrSet(ActionDefinition actionDefinition) {
Expand Down Expand Up @@ -369,7 +274,7 @@ public static String refreshActionDataParameter(Action action) {
return "ownerData";
}
if (pageHasSignedId(pageDefinition)) {
return "{ __signedIdentifier: signedIdentifier } as JudoIdentifiable<any>";
return "{ __signedIdentifier: signedIdentifier } as any";
}
if (isSingleAccessPage(pageDefinition)) {
return "singletonHost.current";
Expand Down Expand Up @@ -543,4 +448,9 @@ public static boolean isActionParentEagerElement(Action action) {
}
return false;
}

public static boolean isActionParentEagerTable(Action action) {
Table table = getTableParentForActionDefinition(action.getActionDefinition());
return table != null && table.isIsEager();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,47 +127,37 @@ public static void fillFlattenedVisualElements(Container container, SortedSet<Vi
});
}

public static String getTableAPIImports(Table table, PageContainer container) {
public static List<String> getTableAPIImports(Table table, PageContainer container) {
Set<String> res = new HashSet<>();

if (!container.isTable() && container.getDataElement() instanceof ClassType dataElement) {
res.add(classDataName(dataElement, ""));
res.add(classDataName(dataElement, "Stored"));
}

ClassType classType = getReferenceClassType(table);

if (classType != null) {
res.add(classDataName(classType, ""));
res.add(classDataName(classType, "Stored"));
res.add(classDataName(classType, "QueryCustomizer"));
}

return res.stream().sorted().collect(Collectors.joining(", "));
return res.stream().sorted().toList();
}

public static String getLinkAPIImports(Link link, PageContainer container) {
public static List<String> getLinkAPIImports(Link link, PageContainer container) {
Set<String> res = new HashSet<>();

if (!container.isTable() && container.getDataElement() instanceof ClassType dataElement) {
res.add(classDataName(dataElement, ""));
res.add(classDataName(dataElement, "Stored"));
}

if (link.getDataElement() instanceof RelationType relationType) {
ClassType classType = relationType.getTarget();

if (classType != null) {
res.add(classDataName(classType, ""));
res.add(classDataName(classType, "Stored"));
res.add(classDataName(classType, "QueryCustomizer"));
}
}

if (link.getRefreshActionDefinition() != null) {
res.add("JudoRestResponse");
}

return res.stream().sorted().collect(Collectors.joining(", "));
return res.stream().sorted().toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.stream.Collectors;

import static hu.blackbelt.judo.ui.generator.react.UiActionsHelper.getActionOperationOutputClassType;
import static hu.blackbelt.judo.ui.generator.react.UiActionsHelper.isPageDataElementUnmappedSingle;
import static hu.blackbelt.judo.ui.generator.react.UiWidgetHelper.collectVisualElementsMatchingCondition;
import static hu.blackbelt.judo.ui.generator.react.UiWidgetHelper.getReferenceClassType;
import static hu.blackbelt.judo.ui.generator.typescript.rest.commons.UiCommonsHelper.*;
Expand Down Expand Up @@ -458,7 +459,7 @@ public static boolean hasExportAction(PageDefinition pageDefinition) {
return pageDefinition.getActions().stream().anyMatch(page -> page.getIsExportAction());
}

public static boolean isDialogValidationSupported(PageDefinition pageDefinition) {
public static boolean isValidationSupported(PageDefinition pageDefinition) {
if (pageDefinition.getRelationType() != null) {
if (pageDefinition.getContainer().isView() && pageDefinition.getRelationType().getIsUpdateValidatable()) {
return true;
Expand All @@ -468,4 +469,20 @@ public static boolean isDialogValidationSupported(PageDefinition pageDefinition)
}
return false;
}

public static String dialogDataInitialValue(PageDefinition pageDefinition) {
if (pageDefinition.getContainer().isTable()) {
return "[]";
} else {
if (pageDefinition.getContainer().isView()) {
if (isPageDataElementUnmappedSingle(pageDefinition)) {
return "output";
} else {
return "(isDraft ? simpleCloneDeep(getValue(ownerData, dataPath!, {})) : {})";
}
} else {
return "(templateDataOverride ?? {})";
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import type {
Operation,
} from '../../components-api';
import { FilterType } from '../../components-api';
import { dateToJudoDateString, exists, uiDateToServiceDate, serviceDateToUiDate } from '../../utilities';
import { exists } from '../../utilities';
import { mainContainerPadding } from '../../theme';
import { _BooleanOperation, _EnumerationOperation, _NumericOperation, _StringOperation } from '~/services/data-api/common/operations';
import { DropdownButton } from '../DropdownButton';
Expand Down Expand Up @@ -154,9 +154,9 @@ const FilterInput = ({ filter, setFilterValue, valueId }: FilterInputProps) => {
<DatePicker
className={valueId}
label={filter.filterOption.label ?? filter.filterOption.attributeName}
value={serviceDateToUiDate(filter.filterBy.value ?? null)}
value={filter.filterBy.value ?? null}
views={['year', 'month', 'day']}
onChange={(newValue) => setFilterValue(filter, uiDateToServiceDate(newValue))}
onChange={(newValue) => setFilterValue(filter, newValue)}
slotProps={ {
textField: {
InputProps: {
Expand All @@ -175,7 +175,7 @@ const FilterInput = ({ filter, setFilterValue, valueId }: FilterInputProps) => {
<DateTimePicker
className={valueId}
label={filter.filterOption.label ?? filter.filterOption.attributeName}
value={serviceDateToUiDate(filter.filterBy.value ?? null)}
value={filter.filterBy.value ?? null}
ampm={false}
ampmInClock={false}
views={['year', 'month', 'day', 'hours', 'minutes', 'seconds']}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
{{/ if }}
}
from '~/utilities';
import type { TableRowAction{{# if isMUILicensePlanPro }}, PersistedColumnInfo{{/ if }} } from '~/utilities';
import type { TableRowAction, FiltersSerializer{{# if isMUILicensePlanPro }}, PersistedColumnInfo{{/ if }} } from '~/utilities';
import type { QueryCustomizer } from '~/services/data-api/common/QueryCustomizer';
import { MdiIcon } from '../MdiIcon';
import { Box, Button, Typography } from '@mui/material';
Expand Down Expand Up @@ -85,6 +85,7 @@ interface EagerTableProps<T extends GridValidRowModel, TStored extends GridValid
isFormUpdateable?: () => boolean;
enabledByName?: string;
relationName: string;
filtersSerializer: FiltersSerializer;
}

export function EagerTable<T extends GridValidRowModel, TStored extends T, S extends QueryCustomizer<T>>(props: EagerTableProps<T, TStored>) {
Expand Down Expand Up @@ -120,6 +121,7 @@ export function EagerTable<T extends GridValidRowModel, TStored extends T, S ext
enabledByName,
relationName,
checkboxSelection,
filtersSerializer,
} = props;

const apiRef = useGridApiRef();
Expand Down Expand Up @@ -149,7 +151,7 @@ export function EagerTable<T extends GridValidRowModel, TStored extends T, S ext
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>([]);
const [sortModel, setSortModel] = useState<GridSortModel>(getItemParsedWithDefault(sortModelKey, defaultSortParamsForTable));
const [filterModel, setFilterModel] = useState<GridFilterModel>(getItemParsedWithDefault(filterModelKey, { items: [] }));
const [filters, setFilters] = useState<Filter[]>(getItemParsedWithDefault(filtersKey, []));
const [filters, setFilters] = useState<Filter[]>(filtersSerializer.deserialize(getItemParsedWithDefault(filtersKey, [])));
{{# if isMUILicensePlanPro }}
const [columnState, setColumnState] = useState<PersistedColumnInfo[]>(getItemParsedWithDefault(columnStateKey, []));
{{/ if }}
Expand Down Expand Up @@ -264,7 +266,7 @@ export function EagerTable<T extends GridValidRowModel, TStored extends T, S ext
page: 0,
}));
setFilters(newFilters);
setItemStringified(filtersKey, newFilters);
setItemStringified(filtersKey, filtersSerializer.serialize(newFilters));

setQueryCustomizer((prevQueryCustomizer: S | QueryCustomizer<T>) => {
// remove previous filter values, so that we can always start with a clean slate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
mapFilterToFilterModel,
{{/ if }}
} from '~/utilities';
import type { TableRowAction{{# if isMUILicensePlanPro }}, PersistedColumnInfo{{/ if }} } from '~/utilities';
import type { TableRowAction, FiltersSerializer{{# if isMUILicensePlanPro }}, PersistedColumnInfo{{/ if }} } from '~/utilities';
import type { JudoStored } from '~/services/data-api/common/JudoStored';
import type { QueryCustomizer } from '~/services/data-api/common/QueryCustomizer';
import { CustomTablePagination } from '~/components';
Expand Down Expand Up @@ -96,6 +96,7 @@ interface LazyTableProps<T extends GridValidRowModel, TStored extends GridValidR
enabledByName?: string;
checkboxSelection?: boolean;
relationName: string;
filtersSerializer: FiltersSerializer;
}

export function LazyTable<T extends GridValidRowModel, TStored extends T, S extends QueryCustomizer<T>>(props: LazyTableProps<T, TStored>) {
Expand Down Expand Up @@ -139,6 +140,7 @@ export function LazyTable<T extends GridValidRowModel, TStored extends T, S exte
enabledByName,
relationName,
checkboxSelection,
filtersSerializer,
} = props;

const apiRef = useGridApiRef();
Expand Down Expand Up @@ -170,7 +172,7 @@ export function LazyTable<T extends GridValidRowModel, TStored extends T, S exte
const [selectionModel, setSelectionModel] = useState<GridRowSelectionModel>([]);
const [sortModel, setSortModel] = useState<GridSortModel>(getItemParsedWithDefault(sortModelKey, defaultSortParamsForTable));
const [filterModel, setFilterModel] = useState<GridFilterModel>(getItemParsedWithDefault(filterModelKey, { items: [] }));
const [filters, setFilters] = useState<Filter[]>(getItemParsedWithDefault(filtersKey, []));
const [filters, setFilters] = useState<Filter[]>(filtersSerializer.deserialize(getItemParsedWithDefault(filtersKey, [])));
{{# if isMUILicensePlanPro }}
const [columnState, setColumnState] = useState<PersistedColumnInfo[]>(getItemParsedWithDefault(columnStateKey, []));
{{/ if }}
Expand Down Expand Up @@ -308,7 +310,7 @@ export function LazyTable<T extends GridValidRowModel, TStored extends T, S exte
const handleFiltersChange = (newFilters: Filter[]) => {
setPage(0);
setFilters(newFilters);
setItemStringified(filtersKey, newFilters);
setItemStringified(filtersKey, filtersSerializer.serialize(newFilters));

setQueryCustomizer((prevQueryCustomizer: S | QueryCustomizer<T>) => {
// remove previous filter values, so that we can always start with a clean slate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const columnsActionCalculator: ColumnActionsProvider<any, any> = (
t: TFunction<string, any>,
isLoading: boolean,
getSelectedRows: () => any[],
ownerdata?: any,
ownerData?: any,
options?: ColumnsActionsOptions,
): GridActionsColDef[] => {
const safeOptions: ColumnsActionsOptions = {
Expand Down Expand Up @@ -51,7 +51,7 @@ export const columnsActionCalculator: ColumnActionsProvider<any, any> = (
key={a.id}
variant="text"
startIcon={a.icon}
disabled={a.disabled ? a.disabled(params.row, isLoading, getSelectedRows, ownerdata) : false}
disabled={a.disabled ? a.disabled(params.row, isLoading, getSelectedRows, ownerData) : false}
onClick={() => a.action!(params.row)}
>
{a.label ?? ''}
Expand All @@ -66,7 +66,7 @@ export const columnsActionCalculator: ColumnActionsProvider<any, any> = (
label: action.label,
startIcon: action.icon,
onClick: () => action.action!(params.row),
disabled: action.disabled ? action.disabled(params.row, isLoading, getSelectedRows, ownerdata) : false,
disabled: action.disabled ? action.disabled(params.row, isLoading, getSelectedRows, ownerData) : false,
}))}
>
<MdiIcon path="menu-down" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { MdiIcon } from '~/components/MdiIcon';
import { debounce } from '@mui/material/utils';
import { debounceInputs } from '~/config/general';
import { QueryCustomizer } from '~/services/data-api/common/QueryCustomizer';
import { FilterBytypesString } from '~/services/data-api/rest/FilterBytypesString';
import { FilterByTypesString } from '~/services/data-api/rest/FilterByTypesString';
import { StringOperation } from '~/services/data-api/model/StringOperation';

export interface TagsProps<P, T> {
Expand Down Expand Up @@ -78,7 +78,7 @@ export function Tags<P, T> (props: TagsProps<P, T>) {
const handleSearch = async (searchText: string) => {
try {
setLoading(true);
const filter: FilterBytypesString[] = (ownerData[name] as T[] ?? []).map((c: any) => ({
const filter: FilterByTypesString[] = (ownerData[name] as T[] ?? []).map((c: any) => ({
value: c[autoCompleteAttribute]!,
operator: StringOperation.notEqual,
}));
Expand Down
Loading
Loading