@headless-adminapp/fluent 1.1.4 → 1.1.7
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/DataGrid/TableCell/TableCellChoice.js +2 -30
- package/DataGrid/useTableColumns.js +41 -2
- package/PageEntityForm/PageEntityForm.js +8 -0
- package/PageEntityForm/SectionContainer.d.ts +2 -2
- package/PageEntityForm/SectionContainer.js +18 -4
- package/PageEntityForm/StandardControl.js +7 -2
- package/components/ChoiceBadge.d.ts +9 -0
- package/components/ChoiceBadge.js +29 -0
- package/components/LoginForm.d.ts +8 -0
- package/components/LoginForm.js +4 -4
- package/components/PageLogin.d.ts +5 -0
- package/components/PageLogin.js +2 -1
- package/form/controls/RegardingControl.d.ts +25 -0
- package/form/controls/RegardingControl.js +202 -0
- package/form/controls/SelectControl.d.ts +1 -1
- package/form/controls/SelectControl.js +1 -3
- package/form/controls/TextAreaControl.d.ts +3 -1
- package/form/controls/TextAreaControl.js +33 -8
- package/form/controls/useLookupData.d.ts +12 -2
- package/form/controls/useLookupData.js +71 -20
- package/form/layout/FormSection/FormSection.js +9 -2
- package/form/layout/FormTab/FormTab.js +1 -0
- package/form/layout/FormTab/FormTabColumn.js +1 -0
- package/package.json +2 -2
- package/App/NavigationContainer.d.ts +0 -10
- package/App/NavigationContainer.js +0 -68
- package/App/utils.d.ts +0 -14
- package/App/utils.js +0 -26
- package/Insights/CommandBarContainer.d.ts +0 -1
- package/Insights/CommandBarContainer.js +0 -18
- package/Insights/FilterBarContainer.d.ts +0 -1
- package/Insights/FilterBarContainer.js +0 -99
- package/Insights/hooks/useQueriesData.d.ts +0 -7
- package/Insights/hooks/useQueriesData.js +0 -89
- package/Insights/hooks/useWidgetDetail.d.ts +0 -10
- package/Insights/hooks/useWidgetDetail.js +0 -39
- package/PageCalendar/baseEventAttributes.d.ts +0 -35
- package/PageCalendar/baseEventAttributes.js +0 -38
- package/PageCalendar/context.d.ts +0 -20
- package/PageCalendar/context.js +0 -5
- package/PageCalendar/hooks/index.d.ts +0 -1
- package/PageCalendar/hooks/index.js +0 -17
- package/PageCalendar/hooks/useConfig.d.ts +0 -3
- package/PageCalendar/hooks/useConfig.js +0 -8
- package/PageInsights/PageInsights.d.ts +0 -7
- package/PageInsights/PageInsights.js +0 -31
- package/PageInsights/index.d.ts +0 -1
- package/PageInsights/index.js +0 -5
|
@@ -2,33 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TableCellChoice = TableCellChoice;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
-
const
|
|
6
|
-
const color_1 = require("@headless-adminapp/app/utils/color");
|
|
7
|
-
const react_1 = require("react");
|
|
5
|
+
const ChoiceBadge_1 = require("../../components/ChoiceBadge");
|
|
8
6
|
const TableCellBase_1 = require("./TableCellBase");
|
|
9
7
|
function TableCellChoice(props) {
|
|
10
|
-
const bgColor = (0, react_1.useMemo)(() => {
|
|
11
|
-
if (!props.value || !props.attribute.options) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
return props.attribute.options.find((option) => option.value === props.value)?.color;
|
|
15
|
-
}, [props.attribute.options, props.value]);
|
|
16
|
-
const color = (0, react_1.useMemo)(() => {
|
|
17
|
-
if (!bgColor) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
return (0, color_1.isColorDark)(bgColor) ? '#FFFFFF' : '#000000';
|
|
21
|
-
}, [bgColor]);
|
|
22
|
-
if (!props.formattedValue) {
|
|
23
|
-
return ((0, jsx_runtime_1.jsx)(TableCellBase_1.TableCellBase, { style: {
|
|
24
|
-
textOverflow: 'ellipsis',
|
|
25
|
-
overflow: 'hidden',
|
|
26
|
-
whiteSpace: 'nowrap',
|
|
27
|
-
width: props.width,
|
|
28
|
-
minWidth: props.width,
|
|
29
|
-
maxWidth: props.width,
|
|
30
|
-
} }));
|
|
31
|
-
}
|
|
32
8
|
return ((0, jsx_runtime_1.jsx)(TableCellBase_1.TableCellBase, { style: {
|
|
33
9
|
textOverflow: 'ellipsis',
|
|
34
10
|
overflow: 'hidden',
|
|
@@ -36,9 +12,5 @@ function TableCellChoice(props) {
|
|
|
36
12
|
width: props.width,
|
|
37
13
|
minWidth: props.width,
|
|
38
14
|
maxWidth: props.width,
|
|
39
|
-
}, children: (0, jsx_runtime_1.jsx)(
|
|
40
|
-
backgroundColor: bgColor ?? react_components_1.tokens.colorNeutralBackground3,
|
|
41
|
-
color: color ?? react_components_1.tokens.colorNeutralForeground2,
|
|
42
|
-
fontWeight: react_components_1.tokens.fontWeightRegular,
|
|
43
|
-
}, children: props.formattedValue }) }));
|
|
15
|
+
}, children: (0, jsx_runtime_1.jsx)(ChoiceBadge_1.ChoiceBadge, { attribute: props.attribute, formattedValue: props.formattedValue, value: props.value }) }));
|
|
44
16
|
}
|
|
@@ -320,6 +320,19 @@ function renderCellContent({ info, column, schema, schemaStore, locale, routeRes
|
|
|
320
320
|
formattedValue,
|
|
321
321
|
});
|
|
322
322
|
}
|
|
323
|
+
case 'regarding': {
|
|
324
|
+
return renderRegardingAttribute({
|
|
325
|
+
info,
|
|
326
|
+
column,
|
|
327
|
+
schemaStore,
|
|
328
|
+
routeResolver,
|
|
329
|
+
recordSetSetter,
|
|
330
|
+
router,
|
|
331
|
+
value,
|
|
332
|
+
attribute,
|
|
333
|
+
formattedValue,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
323
336
|
case 'attachment': {
|
|
324
337
|
const url = value?.url;
|
|
325
338
|
if (!url) {
|
|
@@ -346,7 +359,7 @@ function renderCellContent({ info, column, schema, schemaStore, locale, routeRes
|
|
|
346
359
|
}
|
|
347
360
|
function renderPrimaryAttribute({ info, column, schema, routeResolver, openRecord, value, }) {
|
|
348
361
|
const path = routeResolver({
|
|
349
|
-
logicalName:
|
|
362
|
+
logicalName: info.row.original.$entity,
|
|
350
363
|
type: app_1.PageType.EntityForm,
|
|
351
364
|
id: info.row.original[schema.idAttribute],
|
|
352
365
|
});
|
|
@@ -355,7 +368,7 @@ function renderPrimaryAttribute({ info, column, schema, routeResolver, openRecor
|
|
|
355
368
|
schema,
|
|
356
369
|
value,
|
|
357
370
|
}), value] }), width: info.column.getSize(), href: path, onClick: () => {
|
|
358
|
-
openRecord(info.row.original[schema.idAttribute]);
|
|
371
|
+
openRecord(info.row.original[schema.idAttribute], info.row.original.$entity);
|
|
359
372
|
} }, column.id));
|
|
360
373
|
}
|
|
361
374
|
function renderPrimaryAttributeAvatar({ info, schema, value, }) {
|
|
@@ -396,3 +409,29 @@ function renderLookupAttribute({ value, info, column, schemaStore, routeResolver
|
|
|
396
409
|
router.push(path);
|
|
397
410
|
} }, column.id));
|
|
398
411
|
}
|
|
412
|
+
function renderRegardingAttribute({ value, info, column, schemaStore, routeResolver, recordSetSetter, router, formattedValue, }) {
|
|
413
|
+
if (!value) {
|
|
414
|
+
return ((0, jsx_runtime_1.jsx)(TableCell_1.TableCellText, { value: "", width: info.column.getSize() }, column.id));
|
|
415
|
+
}
|
|
416
|
+
const hasSchema = schemaStore.hasSchema(value.logicalName);
|
|
417
|
+
if (!hasSchema) {
|
|
418
|
+
return ((0, jsx_runtime_1.jsx)(TableCell_1.TableCellText, { value: "", width: info.column.getSize() }, column.id));
|
|
419
|
+
}
|
|
420
|
+
const logicalName = value.logicalName;
|
|
421
|
+
const lookupSchema = schemaStore.getSchema(logicalName);
|
|
422
|
+
const path = routeResolver({
|
|
423
|
+
logicalName,
|
|
424
|
+
type: app_1.PageType.EntityForm,
|
|
425
|
+
id: value.id,
|
|
426
|
+
});
|
|
427
|
+
return ((0, jsx_runtime_1.jsx)(TableCellLink_1.TableCellLink, { value: (0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [!!lookupSchema.avatarAttribute && ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
|
|
428
|
+
width: 24,
|
|
429
|
+
height: 24,
|
|
430
|
+
fontSize: react_components_1.tokens.fontSizeBase100,
|
|
431
|
+
}, name: formattedValue, color: (0, avatar_1.getAvatarColor)(formattedValue), image: {
|
|
432
|
+
src: value.avatar,
|
|
433
|
+
} })), formattedValue] }), width: info.column.getSize(), href: path, onClick: () => {
|
|
434
|
+
recordSetSetter('', []);
|
|
435
|
+
router.push(path);
|
|
436
|
+
} }, column.id));
|
|
437
|
+
}
|
|
@@ -19,6 +19,14 @@ const PageEntityForm = ({ logicalName, formId, recordId, }) => {
|
|
|
19
19
|
return ((0, jsx_runtime_1.jsx)(PageBroken_1.PageBroken, { Icon: icons_1.Icons.Error, title: result.title, message: result.message }));
|
|
20
20
|
}
|
|
21
21
|
const { schema, form, commands } = result;
|
|
22
|
+
if (!recordId) {
|
|
23
|
+
if (schema.virtual) {
|
|
24
|
+
return ((0, jsx_runtime_1.jsx)(PageBroken_1.PageBroken, { Icon: icons_1.Icons.Error, title: "Virtual Schema", message: "This schema is virtual and cannot be used in this context." }));
|
|
25
|
+
}
|
|
26
|
+
if (schema.restrictions?.disableCreate) {
|
|
27
|
+
return ((0, jsx_runtime_1.jsx)(PageBroken_1.PageBroken, { Icon: icons_1.Icons.Error, title: "Creating is disabled", message: "Creating records is disabled for this entity." }));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
22
30
|
return ((0, jsx_runtime_1.jsx)(PageEntityFormProvider_1.PageEntityFormProvider, { schema: schema, form: form, recordId: recordId, commands: commands, children: (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
23
31
|
display: 'flex',
|
|
24
32
|
flex: 1,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Section } from '@headless-adminapp/core/experience/form';
|
|
2
2
|
import type { SchemaAttributes } from '@headless-adminapp/core/schema';
|
|
3
|
-
export declare function SectionContainer<S extends SchemaAttributes = SchemaAttributes>({ section }: {
|
|
3
|
+
export declare function SectionContainer<S extends SchemaAttributes = SchemaAttributes>({ section }: Readonly<{
|
|
4
4
|
section: Section<S>;
|
|
5
5
|
readOnly: boolean;
|
|
6
|
-
}): import("react/jsx-runtime").JSX.Element | null;
|
|
6
|
+
}>): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -39,7 +39,7 @@ function SectionContainer({ section }) {
|
|
|
39
39
|
if (hiddenSections[section.name] || visibleControls.length === 0) {
|
|
40
40
|
return null;
|
|
41
41
|
}
|
|
42
|
-
return ((0, jsx_runtime_1.jsx)(layout_1.FormSection, { title: (0, utils_2.localizedLabel)(language, section), columnCount: section.columnCount, labelPosition: section.labelPosition, noPadding: section.noPadding, hideLabel: section.hideLabel, children: visibleControls.map((control, index) => {
|
|
42
|
+
return ((0, jsx_runtime_1.jsx)(layout_1.FormSection, { title: (0, utils_2.localizedLabel)(language, section), columnCount: section.columnCount, labelPosition: section.labelPosition, noPadding: section.noPadding, hideLabel: section.hideLabel, fullHeight: section.fullHeight, children: visibleControls.map((control, index) => {
|
|
43
43
|
switch (control.type) {
|
|
44
44
|
case 'standard': {
|
|
45
45
|
const attribute = schema.attributes[control.attributeName];
|
|
@@ -94,7 +94,7 @@ function SectionContainer({ section }) {
|
|
|
94
94
|
recordId,
|
|
95
95
|
attributeName: control.attributeName,
|
|
96
96
|
logicalName: schema.logicalName,
|
|
97
|
-
} }) }));
|
|
97
|
+
}, autoHeight: control.autoHeight, maxHeight: control.maxHeight }) }));
|
|
98
98
|
} }, control.attributeName) }, control.attributeName));
|
|
99
99
|
}
|
|
100
100
|
case 'editablegrid': {
|
|
@@ -120,12 +120,26 @@ function SectionContainer({ section }) {
|
|
|
120
120
|
refAttributeName: control.associatedAttribute,
|
|
121
121
|
} }, index));
|
|
122
122
|
}
|
|
123
|
+
case 'component': {
|
|
124
|
+
const Component = control.component === 'string'
|
|
125
|
+
? componentStore_1.componentStore.getComponent(control.component)
|
|
126
|
+
: control.component;
|
|
127
|
+
if (!Component) {
|
|
128
|
+
console.warn(`Component ${control.component} not found for control ${control.key}`);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
132
|
+
gridColumn: control.span
|
|
133
|
+
? `var(--section-item-span-${control.span ?? 1})`
|
|
134
|
+
: undefined,
|
|
135
|
+
display: 'flex',
|
|
136
|
+
}, children: (0, jsx_runtime_1.jsx)(Component, { ...control.componentProps }) }, index));
|
|
137
|
+
}
|
|
123
138
|
case 'spacer':
|
|
124
139
|
return ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
125
140
|
gridColumn: control.span
|
|
126
|
-
? `var(--section-item-span-${control.span})`
|
|
141
|
+
? `var(--section-item-span-${control.span ?? 1})`
|
|
127
142
|
: undefined,
|
|
128
|
-
display: `var(--section-item-spacer-${control.span ?? 1})`,
|
|
129
143
|
} }, index));
|
|
130
144
|
default:
|
|
131
145
|
return null;
|
|
@@ -22,6 +22,7 @@ const IntegerControl_1 = require("../form/controls/IntegerControl");
|
|
|
22
22
|
const LookupControl_1 = require("../form/controls/LookupControl");
|
|
23
23
|
const MultiSelectControl_1 = __importDefault(require("../form/controls/MultiSelectControl"));
|
|
24
24
|
const MultiSelectLookupControl_1 = require("../form/controls/MultiSelectLookupControl");
|
|
25
|
+
const RegardingControl_1 = require("../form/controls/RegardingControl");
|
|
25
26
|
const RichTextControl_1 = require("../form/controls/RichTextControl");
|
|
26
27
|
const SelectControl_1 = __importDefault(require("../form/controls/SelectControl"));
|
|
27
28
|
const SwitchControl_1 = require("../form/controls/SwitchControl");
|
|
@@ -43,7 +44,7 @@ const StandardControl = (props) => {
|
|
|
43
44
|
// hideLabel,
|
|
44
45
|
hidePlaceholder, readOnly,
|
|
45
46
|
// quickViewControl,
|
|
46
|
-
allowNavigation, allowNewRecord, } = props;
|
|
47
|
+
allowNavigation, allowNewRecord, autoHeight, maxHeight, } = props;
|
|
47
48
|
const isDisabled = readOnly;
|
|
48
49
|
// const label = hideLabel ? undefined : _label ?? attribute.label;
|
|
49
50
|
const placeholder = hidePlaceholder
|
|
@@ -86,7 +87,7 @@ const StandardControl = (props) => {
|
|
|
86
87
|
}
|
|
87
88
|
case 'textarea': {
|
|
88
89
|
const Control = componentStore_1.componentStore.getComponent('Form.TextAreaControl') ?? TextAreaControl_1.TextAreaControl;
|
|
89
|
-
return (0, jsx_runtime_1.jsx)(Control, { ...controlProps });
|
|
90
|
+
return ((0, jsx_runtime_1.jsx)(Control, { ...controlProps, autoHeight: autoHeight, maxHeight: maxHeight }));
|
|
90
91
|
}
|
|
91
92
|
case 'richtext': {
|
|
92
93
|
const Control = componentStore_1.componentStore.getComponent('Form.RichTextControl') ?? RichTextControl_1.RichTextControl;
|
|
@@ -166,6 +167,10 @@ const StandardControl = (props) => {
|
|
|
166
167
|
const Control = componentStore_1.componentStore.getComponent('Form.MultiSelectLookupControl') ?? MultiSelectLookupControl_1.MultiSelectLookupControl;
|
|
167
168
|
return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, placeholder: placeholder, disabled: isDisabled, dataService: dataService, schema: schemaStore.getSchema(attribute.entity), experienceStore: experienceStore, allowNavigation: allowNavigation, allowNewRecord: allowNewRecord }));
|
|
168
169
|
}
|
|
170
|
+
case 'regarding': {
|
|
171
|
+
const Control = componentStore_1.componentStore.getComponent('Form.RegardingControl') ?? RegardingControl_1.RegardingControl;
|
|
172
|
+
return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, placeholder: placeholder, disabled: isDisabled, dataService: dataService, entities: attribute.entities, schemaStore: schemaStore, experienceStore: experienceStore, allowNavigation: allowNavigation, allowNewRecord: allowNewRecord }));
|
|
173
|
+
}
|
|
169
174
|
case 'boolean': {
|
|
170
175
|
const Control = componentStore_1.componentStore.getComponent('Form.SwitchControl') ?? SwitchControl_1.SwitchControl;
|
|
171
176
|
return ((0, jsx_runtime_1.jsx)(Control, { name: name, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, readOnly: readOnly }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ChoiceAttribute } from '@headless-adminapp/core/attributes';
|
|
2
|
+
interface ChoiceBadgeProps {
|
|
3
|
+
value: unknown;
|
|
4
|
+
attribute: ChoiceAttribute<string | number>;
|
|
5
|
+
formattedValue: string | null;
|
|
6
|
+
size?: 'small' | 'medium';
|
|
7
|
+
}
|
|
8
|
+
export declare function ChoiceBadge(props: Readonly<ChoiceBadgeProps>): import("react/jsx-runtime").JSX.Element | null;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChoiceBadge = ChoiceBadge;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_components_1 = require("@fluentui/react-components");
|
|
6
|
+
const color_1 = require("@headless-adminapp/app/utils/color");
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
function ChoiceBadge(props) {
|
|
9
|
+
const bgColor = (0, react_1.useMemo)(() => {
|
|
10
|
+
if (!props.value || !props.attribute.options) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
return props.attribute.options.find((option) => option.value === props.value)?.color;
|
|
14
|
+
}, [props.attribute.options, props.value]);
|
|
15
|
+
const color = (0, react_1.useMemo)(() => {
|
|
16
|
+
if (!bgColor) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
return (0, color_1.isColorDark)(bgColor) ? '#FFFFFF' : '#000000';
|
|
20
|
+
}, [bgColor]);
|
|
21
|
+
if (!props.formattedValue) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return ((0, jsx_runtime_1.jsx)(react_components_1.Badge, { style: {
|
|
25
|
+
backgroundColor: bgColor ?? react_components_1.tokens.colorNeutralBackground3,
|
|
26
|
+
color: color ?? react_components_1.tokens.colorNeutralForeground2,
|
|
27
|
+
fontWeight: react_components_1.tokens.fontWeightRegular,
|
|
28
|
+
}, size: props.size, children: props.formattedValue }));
|
|
29
|
+
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
+
export interface LoginFormData {
|
|
2
|
+
username: string;
|
|
3
|
+
password: string;
|
|
4
|
+
}
|
|
1
5
|
interface LoginFormProps {
|
|
2
6
|
logoImageUrl?: string;
|
|
3
7
|
onLogin: (username: string, password: string) => Promise<void>;
|
|
8
|
+
beforeLoginContent?: React.ReactNode;
|
|
9
|
+
afterLoginContent?: React.ReactNode;
|
|
10
|
+
subtitle?: string;
|
|
11
|
+
defaultValues?: LoginFormData;
|
|
4
12
|
}
|
|
5
13
|
export declare function LoginForm(props: LoginFormProps): import("react/jsx-runtime").JSX.Element;
|
|
6
14
|
export {};
|
package/components/LoginForm.js
CHANGED
|
@@ -44,7 +44,7 @@ const initialValues = {
|
|
|
44
44
|
};
|
|
45
45
|
function LoginForm(props) {
|
|
46
46
|
const form = (0, react_hook_form_1.useForm)({
|
|
47
|
-
defaultValues: initialValues,
|
|
47
|
+
defaultValues: props.defaultValues ?? initialValues,
|
|
48
48
|
resolver: (0, yup_1.yupResolver)(validationSchema),
|
|
49
49
|
});
|
|
50
50
|
const handleOnSubmit = async (values) => {
|
|
@@ -72,14 +72,14 @@ function LoginForm(props) {
|
|
|
72
72
|
width: 80,
|
|
73
73
|
height: 80,
|
|
74
74
|
aspectRatio: 'auto 80 / 80',
|
|
75
|
-
}, alt: "logo" })) }), (0, jsx_runtime_1.jsx)(react_components_1.Subtitle1, { children: "Log in to your account" }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
75
|
+
}, alt: "logo" })) }), (0, jsx_runtime_1.jsx)(react_components_1.Subtitle1, { children: "Log in to your account" }), props.subtitle && (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: props.subtitle }), (0, jsx_runtime_1.jsxs)("div", { style: {
|
|
76
76
|
display: 'flex',
|
|
77
77
|
flexDirection: 'column',
|
|
78
78
|
alignItems: 'stretch',
|
|
79
79
|
justifyContent: 'flex-start',
|
|
80
80
|
gap: 16,
|
|
81
|
-
}, children: [(0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "username", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Username", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(TextControl_1.TextControl, { placeholder: "Username", appearance: "outline", name: field.name, value: field.value, onChange: field.onChange, onBlur: field.onBlur, autoCapitalize: "none", autoCorrect: "off", error: !!fieldState.error?.message && formState.isSubmitted }) })) }), (0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "password", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Password", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(PasswordControl_1.PasswordControl, { placeholder: "Password", name: field.name, appearance: "outline", error: !!fieldState.error?.message && formState.isSubmitted, value: field.value, onChange: field.onChange, onBlur: field.onBlur }) })) }), !!form.formState.errors.root && ((0, jsx_runtime_1.jsx)(react_components_1.MessageBar, { intent: "error", children: (0, jsx_runtime_1.jsx)(react_components_1.MessageBarBody, { children: form.formState.errors.root.message }) })), (0, jsx_runtime_1.jsxs)(react_components_1.Button, { appearance: "primary", type: "submit", style: {
|
|
81
|
+
}, children: [(0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "username", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Username", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(TextControl_1.TextControl, { placeholder: "Username", appearance: "outline", name: field.name, value: field.value, onChange: field.onChange, onBlur: field.onBlur, autoCapitalize: "none", autoCorrect: "off", error: !!fieldState.error?.message && formState.isSubmitted }) })) }), (0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: form.control, name: "password", render: ({ field, fieldState, formState }) => ((0, jsx_runtime_1.jsx)(SectionControl_1.SectionControlWrapper, { label: "Password", labelPosition: "top", required: true, isError: !!fieldState.error?.message && formState.isSubmitted, errorMessage: fieldState.error?.message, children: (0, jsx_runtime_1.jsx)(PasswordControl_1.PasswordControl, { placeholder: "Password", name: field.name, appearance: "outline", error: !!fieldState.error?.message && formState.isSubmitted, value: field.value, onChange: field.onChange, onBlur: field.onBlur }) })) }), props.beforeLoginContent, !!form.formState.errors.root && ((0, jsx_runtime_1.jsx)(react_components_1.MessageBar, { intent: "error", children: (0, jsx_runtime_1.jsx)(react_components_1.MessageBarBody, { children: form.formState.errors.root.message }) })), (0, jsx_runtime_1.jsxs)(react_components_1.Button, { appearance: "primary", type: "submit", style: {
|
|
82
82
|
marginTop: 8,
|
|
83
83
|
pointerEvents: form.formState.isSubmitting ? 'none' : 'auto',
|
|
84
|
-
}, children: [form.formState.isSubmitting && ((0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny", appearance: "inverted", style: { marginRight: 4 } })), "Login"] })] }), (0, jsx_runtime_1.jsx)("div", { style: { height: 80 } })] }) }));
|
|
84
|
+
}, children: [form.formState.isSubmitting && ((0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny", appearance: "inverted", style: { marginRight: 4 } })), "Login"] }), props.afterLoginContent] }), (0, jsx_runtime_1.jsx)("div", { style: { height: 80 } })] }) }));
|
|
85
85
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { LoginFormData } from './LoginForm';
|
|
1
2
|
interface LoginPageProps {
|
|
2
3
|
logoImageUrl?: string;
|
|
3
4
|
illustrationImageUrl?: string;
|
|
4
5
|
onLogin: (username: string, password: string) => Promise<void>;
|
|
6
|
+
beforeLoginContent?: React.ReactNode;
|
|
7
|
+
afterLoginContent?: React.ReactNode;
|
|
8
|
+
subtitle?: string;
|
|
9
|
+
defaultValues?: LoginFormData;
|
|
5
10
|
}
|
|
6
11
|
export declare function PageLogin(props: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
7
12
|
export {};
|
package/components/PageLogin.js
CHANGED
|
@@ -33,7 +33,8 @@ function PageLogin(props) {
|
|
|
33
33
|
justifyContent: 'flex-start',
|
|
34
34
|
gap: 16,
|
|
35
35
|
minWidth: 300,
|
|
36
|
-
|
|
36
|
+
maxWidth: 300,
|
|
37
|
+
}, children: (0, jsx_runtime_1.jsx)(LoginForm_1.LoginForm, { logoImageUrl: props.logoImageUrl, onLogin: props.onLogin, defaultValues: props.defaultValues, beforeLoginContent: props.beforeLoginContent, afterLoginContent: props.afterLoginContent, subtitle: props.subtitle }) }) }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
37
38
|
display: 'flex',
|
|
38
39
|
flexDirection: 'column',
|
|
39
40
|
gap: 16,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ISchemaExperienceStore, ISchemaStore } from '@headless-adminapp/core/store';
|
|
2
|
+
import { IDataService } from '@headless-adminapp/core/transport';
|
|
3
|
+
import { ControlProps } from './types';
|
|
4
|
+
export interface LookupOption {
|
|
5
|
+
limit: number;
|
|
6
|
+
search: string;
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type DataLookup = {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
logicalName: string;
|
|
13
|
+
avatar?: string;
|
|
14
|
+
};
|
|
15
|
+
export type RegardingControlProps = ControlProps<DataLookup> & {
|
|
16
|
+
lookupKey?: string;
|
|
17
|
+
dataService: IDataService;
|
|
18
|
+
entities: string[];
|
|
19
|
+
schemaStore: ISchemaStore;
|
|
20
|
+
experienceStore: ISchemaExperienceStore;
|
|
21
|
+
viewId?: string;
|
|
22
|
+
allowNavigation?: boolean;
|
|
23
|
+
allowNewRecord?: boolean;
|
|
24
|
+
};
|
|
25
|
+
export declare function RegardingControl(props: RegardingControlProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RegardingControl = RegardingControl;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_components_1 = require("@fluentui/react-components");
|
|
6
|
+
const app_1 = require("@headless-adminapp/app/app");
|
|
7
|
+
const hooks_1 = require("@headless-adminapp/app/hooks");
|
|
8
|
+
const useMetadata_1 = require("@headless-adminapp/app/metadata/hooks/useMetadata");
|
|
9
|
+
const hooks_2 = require("@headless-adminapp/app/route/hooks");
|
|
10
|
+
const app_2 = require("@headless-adminapp/core/experience/app");
|
|
11
|
+
const icons_1 = require("@headless-adminapp/icons");
|
|
12
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
13
|
+
const react_1 = require("react");
|
|
14
|
+
const AppStringContext_1 = require("../../App/AppStringContext");
|
|
15
|
+
const RecordCard_1 = require("../../PageEntityForm/RecordCard");
|
|
16
|
+
const avatar_1 = require("../../utils/avatar");
|
|
17
|
+
const useLookupData_1 = require("./useLookupData");
|
|
18
|
+
function RegardingControl(props) {
|
|
19
|
+
const Control = LookupControlMd;
|
|
20
|
+
return (0, jsx_runtime_1.jsx)(Control, { ...props });
|
|
21
|
+
}
|
|
22
|
+
const useStyles = (0, react_components_1.makeStyles)({
|
|
23
|
+
option: {
|
|
24
|
+
padding: 0,
|
|
25
|
+
'& .fui-Option__checkIcon': {
|
|
26
|
+
display: 'none',
|
|
27
|
+
},
|
|
28
|
+
'&[data-activedescendant-focusvisible]': {
|
|
29
|
+
background: react_components_1.tokens.colorNeutralBackground1Hover,
|
|
30
|
+
'&:after': {
|
|
31
|
+
border: 'none !important',
|
|
32
|
+
// background: tokens.colorNeutralBackground1Hover,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
const LookupControlMd = ({ value, onChange, id, name, onBlur, onFocus, placeholder, disabled, autoFocus, readOnly, dataService, entities, schemaStore, allowNavigation, }) => {
|
|
38
|
+
const [lookupEnabled, setLookupEnabled] = (0, react_1.useState)(false);
|
|
39
|
+
const [open, setOpen] = (0, react_1.useState)(false);
|
|
40
|
+
const [searchText, setSearchText] = (0, react_1.useState)('');
|
|
41
|
+
const { loockupStrings } = (0, AppStringContext_1.useAppStrings)();
|
|
42
|
+
const routeResolver = (0, hooks_2.useRouteResolver)();
|
|
43
|
+
const router = (0, hooks_2.useRouter)();
|
|
44
|
+
const path = (0, react_1.useMemo)(() => {
|
|
45
|
+
if (!value) {
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
if (!allowNavigation) {
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
return routeResolver({
|
|
52
|
+
logicalName: value.logicalName,
|
|
53
|
+
type: app_2.PageType.EntityForm,
|
|
54
|
+
id: value.id,
|
|
55
|
+
});
|
|
56
|
+
}, [allowNavigation, routeResolver, value]);
|
|
57
|
+
const handleOpenRecord = (0, react_1.useCallback)((event) => {
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
event.stopPropagation();
|
|
60
|
+
if (!path) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
router.push(path);
|
|
64
|
+
}, [path, router]);
|
|
65
|
+
(0, react_1.useEffect)(() => {
|
|
66
|
+
if (open)
|
|
67
|
+
setLookupEnabled(true);
|
|
68
|
+
}, [open]);
|
|
69
|
+
const [debouncedSearchText] = (0, hooks_1.useDebouncedValue)(searchText, 500);
|
|
70
|
+
const styles = useStyles();
|
|
71
|
+
const { experienceStore } = (0, useMetadata_1.useMetadata)();
|
|
72
|
+
const { isFetching: isConfigFetching, data: configs } = (0, react_query_1.useQuery)({
|
|
73
|
+
queryKey: ['data', 'getLookupViews', entities, undefined],
|
|
74
|
+
queryFn: async () => {
|
|
75
|
+
return Promise.all(entities.map(async (name) => {
|
|
76
|
+
const schema = schemaStore.getSchema(name);
|
|
77
|
+
const view = await experienceStore.getViewLookupV2(name);
|
|
78
|
+
return {
|
|
79
|
+
schema,
|
|
80
|
+
view: view?.experience,
|
|
81
|
+
};
|
|
82
|
+
}));
|
|
83
|
+
},
|
|
84
|
+
throwOnError: true,
|
|
85
|
+
initialData: [],
|
|
86
|
+
});
|
|
87
|
+
const result = (0, useLookupData_1.useLookupDatas)({
|
|
88
|
+
dataService,
|
|
89
|
+
searchText: debouncedSearchText,
|
|
90
|
+
enabled: lookupEnabled && !isConfigFetching && !value && !readOnly && !disabled,
|
|
91
|
+
items: configs,
|
|
92
|
+
});
|
|
93
|
+
const isLoading = result.some((item) => item.isFetching);
|
|
94
|
+
(0, react_1.useEffect)(() => {
|
|
95
|
+
if (value) {
|
|
96
|
+
setSearchText(value.name);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
setSearchText('');
|
|
100
|
+
}
|
|
101
|
+
}, [value]);
|
|
102
|
+
const handleChange = (value) => {
|
|
103
|
+
setSearchText('');
|
|
104
|
+
if (!value) {
|
|
105
|
+
return onChange?.(null);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const schema = schemaStore.getSchema(value.$entity);
|
|
109
|
+
return onChange?.({
|
|
110
|
+
id: value[schema.idAttribute],
|
|
111
|
+
name: value[schema.primaryAttribute],
|
|
112
|
+
logicalName: schema.logicalName,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const valueSchema = (0, react_1.useMemo)(() => {
|
|
117
|
+
if (!value) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
return schemaStore.getSchema(value?.logicalName);
|
|
121
|
+
}, [schemaStore, value]);
|
|
122
|
+
return ((0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative', width: '100%' }, children: [(0, jsx_runtime_1.jsxs)(react_components_1.Combobox, { name: name, appearance: "filled-darker", expandIcon: readOnly || disabled ? null : isLoading ? ((0, jsx_runtime_1.jsx)(react_components_1.Spinner, { size: "extra-tiny" })) : ((0, jsx_runtime_1.jsx)(icons_1.Icons.Search, { size: 18 })), placeholder: !value ? placeholder : '', inputMode: "search", style: { width: '100%', minWidth: 'unset' }, autoComplete: "off", readOnly: readOnly || disabled,
|
|
123
|
+
// disabled={disabled}
|
|
124
|
+
open: open && !value && !readOnly && !disabled, value: !value ? searchText : '', onOpenChange: (e, data) => setOpen(data.open), onChange: (e) => {
|
|
125
|
+
setSearchText(e.target.value);
|
|
126
|
+
}, onOptionSelect: (e, item) => {
|
|
127
|
+
const _item = result
|
|
128
|
+
.map((group, index) => {
|
|
129
|
+
const schema = configs[index].schema;
|
|
130
|
+
if (!schema) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const data = group.data;
|
|
134
|
+
const record = data?.records.find((x) => String(x[schema.idAttribute]) === String(item.optionValue));
|
|
135
|
+
return record;
|
|
136
|
+
})
|
|
137
|
+
.filter(Boolean)[0];
|
|
138
|
+
handleChange(_item ?? null);
|
|
139
|
+
}, disableAutoFocus: true, onBlur: onBlur, onFocus: onFocus, id: id, autoFocus: autoFocus, children: [result.map((group, index) => {
|
|
140
|
+
const schema = configs[index].schema;
|
|
141
|
+
const view = configs[index].view;
|
|
142
|
+
const data = group.data;
|
|
143
|
+
if (!data?.records.length) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return ((0, jsx_runtime_1.jsx)(react_components_1.OptionGroup, { label: schema.label, children: data?.records.map((item) => {
|
|
147
|
+
return ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: item[schema.idAttribute], className: (0, react_components_1.mergeClasses)(styles.option), text: item[schema.primaryAttribute], children: view?.card ? ((0, jsx_runtime_1.jsx)(RecordCard_1.RecordCard, { cardView: view.card, record: item, schema: schema })) : item[schema.primaryAttribute] }, item[schema.idAttribute]));
|
|
148
|
+
}) }, schema.logicalName));
|
|
149
|
+
}), !isLoading &&
|
|
150
|
+
result.every((item) => !item.data?.records.length) && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
151
|
+
paddingInline: react_components_1.tokens.spacingHorizontalL,
|
|
152
|
+
paddingBlock: react_components_1.tokens.spacingVerticalS,
|
|
153
|
+
}, children: (0, jsx_runtime_1.jsx)(react_components_1.Body1, { children: loockupStrings.noRecordsFound }) }))] }), !!value && ((0, jsx_runtime_1.jsx)("div", { style: {
|
|
154
|
+
position: 'absolute',
|
|
155
|
+
inset: 0,
|
|
156
|
+
alignItems: 'center',
|
|
157
|
+
paddingInline: 4,
|
|
158
|
+
display: 'flex',
|
|
159
|
+
}, children: (0, jsx_runtime_1.jsx)(react_components_1.TagGroup, { as: "div", children: (0, jsx_runtime_1.jsx)(react_components_1.Tag, { as: "span", appearance: "brand", size: "small", dismissible: !disabled && !readOnly, value: value.id, style: {
|
|
160
|
+
paddingRight: !disabled && !readOnly ? 0 : 5,
|
|
161
|
+
background: react_components_1.tokens.colorNeutralBackground6,
|
|
162
|
+
}, dismissIcon: (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', cursor: 'pointer' }, onClick: () => {
|
|
163
|
+
onChange?.(null);
|
|
164
|
+
}, children: (0, jsx_runtime_1.jsx)(icons_1.Icons.Close, { size: 16 }) }), primaryText: {
|
|
165
|
+
style: {
|
|
166
|
+
paddingBottom: 0,
|
|
167
|
+
},
|
|
168
|
+
}, children: allowNavigation && path ? ((0, jsx_runtime_1.jsxs)(react_components_1.Link, { href: path, onClick: handleOpenRecord, style: {
|
|
169
|
+
display: 'flex',
|
|
170
|
+
alignItems: 'center',
|
|
171
|
+
gap: react_components_1.tokens.spacingHorizontalXS,
|
|
172
|
+
}, children: [!!valueSchema && ((0, jsx_runtime_1.jsx)(LookupAvatar, { schema: valueSchema, logicalName: valueSchema.logicalName, value: value })), (0, jsx_runtime_1.jsx)(react_components_1.Body1, { style: {
|
|
173
|
+
overflow: 'hidden',
|
|
174
|
+
textOverflow: 'ellipsis',
|
|
175
|
+
whiteSpace: 'nowrap',
|
|
176
|
+
}, children: value?.name })] })) : ((0, jsx_runtime_1.jsx)(react_components_1.Body1, { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: value?.name })) }) }) }))] }));
|
|
177
|
+
};
|
|
178
|
+
const LookupAvatar = ({ logicalName, schema, value, }) => {
|
|
179
|
+
const { schemaMetadataDic } = (0, app_1.useAppContext)();
|
|
180
|
+
if (!schema.avatarAttribute) {
|
|
181
|
+
const experienceSchema = schemaMetadataDic[logicalName];
|
|
182
|
+
const Icon = experienceSchema.Icon ?? icons_1.Icons.Entity ?? icons_1.IconPlaceholder;
|
|
183
|
+
return ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
|
|
184
|
+
width: 20,
|
|
185
|
+
height: 20,
|
|
186
|
+
}, icon: {
|
|
187
|
+
style: {
|
|
188
|
+
background: 'transparent',
|
|
189
|
+
color: 'inherit',
|
|
190
|
+
},
|
|
191
|
+
children: (0, jsx_runtime_1.jsx)(Icon, { size: 20 }),
|
|
192
|
+
} }));
|
|
193
|
+
}
|
|
194
|
+
return ((0, jsx_runtime_1.jsx)(react_components_1.Avatar, { style: {
|
|
195
|
+
width: 20,
|
|
196
|
+
height: 20,
|
|
197
|
+
fontSize: react_components_1.tokens.fontSizeBase100,
|
|
198
|
+
backgroundColor: 'transparent',
|
|
199
|
+
}, name: value?.name, color: (0, avatar_1.getAvatarColor)(value?.name), image: {
|
|
200
|
+
src: value?.avatar,
|
|
201
|
+
} }));
|
|
202
|
+
};
|
|
@@ -6,4 +6,4 @@ export interface Lookup<T = string> {
|
|
|
6
6
|
export interface SelectControlProps<T> extends ControlProps<T> {
|
|
7
7
|
options: Lookup<T>[];
|
|
8
8
|
}
|
|
9
|
-
export default function SelectControl<T extends string | number>({ value, onChange, options, id, name, disabled, onBlur, onFocus, placeholder, }: SelectControlProps<T
|
|
9
|
+
export default function SelectControl<T extends string | number>({ value, onChange, options, id, name, disabled, onBlur, onFocus, placeholder, }: Readonly<SelectControlProps<T>>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -22,7 +22,5 @@ function SelectControl({ value, onChange, options, id, name, disabled, onBlur, o
|
|
|
22
22
|
// onChange={(e, v) => handleChange(v as string)}
|
|
23
23
|
selectedOptions: value ? [String(value)] : [], onOptionSelect: (event, data) => {
|
|
24
24
|
handleChange(data.optionValue);
|
|
25
|
-
}, onBlur: () => onBlur?.(), onFocus: () => onFocus?.(),
|
|
26
|
-
// error={error}
|
|
27
|
-
disabled: disabled, children: transformedOptions.map((x) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: x.value, children: x.label }, x.value))) }));
|
|
25
|
+
}, onBlur: () => onBlur?.(), onFocus: () => onFocus?.(), style: { pointerEvents: disabled ? 'none' : undefined }, children: transformedOptions.map((x) => ((0, jsx_runtime_1.jsx)(react_components_1.Option, { value: x.value, children: x.label }, x.value))) }));
|
|
28
26
|
}
|
|
@@ -2,5 +2,7 @@ import { ControlProps } from './types';
|
|
|
2
2
|
export interface TextAreaControlProps extends ControlProps<string> {
|
|
3
3
|
rows?: number;
|
|
4
4
|
textTransform?: 'capitalize' | 'uppercase' | 'lowercase' | 'none';
|
|
5
|
+
autoHeight?: boolean;
|
|
6
|
+
maxHeight?: number;
|
|
5
7
|
}
|
|
6
|
-
export declare function TextAreaControl({ value, onChange, id, name, placeholder, onBlur, onFocus, disabled, readOnly, rows, textTransform, }: TextAreaControlProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare function TextAreaControl({ value, onChange, id, name, placeholder, onBlur, onFocus, disabled, readOnly, rows, textTransform, autoHeight, maxHeight, }: TextAreaControlProps): import("react/jsx-runtime").JSX.Element;
|