From bf1d0074010bd90158bb6d077f3d56ac4fe19ebd Mon Sep 17 00:00:00 2001 From: Norbert Csaba Herczeg Date: Thu, 5 Sep 2024 19:03:30 +0200 Subject: [PATCH] JNG-5914 table tag representation --- .../Planet/View/PlanetView.tsx.snapshot | 1 + .../Galaxy/Form/ViewGalaxyForm.tsx.snapshot | 1 + .../Galaxy/View/ViewGalaxyView.tsx.snapshot | 15 +- .../model/ActionGroupTest-ui.model | 4 +- .../react/UiPageContainerHelper.java | 7 + .../ui/generator/react/UiWidgetHelper.java | 8 + .../containers/components/tag/index.tsx.hbs | 148 ++++++++++++++++++ .../containers/components/tag/types.ts.hbs | 72 +++++++++ .../actor/src/containers/container.tsx.hbs | 1 + .../src/containers/widget-fragments/table.hbs | 4 + .../src/main/resources/ui-react.yaml | 20 +++ pom.xml | 2 +- 12 files changed, 267 insertions(+), 16 deletions(-) create mode 100644 judo-ui-react/src/main/resources/actor/src/containers/components/tag/index.tsx.hbs create mode 100644 judo-ui-react/src/main/resources/actor/src/containers/components/tag/types.ts.hbs diff --git a/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/Planet/View/PlanetView.tsx.snapshot b/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/Planet/View/PlanetView.tsx.snapshot index 44d03a1b..511e2583 100644 --- a/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/Planet/View/PlanetView.tsx.snapshot +++ b/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/Planet/View/PlanetView.tsx.snapshot @@ -30,6 +30,7 @@ import { isErrorOperationFault, useErrorHandler } from '~/utilities'; import {} from '@mui/x-date-pickers'; import type {} from '@mui/x-date-pickers'; import {} from '~/components/widgets'; +import { Tags } from '~/components/widgets'; import { useConfirmationBeforeChange } from '~/hooks'; import type { Planet, PlanetStored } from '~/services/data-api/model/Planet'; import { PLANET_VIEW_CONTAINER_ACTIONS_HOOK_INTERFACE_KEY } from './customization'; diff --git a/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/Form/ViewGalaxyForm.tsx.snapshot b/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/Form/ViewGalaxyForm.tsx.snapshot index 598572ac..ee7b31d1 100644 --- a/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/Form/ViewGalaxyForm.tsx.snapshot +++ b/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/Form/ViewGalaxyForm.tsx.snapshot @@ -36,6 +36,7 @@ import { isErrorOperationFault, useErrorHandler } from '~/utilities'; import { DateTimePicker } from '@mui/x-date-pickers'; import type { DateTimeValidationError } from '@mui/x-date-pickers'; import { NumericInput } from '~/components/widgets'; +import { Tags } from '~/components/widgets'; import { autoFocusRefDelay } from '~/config'; import { useConfirmationBeforeChange } from '~/hooks'; import type { ViewAstronomer, ViewAstronomerStored } from '~/services/data-api/model/ViewAstronomer'; diff --git a/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/View/ViewGalaxyView.tsx.snapshot b/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/View/ViewGalaxyView.tsx.snapshot index a2a0d450..9660e752 100644 --- a/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/View/ViewGalaxyView.tsx.snapshot +++ b/judo-ui-react-itest/ActionGroupTest/action_group_test__god/src/test/resources/snapshots/frontend-react/src/containers/View/Galaxy/View/ViewGalaxyView.tsx.snapshot @@ -42,6 +42,7 @@ import { isErrorOperationFault, useErrorHandler } from '~/utilities'; import { DateTimePicker } from '@mui/x-date-pickers'; import type { DateTimeValidationError } from '@mui/x-date-pickers'; import { AssociationButton, NumericInput } from '~/components/widgets'; +import { Tags } from '~/components/widgets'; import { useConfirmationBeforeChange } from '~/hooks'; import type { ViewAstronomer, ViewAstronomerStored } from '~/services/data-api/model/ViewAstronomer'; import type { ViewGalaxy, ViewGalaxyStored } from '~/services/data-api/model/ViewGalaxy'; @@ -158,19 +159,7 @@ export default function ViewGalaxyView(props: ViewGalaxyViewProps) { alignItems="stretch" justifyContent="flex-start" > - + {'LMAO'} diff --git a/judo-ui-react-itest/ActionGroupTest/model/ActionGroupTest-ui.model b/judo-ui-react-itest/ActionGroupTest/model/ActionGroupTest-ui.model index e50dfc3f..d6986b09 100644 --- a/judo-ui-react-itest/ActionGroupTest/model/ActionGroupTest-ui.model +++ b/judo-ui-react-itest/ActionGroupTest/model/ActionGroupTest-ui.model @@ -5674,7 +5674,7 @@ - + @@ -7299,7 +7299,7 @@ - + diff --git a/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPageContainerHelper.java b/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPageContainerHelper.java index 425b75ac..5a8e7663 100644 --- a/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPageContainerHelper.java +++ b/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiPageContainerHelper.java @@ -55,6 +55,13 @@ public static List getLinksForPageContainers(Application application) { public static List getTablesForPageContainers(Application application) { return application.getPageContainers().stream().flatMap(c -> ((List
) c.getTables()).stream()) + .filter(t -> TableRepresentation.TABLE.equals(t.getRepresentationComponent())) + .collect(Collectors.toList()); + } + + public static List
getTagsForPageContainers(Application application) { + return application.getPageContainers().stream().flatMap(c -> ((List
) c.getTables()).stream()) + .filter(t -> TableRepresentation.TAG.equals(t.getRepresentationComponent())) .collect(Collectors.toList()); } diff --git a/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiWidgetHelper.java b/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiWidgetHelper.java index 621d9edd..26c234b2 100644 --- a/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiWidgetHelper.java +++ b/judo-ui-react/src/main/java/hu/blackbelt/judo/ui/generator/react/UiWidgetHelper.java @@ -202,6 +202,14 @@ public static String tableComponentName(Table table) { .collect(Collectors.joining()) + "Component"; } + public static String tagComponentName(Table table) { + return tableComponentName(table); + } + + public static boolean isTableTag(Table table) { + return TableRepresentation.TAG.equals(table.getRepresentationComponent()); + } + public static Column getFirstAutocompleteColumnForLink(Link link) { Optional column = link.getParts().stream() .filter(c -> c.getAttributeType().getDataType() instanceof StringType && !c.getAttributeType().getIsMemberTypeTransient()) diff --git a/judo-ui-react/src/main/resources/actor/src/containers/components/tag/index.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/containers/components/tag/index.tsx.hbs new file mode 100644 index 00000000..2666aeaf --- /dev/null +++ b/judo-ui-react/src/main/resources/actor/src/containers/components/tag/index.tsx.hbs @@ -0,0 +1,148 @@ +{{> fragment.header.hbs }} + +import { useState, useEffect, useMemo, useRef, useCallback } from 'react'; +import type { ElementType, MouseEvent, Dispatch, SetStateAction, FC } from 'react'; +import { useTranslation } from 'react-i18next'; +import type { JudoIdentifiable } from '~/services/data-api/common/JudoIdentifiable'; +import type { JudoRestResponse } from '~/services/data-api/rest/requestResponse'; +import Box from '@mui/material/Box'; +import IconButton from '@mui/material/IconButton'; +import Button from '@mui/material/Button'; +import ButtonGroup from '@mui/material/ButtonGroup'; +import Typography from '@mui/material/Typography'; +import { GridLogicOperator, useGridApiRef } from '@mui/x-data-grid{{ getMUIDataGridPlanSuffix }}'; +{{# if isMUILicensePlanPro }} +import { gridColumnDefinitionsSelector } from '@mui/x-data-grid{{ getMUIDataGridPlanSuffix }}'; +{{/ if }} +import type { + GridColDef, + GridFilterModel, + GridRowModel, + GridRowId, + GridRenderCellParams, + GridRowSelectionModel, + GridSortItem, + GridSortModel, + GridRowClassNameParams, + GridRowParams, + GridValidRowModel, +} from '@mui/x-data-grid{{ getMUIDataGridPlanSuffix }}'; +import { baseColumnConfig, baseTableConfig, basePageSizeOptions{{# unless table.isEager }}, filterDebounceMs{{/ unless }} } from '~/config'; +import { MdiIcon{{# unless table.isEager }}, CustomTablePagination{{/ unless }} } from '~/components'; +import { + {{# if (tableHasBooleanColumn table) }}booleanColumnOperators,{{/ if }} + {{# if (tableHasDateColumn table) }}dateColumnOperators,{{/ if }} + {{# if (tableHasDateTimeColumn table) }}dateTimeColumnOperators,{{/ if }} + {{# if (tableHasNumericColumn table) }}numericColumnOperators,{{/ if }} + {{# if (tableHasEnumerationColumn table) }}singleSelectColumnOperators,{{/ if }} + {{# if isUseInlineColumnFilters }}stringColumnOperators,{{/ if }} + columnsActionCalculator, + ContextMenu, + StripedDataGrid, + EagerTable, + LazyTable, +} from '~/components/table'; +import { Tags } from '~/components/widgets'; +import { useConfirmDialog } from '~/components/dialog'; +import type { ContextMenuApi } from '~/components/table/ContextMenu'; +import type { Filter, FilterOption } from '~/components-api'; +import { FilterType } from '~/components-api'; +import { CUSTOM_VISUAL_ELEMENT_INTERFACE_KEY } from '~/custom'; +{{# each (getTableAPIImports table container) as |imp| }} + import type { + {{ imp }}, + {{ imp }}Stored, + } from '~/services/data-api/model/{{ imp }}'; + import type { + {{ imp }}QueryCustomizer, + } from '~/services/data-api/rest/{{ imp }}QueryCustomizer'; +{{/ each }} +{{# or (tableHasNumericColumn table) (tableHasDateColumn table) (tableHasDateTimeColumn table) }} +import { useL10N } from '~/l10n/l10n-context'; +{{/ or }} +import { + TABLE_COLUMN_CUSTOMIZER_HOOK_INTERFACE_KEY, + randomUtils, + {{# if container.isSelector }} + isRowSelectable, + {{ else }} + getUpdatedRowsSelected, + {{/ if }} + {{# if table.isEager }} + applyInMemoryFilters, + {{/ if }} + {{# if (tableHasBinaryColumn table) }} + fileHandling, + {{/ if }} + {{# if isUseInlineColumnFilters }} + mapFilterModelToFilters, + mapFilterToFilterModel, + {{/ if }} + mapAllFiltersToQueryCustomizerProperties, + processQueryCustomizer, + serializeFilters, + deserializeFilters, + {{# unless table.isEager }} + useErrorHandler, + {{/ unless }} +} from '~/utilities'; +import type { SidekickComponentProps, DialogResult, TableRowAction, ToolBarActionProps, ColumnCustomizerHook, FiltersSerializer{{# if isMUILicensePlanPro }}, PersistedColumnInfo{{/ if }} } from '~/utilities'; +import { OBJECTCLASS } from '@pandino/pandino-api'; +import { useTrackComponent, ComponentProxy } from '@pandino/react-hooks'; +{{# if (stringValueIsTrue useTableRowHighlighting) }} +import { useTrackService } from '@pandino/react-hooks'; +import { RowHighlightLegend } from '~/components/table'; +import { TABLE_ROW_HIGHLIGHTING_HOOK_INTERFACE_KEY, transformRowStylings } from '~/theme/table-row-highlighting'; +import type { RowStylerConfigured, TableRowHighlightingHook } from '~/theme/table-row-highlighting'; +{{/ if }} +import type { {{ componentName table }}ActionDefinitions, {{ componentName table }}Props } from './types'; +import { {{ classDataName (getReferenceClassType table) 'StoredSerializer' }} } from '~/services/data-api/rest/{{ classDataName (getReferenceClassType table) 'Serializer' }}'; + + +export const filtersSerializer: FiltersSerializer = { + serialize: (filters: Filter[]) => serializeFilters<{{ classDataName (getReferenceClassType table) 'Stored' }}>(filters, {{ classDataName (getReferenceClassType table) 'StoredSerializer' }}.getInstance()), + deserialize: (filters: Filter[]) => deserializeFilters<{{ classDataName (getReferenceClassType table) 'Stored' }}>(filters, {{ classDataName (getReferenceClassType table) 'StoredSerializer' }}.getInstance()), +}; + +// XMIID: {{ getXMIID table }} +// Name: {{ table.name }} +export function {{ componentName table }}(props: {{ componentName table }}Props) { + const { + uniqueId, + actions, + dataPath, + isOwnerLoading, + isDraft, + validationError, + ownerData, + editMode, + isFormUpdateable, + } = props; + + return ( +
+ + id="{{ getXMIID table }}" + label={'KUKAC'} + helperText={validationError} + error={!!validationError} + editMode={editMode} + ownerData={ownerData} + name="{{ table.relationName }}" + disabled={!isFormUpdateable()} + autoCompleteAttribute="{{ table.columns.[0].attributeType.name }}" + onAutoCompleteSearch={ async (searchText, preparedQueryCustomizer) => { + alert('lol'); + return Promise.resolve([]); + } } + onValueChange={ async (values) => { + console.log(values); + } } + onItemClick={(target) => alert('A')} + onSearchDialogsClick={() => alert('B')} + onClearDialogsClick={() => alert('C')} + identifierAttribute="__identifier" + /> +
+ ); +} diff --git a/judo-ui-react/src/main/resources/actor/src/containers/components/tag/types.ts.hbs b/judo-ui-react/src/main/resources/actor/src/containers/components/tag/types.ts.hbs new file mode 100644 index 00000000..9b520054 --- /dev/null +++ b/judo-ui-react/src/main/resources/actor/src/containers/components/tag/types.ts.hbs @@ -0,0 +1,72 @@ +import type { ElementType, Dispatch, SetStateAction } from 'react'; +import type { + GridFilterModel, +} from '@mui/x-data-grid{{ getMUIDataGridPlanSuffix }}'; +{{# each (getTableAPIImports table container) as |imp| }} + import type { + {{ imp }}, + {{ imp }}Stored, + } from '~/services/data-api/model/{{ imp }}'; + import type { + {{ imp }}QueryCustomizer, + } from '~/services/data-api/rest/{{ imp }}QueryCustomizer'; +{{/ each }} +import type { JudoRestResponse } from '~/services/data-api/rest/requestResponse'; +import type { Filter, FilterOption } from '~/components-api'; +import type { DialogResult } from '~/utilities'; + +export interface {{ componentName table }}ActionDefinitions { + get{{ firstToUpper table.relationName }}Mask?: () => string; + get{{ firstToUpper table.relationName }}RowRepresentation?: (row: {{ classDataName (getReferenceClassType table) 'Stored' }}) => string; +{{# each table.tableActionDefinitions as |actionDefinition| }} + {{# if actionDefinition.isFilterAction }} + {{ simpleActionDefinitionName actionDefinition }}?: (id: string, filterOptions: FilterOption[], model?: GridFilterModel, filters?: Filter[]) => Promise<{ model?: GridFilterModel; filters?: Filter[] }>; + {{ else }} + {{# if actionDefinition.isRefreshAction }} + {{ simpleActionDefinitionName actionDefinition }}?: (queryCustomizer: {{ classDataName (getReferenceClassType table) 'QueryCustomizer' }}) => Promise>; + {{ else }} + {{# if actionDefinition.isExportAction }} + {{ simpleActionDefinitionName actionDefinition }}?: (queryCustomizer: {{ classDataName (getReferenceClassType table) 'QueryCustomizer' }}) => Promise; + {{ else }} + {{# if actionDefinition.isSelectorRangeAction }} + {{ simpleActionDefinitionName actionDefinition }}?: (queryCustomizer: {{ classDataName (getReferenceClassType table) 'QueryCustomizer' }}) => Promise>; + {{ else }} + {{# if actionDefinition.isBulk }} + {{ simpleActionDefinitionName actionDefinition }}?: (selectedRows: {{ classDataName (getReferenceClassType table) 'Stored' }}[]) => Promise>; + {{ else }} + {{ simpleActionDefinitionName actionDefinition }}?: ({{# if actionDefinition.targetType }}target: {{ classDataName actionDefinition.targetType 'Stored' }}{{/ if }}) => Promise; + {{/ if }} + {{/ if }} + {{/ if }} + {{/ if }} + {{/ if }} +{{/ each }} +{{# each table.rowActionDefinitions as |actionDefinition| }} + {{ simpleActionDefinitionName actionDefinition }}?: (row: {{ classDataName (getReferenceClassType table) 'Stored' }}{{# if actionDefinition.isOpenPageAction }}, isDraft?: boolean{{/ if }}) => Promise; +{{/ each }} + {{ table.relationType.name }}AdditionalToolbarButtons?: ( + {{# with (getReferenceClassType table) as |classType| }} + data: {{# if classType.isMapped }}{{ classDataName classType 'Stored' }}{{ else }}{{ classDataName classType '' }}{{/ if }}[], + {{/ with }} + isLoading: boolean, + selectedRows: {{ classDataName (getReferenceClassType table) 'Stored' }}[], + clearSelections: () => void + {{# unless container.table }} + , ownerData: {{ classDataName container.dataElement 'Stored' }} + , editMode: boolean + , isFormUpdateable: () => boolean + {{/ unless }} + ) => Record; +} + +export interface {{ componentName table }}Props { + uniqueId: string; + actions: {{ componentName table }}ActionDefinitions; + dataPath?: string; + isOwnerLoading?: boolean; + isDraft?: boolean; + validationError?: string; + ownerData: {{ classDataName container.dataElement 'Stored' }}; + editMode: boolean; + isFormUpdateable: () => boolean; +} diff --git a/judo-ui-react/src/main/resources/actor/src/containers/container.tsx.hbs b/judo-ui-react/src/main/resources/actor/src/containers/container.tsx.hbs index 9149f70f..2017cb26 100644 --- a/judo-ui-react/src/main/resources/actor/src/containers/container.tsx.hbs +++ b/judo-ui-react/src/main/resources/actor/src/containers/container.tsx.hbs @@ -9,6 +9,7 @@ import { useTrackService } from '@pandino/react-hooks'; {{> actor/src/fragments/container/view-imports.fragment.hbs }} {{/ unless }} {{# unless (containerIsEmptyDashboard container) }} + import { Tags } from '~/components/widgets'; {{# each (getContainerApiImports container) as |imp| }} import type { {{ classDataName imp '' }}, {{ classDataName imp 'Stored' }} } from '~/services/data-api/model/{{ classDataName imp '' }}'; {{/ each }} diff --git a/judo-ui-react/src/main/resources/actor/src/containers/widget-fragments/table.hbs b/judo-ui-react/src/main/resources/actor/src/containers/widget-fragments/table.hbs index 2587a187..2136a6eb 100644 --- a/judo-ui-react/src/main/resources/actor/src/containers/widget-fragments/table.hbs +++ b/judo-ui-react/src/main/resources/actor/src/containers/widget-fragments/table.hbs @@ -30,6 +30,7 @@ {{/ if }} + {{# unless (isTableTag child) }} <{{ componentName child }} uniqueId={'{{ getXMIID child }}'} actions={actions} @@ -52,6 +53,9 @@ refreshCounter={refreshCounter} isOwnerLoading={isLoading} /> + {{ else }} + {'LMAO'} + {{/ unless }} diff --git a/judo-ui-react/src/main/resources/ui-react.yaml b/judo-ui-react/src/main/resources/ui-react.yaml index 65f1ba20..d85a4aca 100644 --- a/judo-ui-react/src/main/resources/ui-react.yaml +++ b/judo-ui-react/src/main/resources/ui-react.yaml @@ -758,6 +758,26 @@ templates: - name: table expression: "#self" + - name: actor/src/containers/components/tag/index.tsx + factoryExpression: "#getTagsForPageContainers(#application)" + pathExpression: "'src/containers/' + #containerPath(#self.pageContainer) + '/components/' + #tagComponentName(#self) + '/index.tsx'" + templateName: actor/src/containers/components/tag/index.tsx.hbs + templateContext: + - name: container + expression: "#self.pageContainer" + - name: table + expression: "#self" + + - name: actor/src/containers/components/tag/types.ts + factoryExpression: "#getTagsForPageContainers(#application)" + pathExpression: "'src/containers/' + #containerPath(#self.pageContainer) + '/components/' + #tagComponentName(#self) + '/types.ts'" + templateName: actor/src/containers/components/tag/types.ts.hbs + templateContext: + - name: container + expression: "#self.pageContainer" + - name: table + expression: "#self" + # Actor - src - pages - name: actor/src/pages/Redirect.tsx diff --git a/pom.xml b/pom.xml index ad814f23..3aef845a 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,7 @@ 18.14.2 8.9.2 - 1.1.0.20240725_123755_3c5f2837_develop + 1.1.0.20240905_151408_4d3b9bd0_feature_JNG_5914_table_tag_representation 1.0.0.20240712_085217_8319ce27_develop 1.0.0.20240823_165725_58575058_feature_JNG_5888_filter_context