@nocobase/client-v2 2.2.0-beta.9 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/APIClient.d.ts +13 -3
- package/es/BaseApplication.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterface.d.ts +1 -0
- package/es/collection-field-interface/CollectionFieldInterfaceManager.d.ts +1 -0
- package/es/components/category-tabs/SortableCategoryTabs.d.ts +55 -0
- package/es/components/category-tabs/index.d.ts +9 -0
- package/es/components/form/ScanInput/useCodeScanner.d.ts +3 -2
- package/es/components/form/TypedVariableInput.d.ts +31 -5
- package/es/components/form/filter/CollectionFilter.d.ts +2 -0
- package/es/components/form/filter/CollectionFilterItem.d.ts +11 -1
- package/es/components/form/filter/CollectionFilterPanel.d.ts +2 -0
- package/es/components/form/filter/index.d.ts +2 -0
- package/es/components/form/filter/useFilterActionProps.d.ts +2 -0
- package/es/components/index.d.ts +1 -0
- package/es/flow/actions/index.d.ts +1 -1
- package/es/flow/actions/linkageRules.d.ts +27 -0
- package/es/flow/admin-shell/admin-layout/AdminLayoutMenuModels.d.ts +1 -0
- package/es/flow/components/FieldAssignExactDatePicker.d.ts +1 -0
- package/es/flow/components/FieldAssignValueInput.d.ts +7 -24
- package/es/flow/components/FlowRoute.d.ts +2 -2
- package/es/flow/components/RunJSValueEditor.d.ts +1 -0
- package/es/flow/components/field-value-variable/DateVariableEditor.d.ts +24 -0
- package/es/flow/components/field-value-variable/FieldValueVariableInput.d.ts +31 -0
- package/es/flow/components/field-value-variable/dateValue.d.ts +36 -0
- package/es/flow/components/field-value-variable/index.d.ts +11 -0
- package/es/flow/components/filter/FilterGroup.d.ts +1 -0
- package/es/flow/components/filter/VariableFilterItem.d.ts +6 -1
- package/es/flow/components/placeholders/BlockPlaceholder.d.ts +1 -0
- package/es/flow/index.d.ts +1 -0
- package/es/flow/internal/registerDeviceTypeContext.d.ts +10 -0
- package/es/flow/internal/utils/operatorSchemaHelper.d.ts +2 -2
- package/es/flow/models/actions/UpdateRecordActionUtils.d.ts +8 -2
- package/es/flow/models/base/ActionModelCore.d.ts +4 -2
- package/es/flow/models/base/BlockGridModel.d.ts +3 -0
- package/es/flow/models/base/CollectionBlockModel.d.ts +3 -0
- package/es/flow/models/base/PageModel/PageModel.d.ts +12 -0
- package/es/flow/models/base/PageModel/PageModelTabBar.d.ts +22 -0
- package/es/flow/models/base/PageModel/PageTabModel.d.ts +12 -0
- package/es/flow/models/blocks/details/DetailsBlockModel.d.ts +3 -0
- package/es/flow/models/blocks/filter-form/FilterFormGridModel.d.ts +1 -0
- package/es/flow/models/blocks/filter-form/FilterFormSubmitActionModel.d.ts +3 -1
- package/es/flow/models/blocks/form/FormBlockModel.d.ts +7 -0
- package/es/flow/models/blocks/form/FormGridModel.d.ts +6 -0
- package/es/flow/models/blocks/form/QuickEditFormModel.d.ts +17 -2
- package/es/flow/models/blocks/form/value-runtime/rules.d.ts +1 -0
- package/es/flow/models/blocks/table/JSColumnModel.d.ts +2 -0
- package/es/flow/models/blocks/table/TableBlockModel.d.ts +1 -0
- package/es/flow/models/blocks/table/TableColumnModel.d.ts +12 -0
- package/es/flow/models/blocks/table/utils.d.ts +1 -0
- package/es/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.d.ts +2 -1
- package/es/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.d.ts +0 -17
- package/es/flow/models/fields/AssociationFieldModel/recordSelectShared.d.ts +41 -0
- package/es/flow/models/fields/DateTimeFieldModel/dateLimit.d.ts +15 -7
- package/es/flow-compat/fieldValidationConstants.d.ts +1 -1
- package/es/flow-compat/passwordUtils.d.ts +1 -1
- package/es/flow-compat/routeTypes.d.ts +1 -0
- package/es/index.d.ts +5 -0
- package/es/index.mjs +199 -161
- package/es/ui-operation/index.d.ts +15 -0
- package/es/ui-operation/ui-operation-codec.d.ts +10 -0
- package/es/utils/getRouteRuntimeVersion.d.ts +23 -0
- package/es/utils/index.d.ts +1 -0
- package/lib/index.js +215 -177
- package/lib/locale/languageCodes.js +3 -1
- package/package.json +9 -7
- package/src/APIClient.ts +90 -7
- package/src/Application.tsx +7 -1
- package/src/BaseApplication.tsx +11 -6
- package/src/__tests__/APIClient.test.tsx +58 -0
- package/src/__tests__/app.test.tsx +73 -0
- package/src/__tests__/browserChecker.test.ts +61 -0
- package/src/__tests__/getRouteRuntimeVersion.test.ts +68 -0
- package/src/__tests__/nocobase-buildin-plugin-auth.test.tsx +35 -2
- package/src/__tests__/settings-center.test.tsx +270 -6
- package/src/acl/ACLProvider.tsx +2 -0
- package/src/acl/__tests__/ACLProvider.test.tsx +92 -0
- package/src/collection-field-interface/CollectionFieldInterface.ts +1 -0
- package/src/collection-field-interface/CollectionFieldInterfaceManager.ts +1 -0
- package/src/collection-manager/field-validation.ts +1 -1
- package/src/components/README.md +7 -1
- package/src/components/README.zh-CN.md +6 -1
- package/src/components/category-tabs/SortableCategoryTabs.tsx +210 -0
- package/src/components/category-tabs/index.ts +10 -0
- package/src/components/form/JsonTextArea.tsx +4 -0
- package/src/components/form/ScanInput/CodeScanner.tsx +79 -35
- package/src/components/form/ScanInput/__tests__/CodeScanner.test.tsx +101 -0
- package/src/components/form/ScanInput/__tests__/useCodeScanner.test.tsx +284 -11
- package/src/components/form/ScanInput/useCodeScanner.ts +332 -24
- package/src/components/form/TypedVariableInput.tsx +452 -101
- package/src/components/form/__tests__/TypedVariableInput.test.tsx +364 -12
- package/src/components/form/filter/CollectionFilter.tsx +4 -0
- package/src/components/form/filter/CollectionFilterItem.tsx +36 -9
- package/src/components/form/filter/CollectionFilterPanel.tsx +4 -0
- package/src/components/form/filter/__tests__/CollectionFilterItem.test.tsx +55 -0
- package/src/components/form/filter/__tests__/useFilterActionProps.test.tsx +95 -0
- package/src/components/form/filter/index.ts +2 -0
- package/src/components/form/filter/useFilterActionProps.ts +37 -6
- package/src/components/form/table/Table.tsx +81 -6
- package/src/components/form/table/__tests__/Table.columnWidth.test.tsx +433 -0
- package/src/components/index.ts +1 -0
- package/src/flow/FlowPage.tsx +9 -1
- package/src/flow/__tests__/FlowPage.test.tsx +50 -3
- package/src/flow/__tests__/FlowRoute.test.tsx +128 -10
- package/src/flow/__tests__/PluginFlowEngine.test.ts +58 -0
- package/src/flow/actions/__tests__/actionLinkageRules.forkProps.test.ts +314 -0
- package/src/flow/actions/__tests__/dataScopeFormValueClear.test.ts +102 -0
- package/src/flow/actions/__tests__/linkageRules.actionStates.test.ts +33 -0
- package/src/flow/actions/__tests__/linkageRules.subFormSetFieldProps.test.ts +72 -0
- package/src/flow/actions/__tests__/linkageRules.tab.test.ts +171 -0
- package/src/flow/actions/__tests__/linkageRulesRefresh.test.ts +7 -3
- package/src/flow/actions/index.ts +2 -0
- package/src/flow/actions/linkageRules.tsx +144 -26
- package/src/flow/actions/linkageRulesRefresh.tsx +2 -6
- package/src/flow/admin-shell/admin-layout/AdminLayoutComponent.tsx +0 -1
- package/src/flow/admin-shell/admin-layout/AdminLayoutMenuUtils.tsx +78 -59
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutComponent.test.tsx +253 -6
- package/src/flow/admin-shell/admin-layout/__tests__/AdminLayoutMenuModels.test.ts +228 -0
- package/src/flow/common/Markdown/style.ts +4 -0
- package/src/flow/components/BlockItemCard.tsx +2 -2
- package/src/flow/components/FieldAssignExactDatePicker.tsx +25 -11
- package/src/flow/components/FieldAssignValueInput.tsx +72 -584
- package/src/flow/components/FlowRoute.tsx +78 -32
- package/src/flow/components/RunJSValueEditor.tsx +9 -1
- package/src/flow/components/__tests__/FieldAssignValueInput.context.test.tsx +216 -0
- package/src/flow/components/field-value-variable/DateVariableEditor.tsx +181 -0
- package/src/flow/components/field-value-variable/FieldValueVariableInput.tsx +326 -0
- package/src/flow/components/field-value-variable/__tests__/FieldValueVariableInput.test.tsx +380 -0
- package/src/flow/components/field-value-variable/dateValue.ts +223 -0
- package/src/flow/components/field-value-variable/index.ts +12 -0
- package/src/flow/components/filter/FilterGroup.tsx +33 -5
- package/src/flow/components/filter/VariableFilterItem.tsx +170 -13
- package/src/flow/components/filter/__tests__/FilterGroup.test.tsx +45 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.leftMetaTree.test.tsx +9 -0
- package/src/flow/components/filter/__tests__/VariableFilterItem.test.tsx +195 -1
- package/src/flow/components/placeholders/BlockPlaceholder.tsx +70 -23
- package/src/flow/components/placeholders/__tests__/BlockPlaceholder.test.tsx +57 -7
- package/src/flow/index.ts +3 -0
- package/src/flow/internal/registerDeviceTypeContext.ts +39 -0
- package/src/flow/internal/utils/operatorSchemaHelper.ts +3 -2
- package/src/flow/models/actions/UpdateRecordActionModel.tsx +18 -1
- package/src/flow/models/actions/UpdateRecordActionUtils.ts +18 -6
- package/src/flow/models/actions/__tests__/UpdateRecordActionModel.test.ts +76 -4
- package/src/flow/models/base/ActionModelCore.tsx +11 -2
- package/src/flow/models/base/BlockGridModel.tsx +26 -0
- package/src/flow/models/base/CollectionBlockModel.tsx +38 -3
- package/src/flow/models/base/PageModel/PageModel.tsx +387 -53
- package/src/flow/models/base/PageModel/PageModelTabBar.tsx +114 -0
- package/src/flow/models/base/PageModel/PageTabModel.tsx +249 -18
- package/src/flow/models/base/PageModel/__tests__/PageModel.test.ts +790 -10
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.module-isolation.test.tsx +130 -0
- package/src/flow/models/base/PageModel/__tests__/PageModelTabBar.test.tsx +118 -0
- package/src/flow/models/base/PageModel/__tests__/PageTabModel.test.ts +1075 -7
- package/src/flow/models/base/__tests__/ActionModelCore.render.test.tsx +49 -0
- package/src/flow/models/base/__tests__/BlockGridModel.selectSceneActivation.test.ts +124 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.addAppends.test.ts +41 -0
- package/src/flow/models/base/__tests__/CollectionBlockModel.initialBeforeRenderRefresh.test.ts +125 -9
- package/src/flow/models/blocks/assign-form/AssignFormItemModel.tsx +28 -53
- package/src/flow/models/blocks/details/DetailsBlockModel.tsx +8 -3
- package/src/flow/models/blocks/details/__tests__/DetailsBlockModel.initialPaginationChangeRefresh.test.ts +32 -1
- package/src/flow/models/blocks/filter-form/FilterFormBlockModel.tsx +28 -3
- package/src/flow/models/blocks/filter-form/FilterFormGridModel.tsx +36 -5
- package/src/flow/models/blocks/filter-form/FilterFormItemModel.tsx +155 -25
- package/src/flow/models/blocks/filter-form/FilterFormSubmitActionModel.tsx +57 -4
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormGridModel.onModelCreated.test.ts +174 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.defineChildren.test.ts +395 -1
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormItemModel.getFilterValue.test.ts +72 -0
- package/src/flow/models/blocks/filter-form/__tests__/FilterFormSubmitActionModel.lifecycle.test.ts +90 -0
- package/src/flow/models/blocks/filter-form/__tests__/defaultValues.wiring.test.ts +66 -4
- package/src/flow/models/blocks/filter-manager/FilterManager.ts +5 -0
- package/src/flow/models/blocks/filter-manager/__tests__/FilterManager.test.ts +40 -0
- package/src/flow/models/blocks/form/FormBlockModel.tsx +47 -0
- package/src/flow/models/blocks/form/FormGridModel.tsx +4 -0
- package/src/flow/models/blocks/form/QuickEditFormModel.tsx +189 -36
- package/src/flow/models/blocks/form/__tests__/FormBlockModel.test.tsx +8 -2
- package/src/flow/models/blocks/form/__tests__/QuickEditFormModel.quickEdit.test.ts +350 -2
- package/src/flow/models/blocks/form/__tests__/runJsFormSubmit.test.ts +131 -0
- package/src/flow/models/blocks/form/value-runtime/__tests__/runtime.test.ts +435 -0
- package/src/flow/models/blocks/form/value-runtime/rules.ts +67 -14
- package/src/flow/models/blocks/form/value-runtime/runtime.ts +43 -19
- package/src/flow/models/blocks/js-block/JSBlock.tsx +1 -1
- package/src/flow/models/blocks/table/JSColumnModel.tsx +10 -1
- package/src/flow/models/blocks/table/TableActionsColumnModel.tsx +2 -1
- package/src/flow/models/blocks/table/TableBlockModel.tsx +29 -3
- package/src/flow/models/blocks/table/TableColumnModel.tsx +48 -9
- package/src/flow/models/blocks/table/__tests__/JSColumnModel.test.tsx +52 -5
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.filterReset.test.ts +78 -0
- package/src/flow/models/blocks/table/__tests__/TableBlockModel.quickEditRefresh.test.ts +12 -0
- package/src/flow/models/blocks/table/__tests__/TableColumnModel.test.tsx +33 -0
- package/src/flow/models/blocks/table/utils.ts +7 -0
- package/src/flow/models/fields/AssociationFieldModel/CascadeSelectFieldModel.tsx +33 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/PopupSubTableFieldModel.tsx +10 -1
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/__tests__/popupContext.test.ts +120 -0
- package/src/flow/models/fields/AssociationFieldModel/PopupSubTableFieldModel/actions/PopupSubTableEditActionModel.tsx +10 -2
- package/src/flow/models/fields/AssociationFieldModel/RecordPickerFieldModel.tsx +24 -1
- package/src/flow/models/fields/AssociationFieldModel/RecordSelectFieldModel.tsx +9 -136
- package/src/flow/models/fields/AssociationFieldModel/__tests__/RecordPickerFieldModel.itemContext.test.ts +167 -3
- package/src/flow/models/fields/AssociationFieldModel/recordSelectShared.tsx +156 -0
- package/src/flow/models/fields/DateTimeFieldModel/__tests__/DateTimeNoTzFieldModel.dateLimit.test.tsx +149 -0
- package/src/flow/models/fields/DateTimeFieldModel/dateLimit.ts +149 -113
- package/src/flow/models/fields/DisplayNumberFieldModel.tsx +1 -1
- package/src/flow/models/fields/JsonFieldModel.tsx +31 -8
- package/src/flow/models/fields/NumberFieldModel.tsx +1 -1
- package/src/flow/models/fields/VariableFieldFormModel.tsx +3 -3
- package/src/flow/models/fields/__tests__/DisplayNumberFieldModel.test.ts +33 -0
- package/src/flow/models/fields/__tests__/JsonFieldModel.test.ts +82 -0
- package/src/flow/models/fields/__tests__/NumberFieldModel.test.tsx +47 -0
- package/src/flow/models/fields/__tests__/VariableFieldFormModel.test.tsx +51 -0
- package/src/flow/models/fields/mobile-components/MobileLazySelect.tsx +26 -10
- package/src/flow/models/fields/mobile-components/MobileSelect.tsx +51 -14
- package/src/flow/models/fields/mobile-components/__tests__/MobileSelect.test.tsx +139 -13
- package/src/flow/utils/dataScopeFormValueClear.ts +4 -3
- package/src/flow-compat/fieldValidationConstants.ts +1 -1
- package/src/flow-compat/routeTypes.ts +1 -0
- package/src/index.ts +5 -0
- package/src/layout-manager/LayoutContentRoute.tsx +2 -1
- package/src/layout-manager/LayoutRoute.tsx +2 -1
- package/src/layout-manager/__tests__/LayoutRoute.test.tsx +87 -1
- package/src/locale/languageCodes.ts +3 -1
- package/src/nocobase-buildin-plugin/index.tsx +12 -0
- package/src/settings-center/AdminSettingsLayout.tsx +23 -2
- package/src/ui-operation/index.ts +33 -0
- package/src/ui-operation/ui-operation-codec.ts +54 -0
- package/src/utils/getRouteRuntimeVersion.ts +185 -0
- package/src/utils/index.tsx +1 -0
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
AdminLayoutMenuItemModel,
|
|
20
20
|
AdminLayoutModel,
|
|
21
21
|
ADMIN_LAYOUT_MODEL_UID,
|
|
22
|
+
buildMenuTitleWithIcon,
|
|
22
23
|
getAdminLayoutMenuMovePositionOptions,
|
|
23
24
|
normalizeAdminLayoutMenuLegacyVariables,
|
|
24
25
|
openAdminLayoutMenuLink,
|
|
@@ -119,6 +120,233 @@ describe('AdminLayoutModel menu items', () => {
|
|
|
119
120
|
...options,
|
|
120
121
|
});
|
|
121
122
|
|
|
123
|
+
type MenuTitleOptions = {
|
|
124
|
+
title: string;
|
|
125
|
+
collapsed: boolean;
|
|
126
|
+
name?: React.ReactNode;
|
|
127
|
+
routeTitle?: string;
|
|
128
|
+
renderType?: 'item' | 'group';
|
|
129
|
+
tooltip?: string;
|
|
130
|
+
badgeCount?: number;
|
|
131
|
+
badgeIndicatorColor?: string;
|
|
132
|
+
badgeTextColor?: string;
|
|
133
|
+
depth?: number;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const createMenuTitle = (options: MenuTitleOptions) => {
|
|
137
|
+
const {
|
|
138
|
+
title,
|
|
139
|
+
collapsed,
|
|
140
|
+
name = title,
|
|
141
|
+
routeTitle = title,
|
|
142
|
+
renderType = 'item',
|
|
143
|
+
tooltip,
|
|
144
|
+
badgeCount,
|
|
145
|
+
badgeIndicatorColor,
|
|
146
|
+
badgeTextColor,
|
|
147
|
+
depth = 1,
|
|
148
|
+
} = options;
|
|
149
|
+
|
|
150
|
+
return React.createElement(
|
|
151
|
+
FlowEngineProvider,
|
|
152
|
+
{ engine },
|
|
153
|
+
React.createElement(
|
|
154
|
+
MemoryRouter,
|
|
155
|
+
{ initialEntries: ['/admin/current-page'] },
|
|
156
|
+
React.createElement(AdminLayoutMenuItemRenderer, {
|
|
157
|
+
renderType,
|
|
158
|
+
item: {
|
|
159
|
+
name,
|
|
160
|
+
path: '/admin/menu-title',
|
|
161
|
+
_runtimePath: '/apps/demo/v2/admin/menu-title',
|
|
162
|
+
_navigationMode: 'spa',
|
|
163
|
+
_isLegacy: false,
|
|
164
|
+
_depth: depth,
|
|
165
|
+
_route: {
|
|
166
|
+
type: NocoBaseDesktopRouteType.flowPage,
|
|
167
|
+
title: routeTitle,
|
|
168
|
+
tooltip,
|
|
169
|
+
schemaUid: 'menu-title',
|
|
170
|
+
options:
|
|
171
|
+
badgeCount == null
|
|
172
|
+
? {}
|
|
173
|
+
: {
|
|
174
|
+
badge: {
|
|
175
|
+
count: badgeCount,
|
|
176
|
+
styles: badgeIndicatorColor ? { indicator: { color: badgeIndicatorColor } } : undefined,
|
|
177
|
+
textColor: badgeTextColor,
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
dom: React.createElement(
|
|
183
|
+
'span',
|
|
184
|
+
{ className: 'ant-pro-base-menu-inline-item-text' },
|
|
185
|
+
collapsed ? title.slice(0, 1) : title,
|
|
186
|
+
),
|
|
187
|
+
options: { isMobile: false, collapsed },
|
|
188
|
+
}),
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const renderMenuTitle = (options: MenuTitleOptions) => render(createMenuTitle(options));
|
|
194
|
+
|
|
195
|
+
it.each([false, true])(
|
|
196
|
+
'should use a native title without an extra tooltip trigger when collapsed is %s',
|
|
197
|
+
async (collapsed) => {
|
|
198
|
+
vi.useFakeTimers();
|
|
199
|
+
const title = 'A complete menu title that may be truncated';
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const { container } = renderMenuTitle({ title, collapsed });
|
|
203
|
+
const link = screen.getByRole('link', { name: title });
|
|
204
|
+
const menuItem = link.closest<HTMLElement>('[role="none"]');
|
|
205
|
+
|
|
206
|
+
expect(link).toHaveAttribute('title', title);
|
|
207
|
+
expect(link.parentElement).toBe(menuItem);
|
|
208
|
+
expect(menuItem).toHaveStyle({ width: '100%', minWidth: 0 });
|
|
209
|
+
expect(link).toHaveStyle({ display: 'block', width: '100%', minWidth: 0, overflow: 'hidden' });
|
|
210
|
+
expect(container.querySelector('.ant-tooltip')).not.toBeInTheDocument();
|
|
211
|
+
|
|
212
|
+
await act(async () => {
|
|
213
|
+
fireEvent.mouseEnter(link);
|
|
214
|
+
await vi.advanceTimersByTimeAsync(500);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
|
218
|
+
} finally {
|
|
219
|
+
vi.clearAllTimers();
|
|
220
|
+
vi.useRealTimers();
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
it('should use the translated native title for an icon-wrapped nested menu name', () => {
|
|
226
|
+
const title = 'A translated nested menu title';
|
|
227
|
+
const { name } = buildMenuTitleWithIcon(
|
|
228
|
+
{ title: 'menu.nested.title', icon: 'AppstoreOutlined' },
|
|
229
|
+
() => title,
|
|
230
|
+
true,
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
renderMenuTitle({ title, name, collapsed: true, depth: 2 });
|
|
234
|
+
|
|
235
|
+
expect(screen.getByRole('link', { name: title })).toHaveAttribute('title', title);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should use the translated native title for an icon-wrapped nested group name', () => {
|
|
239
|
+
const title = 'A translated nested group title';
|
|
240
|
+
const { name } = buildMenuTitleWithIcon(
|
|
241
|
+
{ title: 'menu.nested.group', icon: 'AppstoreOutlined' },
|
|
242
|
+
() => title,
|
|
243
|
+
true,
|
|
244
|
+
);
|
|
245
|
+
const { container } = renderMenuTitle({
|
|
246
|
+
title,
|
|
247
|
+
name,
|
|
248
|
+
routeTitle: 'menu.nested.group',
|
|
249
|
+
renderType: 'group',
|
|
250
|
+
collapsed: true,
|
|
251
|
+
depth: 2,
|
|
252
|
+
});
|
|
253
|
+
const group = container.querySelector('[role="none"]');
|
|
254
|
+
|
|
255
|
+
expect(group).toHaveAttribute('title', title);
|
|
256
|
+
expect(group).toHaveAttribute('aria-label', title);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should preserve a numeric group name as the native title', () => {
|
|
260
|
+
const { container } = renderMenuTitle({
|
|
261
|
+
title: '0',
|
|
262
|
+
name: 0,
|
|
263
|
+
routeTitle: 'menu.numeric.group',
|
|
264
|
+
renderType: 'group',
|
|
265
|
+
collapsed: true,
|
|
266
|
+
});
|
|
267
|
+
const group = container.querySelector('[role="none"]');
|
|
268
|
+
|
|
269
|
+
expect(group).toHaveAttribute('title', '0');
|
|
270
|
+
expect(group).toHaveAttribute('aria-label', '0');
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it.each(['item', 'group'] as const)(
|
|
274
|
+
'should let an explicit route tooltip own hover behavior for a sider %s',
|
|
275
|
+
(renderType) => {
|
|
276
|
+
const title = 'A menu title with an explicit description';
|
|
277
|
+
const { container } = renderMenuTitle({
|
|
278
|
+
title,
|
|
279
|
+
renderType,
|
|
280
|
+
collapsed: false,
|
|
281
|
+
tooltip: 'An explicitly configured menu description',
|
|
282
|
+
});
|
|
283
|
+
const titleTarget =
|
|
284
|
+
renderType === 'item' ? screen.getByRole('link', { name: title }) : container.querySelector('[role="none"]');
|
|
285
|
+
|
|
286
|
+
expect(titleTarget).not.toHaveAttribute('title');
|
|
287
|
+
expect(screen.getByRole('img', { name: 'question-circle' })).toBeInTheDocument();
|
|
288
|
+
},
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
it('should keep the same menu link when the sider expands', async () => {
|
|
292
|
+
vi.useFakeTimers();
|
|
293
|
+
const title = 'A title that fits after expanding';
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
const { rerender } = renderMenuTitle({ title, collapsed: true });
|
|
297
|
+
const link = screen.getByRole('link', { name: title });
|
|
298
|
+
|
|
299
|
+
await act(async () => {
|
|
300
|
+
rerender(createMenuTitle({ title, collapsed: false }));
|
|
301
|
+
await vi.runOnlyPendingTimersAsync();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
expect(screen.getByRole('link', { name: title })).toBe(link);
|
|
305
|
+
expect(link).toHaveAttribute('title', title);
|
|
306
|
+
} finally {
|
|
307
|
+
vi.clearAllTimers();
|
|
308
|
+
vi.useRealTimers();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it.each([true, false])(
|
|
313
|
+
'should render one badge indicator for a nested menu title when collapsed is %s',
|
|
314
|
+
(collapsed) => {
|
|
315
|
+
const title = 'A nested menu title with a badge';
|
|
316
|
+
const { container } = renderMenuTitle({ title, collapsed, badgeCount: 7 });
|
|
317
|
+
|
|
318
|
+
expect(container.querySelectorAll('.ant-badge-count')).toHaveLength(1);
|
|
319
|
+
},
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
it('should render one badge indicator for a top-level collapsed menu title', () => {
|
|
323
|
+
const title = 'A top-level collapsed menu title with a badge';
|
|
324
|
+
const { container } = renderMenuTitle({
|
|
325
|
+
title,
|
|
326
|
+
collapsed: true,
|
|
327
|
+
badgeCount: 7,
|
|
328
|
+
badgeTextColor: 'rgb(1, 2, 3)',
|
|
329
|
+
depth: 0,
|
|
330
|
+
});
|
|
331
|
+
const indicator = container.querySelector<HTMLElement>('.ant-badge-count');
|
|
332
|
+
|
|
333
|
+
expect(container.querySelectorAll('.ant-badge-count')).toHaveLength(1);
|
|
334
|
+
expect(indicator).toHaveStyle({ color: 'rgb(1, 2, 3)' });
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('should preserve the Ant Design indicator color when collapsed badge textColor is unset', () => {
|
|
338
|
+
const title = 'A top-level collapsed menu title with an indicator color';
|
|
339
|
+
const { container } = renderMenuTitle({
|
|
340
|
+
title,
|
|
341
|
+
collapsed: true,
|
|
342
|
+
badgeCount: 7,
|
|
343
|
+
badgeIndicatorColor: 'rgb(4, 5, 6)',
|
|
344
|
+
depth: 0,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
expect(container.querySelector('.ant-badge-count')).toHaveStyle({ color: 'rgb(4, 5, 6)' });
|
|
348
|
+
});
|
|
349
|
+
|
|
122
350
|
it('should normalize legacy variables only inside template expressions', () => {
|
|
123
351
|
expect(normalizeAdminLayoutMenuLegacyVariables('https://a.com?id={{ $user.id }}')).toBe(
|
|
124
352
|
'https://a.com?id={{ ctx.user.id }}',
|
|
@@ -26,6 +26,10 @@ export default function useStyle() {
|
|
|
26
26
|
() => ({
|
|
27
27
|
[`.${COMPONENT_CLS}`]: {
|
|
28
28
|
'.vditor-reset': { fontSize: `${token.fontSize}px !important`, color: 'unset' },
|
|
29
|
+
'.vditor-reset h2': {
|
|
30
|
+
borderBottom: 'none !important',
|
|
31
|
+
boxShadow: 'none !important',
|
|
32
|
+
},
|
|
29
33
|
'.vditor': {
|
|
30
34
|
borderRadius: 8,
|
|
31
35
|
},
|
|
@@ -150,7 +150,7 @@ export const BlockItemCard = React.forwardRef(
|
|
|
150
150
|
) => {
|
|
151
151
|
const { t } = useTranslation();
|
|
152
152
|
const { token } = theme.useToken();
|
|
153
|
-
const { title: blockTitle, description, children, className, heightMode, ...rest } = props;
|
|
153
|
+
const { title: blockTitle, description, children, className, heightMode, style, ...rest } = props;
|
|
154
154
|
const cardRef = useRef<HTMLDivElement | null>(null);
|
|
155
155
|
const setCardRef = useCallback(
|
|
156
156
|
(node: HTMLDivElement | null) => {
|
|
@@ -185,7 +185,7 @@ export const BlockItemCard = React.forwardRef(
|
|
|
185
185
|
<Card
|
|
186
186
|
ref={setCardRef as any}
|
|
187
187
|
title={title}
|
|
188
|
-
style={{ display: 'flex', flexDirection: 'column', height: height }}
|
|
188
|
+
style={{ display: 'flex', flexDirection: 'column', ...style, height: height ?? style?.height }}
|
|
189
189
|
styles={{
|
|
190
190
|
body: { flex: 1, display: 'flex', flexDirection: 'column', overflow: 'auto' },
|
|
191
191
|
header: {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import React, { useMemo, useState } from 'react';
|
|
10
|
+
import React, { useCallback, useMemo, useState } from 'react';
|
|
11
11
|
import { DatePicker, Select, Space } from 'antd';
|
|
12
12
|
import { inferPickerType } from '../../flow-compat';
|
|
13
13
|
import { dayjs, getDateTimeFormat, getPickerFormat } from '@nocobase/utils/client';
|
|
@@ -29,6 +29,7 @@ export interface FieldAssignExactDatePickerProps {
|
|
|
29
29
|
isRange?: boolean;
|
|
30
30
|
onChange?: (value: ExactDatePickerValue) => void;
|
|
31
31
|
style?: React.CSSProperties;
|
|
32
|
+
disabled?: boolean;
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
function getRawSingleValue(value: unknown, isRange: boolean): unknown {
|
|
@@ -114,7 +115,7 @@ function parseRangeValue(value: unknown, format: string): [dayjs.Dayjs, dayjs.Da
|
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProps> = (props) => {
|
|
117
|
-
const { picker = 'date', format, showTime, timeFormat, value, isRange = false, onChange, style } = props;
|
|
118
|
+
const { picker = 'date', format, showTime, timeFormat, value, isRange = false, onChange, style, disabled } = props;
|
|
118
119
|
const flowCtx = useFlowContext();
|
|
119
120
|
const t = flowCtx.model.translate.bind(flowCtx.model);
|
|
120
121
|
|
|
@@ -124,17 +125,17 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
124
125
|
return inferPickerFromRawValue(rawSingleValue, picker);
|
|
125
126
|
});
|
|
126
127
|
|
|
127
|
-
const getResolvedFormat = (
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
() => getResolvedFormat(targetPicker),
|
|
135
|
-
[targetPicker, format, picker, showTime, timeFormat],
|
|
128
|
+
const getResolvedFormat = useCallback(
|
|
129
|
+
(nextPicker: ExactDatePickerMode) => {
|
|
130
|
+
const baseFormat = nextPicker === picker && format ? format : getPickerFormat(nextPicker);
|
|
131
|
+
const dateFormat = nextPicker === 'date' ? stripTimeFromFormat(baseFormat) : baseFormat;
|
|
132
|
+
return getDateTimeFormat(nextPicker, dateFormat, showTime, timeFormat);
|
|
133
|
+
},
|
|
134
|
+
[format, picker, showTime, timeFormat],
|
|
136
135
|
);
|
|
137
136
|
|
|
137
|
+
const resolvedFormat = useMemo(() => getResolvedFormat(targetPicker), [getResolvedFormat, targetPicker]);
|
|
138
|
+
|
|
138
139
|
const singleValue = useMemo(() => {
|
|
139
140
|
if (isRange) return null;
|
|
140
141
|
return parseDateFromRawValue(value, resolvedFormat);
|
|
@@ -156,6 +157,10 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
156
157
|
);
|
|
157
158
|
|
|
158
159
|
const handlePickerTypeChange = (nextPicker: ExactDatePickerMode) => {
|
|
160
|
+
if (disabled) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
159
164
|
setTargetPicker(nextPicker);
|
|
160
165
|
|
|
161
166
|
if (!onChange) {
|
|
@@ -182,7 +187,11 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
182
187
|
inputReadOnly: flowCtx.isMobileLayout,
|
|
183
188
|
showTime: showTime ? { defaultValue: dayjs('00:00:00', 'HH:mm:ss') } : false,
|
|
184
189
|
value: singleValue,
|
|
190
|
+
disabled,
|
|
185
191
|
onChange: (nextDate: dayjs.Dayjs | null) => {
|
|
192
|
+
if (disabled) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
186
195
|
if (nextDate && dayjs.isDayjs(nextDate)) {
|
|
187
196
|
onChange?.(nextDate);
|
|
188
197
|
return;
|
|
@@ -200,7 +209,11 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
200
209
|
inputReadOnly: flowCtx.isMobileLayout,
|
|
201
210
|
showTime: showTime ? { defaultValue: [dayjs('00:00:00', 'HH:mm:ss'), dayjs('23:59:59', 'HH:mm:ss')] } : false,
|
|
202
211
|
value: rangeValue,
|
|
212
|
+
disabled,
|
|
203
213
|
onChange: (nextDates: [dayjs.Dayjs | null, dayjs.Dayjs | null] | null) => {
|
|
214
|
+
if (disabled) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
204
217
|
if (Array.isArray(nextDates) && nextDates[0] && nextDates[1]) {
|
|
205
218
|
onChange?.([nextDates[0], nextDates[1]]);
|
|
206
219
|
return;
|
|
@@ -218,6 +231,7 @@ export const FieldAssignExactDatePicker: React.FC<FieldAssignExactDatePickerProp
|
|
|
218
231
|
value={targetPicker}
|
|
219
232
|
options={pickerOptions}
|
|
220
233
|
onChange={handlePickerTypeChange}
|
|
234
|
+
disabled={disabled}
|
|
221
235
|
/>
|
|
222
236
|
{isRange ? <DatePicker.RangePicker {...rangePickerProps} /> : <DatePicker {...singlePickerProps} />}
|
|
223
237
|
</Space.Compact>
|