@headless-adminapp/fluent 1.1.3 → 1.1.6
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 +16 -2
- package/PageEntityForm/StandardControl.js +10 -0
- 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/TimeControl.d.ts +4 -0
- package/form/controls/TimeControl.js +89 -0
- package/form/controls/useLookupData.d.ts +12 -2
- package/form/controls/useLookupData.js +71 -20
- 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;
|
|
@@ -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,12 +22,14 @@ 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");
|
|
28
29
|
const TelephoneControl_1 = require("../form/controls/TelephoneControl");
|
|
29
30
|
const TextAreaControl_1 = require("../form/controls/TextAreaControl");
|
|
30
31
|
const TextControl_1 = require("../form/controls/TextControl");
|
|
32
|
+
const TimeControl_1 = require("../form/controls/TimeControl");
|
|
31
33
|
const UrlControl_1 = require("../form/controls/UrlControl");
|
|
32
34
|
// Standard Control (Base control)
|
|
33
35
|
// TextControl
|
|
@@ -109,6 +111,10 @@ const StandardControl = (props) => {
|
|
|
109
111
|
const Control = componentStore_1.componentStore.getComponent('Form.DurationControl') ?? DurationControl_1.DurationControl;
|
|
110
112
|
return ((0, jsx_runtime_1.jsx)(Control, { name: name, placeholder: placeholder, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, readOnly: readOnly }));
|
|
111
113
|
}
|
|
114
|
+
case 'time': {
|
|
115
|
+
const Control = componentStore_1.componentStore.getComponent('Form.TimeControl') ?? TimeControl_1.TimeControl;
|
|
116
|
+
return ((0, jsx_runtime_1.jsx)(Control, { name: name, placeholder: placeholder, value: value, onChange: onChange, onBlur: onBlur, error: isError, disabled: isDisabled, readOnly: readOnly }));
|
|
117
|
+
}
|
|
112
118
|
default: {
|
|
113
119
|
return (0, jsx_runtime_1.jsx)(react_1.Fragment, {});
|
|
114
120
|
}
|
|
@@ -161,6 +167,10 @@ const StandardControl = (props) => {
|
|
|
161
167
|
const Control = componentStore_1.componentStore.getComponent('Form.MultiSelectLookupControl') ?? MultiSelectLookupControl_1.MultiSelectLookupControl;
|
|
162
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 }));
|
|
163
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
|
+
}
|
|
164
174
|
case 'boolean': {
|
|
165
175
|
const Control = componentStore_1.componentStore.getComponent('Form.SwitchControl') ?? SwitchControl_1.SwitchControl;
|
|
166
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 metadata_1 = require("@headless-adminapp/app/metadata");
|
|
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, metadata_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
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ControlProps } from './types';
|
|
2
|
+
export interface TimeControlProps extends ControlProps<number> {
|
|
3
|
+
}
|
|
4
|
+
export declare function TimeControl({ value, onChange, id, name, onBlur, placeholder, disabled, readOnly, }: Readonly<TimeControlProps>): import("react/jsx-runtime").JSX.Element;
|