form-craft-package 1.8.2-dev.0 → 1.8.2-dev.1
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/package.json +1 -1
- package/src/components/common/company-logo.tsx +40 -0
- package/src/components/companies/2-unauthenticated/forgot-password.tsx +4 -6
- package/src/components/companies/2-unauthenticated/index.tsx +8 -5
- package/src/components/companies/2-unauthenticated/reset-password.tsx +4 -6
- package/src/components/form/layout-renderer/1-row/header-render.tsx +23 -14
- package/src/components/form/layout-renderer/3-element/7-file-upload.tsx +20 -20
- package/src/components/form/layout-renderer/3-element/8-fields-with-options.tsx +1 -1
- package/src/functions/forms/data-render-functions.tsx +6 -3
- package/src/types/companies/site-layout/authenticated/index.tsx +6 -32
- package/src/types/forms/index.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useState } from 'react'
|
|
2
|
+
|
|
3
|
+
export default function CompanyLogoSection({
|
|
4
|
+
location = LogoLocationEnum.Authenticated,
|
|
5
|
+
logoUrl,
|
|
6
|
+
isPreview,
|
|
7
|
+
}: {
|
|
8
|
+
location?: LogoLocationEnum
|
|
9
|
+
logoUrl?: string
|
|
10
|
+
isPreview?: boolean
|
|
11
|
+
}) {
|
|
12
|
+
const [logoFailed, setLogoFailed] = useState(false)
|
|
13
|
+
|
|
14
|
+
if (!logoUrl || logoFailed)
|
|
15
|
+
return (
|
|
16
|
+
<div className="w-full py-1.5 rounded-md flex items-center justify-center text-danger italic text-lg font-bold">
|
|
17
|
+
[Company Logo]
|
|
18
|
+
</div>
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
const imgClassName =
|
|
22
|
+
location === LogoLocationEnum.Authenticated
|
|
23
|
+
? 'w-auto h-auto max-w-[140px] sm:max-w-[160px] md:max-w-[180px] lg:max-w-[200px] xl:max-w-[220px]'
|
|
24
|
+
: 'h-10 object-contain'
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<img
|
|
28
|
+
alt="Logo"
|
|
29
|
+
src={logoUrl}
|
|
30
|
+
style={{ maxWidth: isPreview ? '200px' : undefined }}
|
|
31
|
+
className={imgClassName}
|
|
32
|
+
onError={() => setLogoFailed(true)}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export enum LogoLocationEnum {
|
|
38
|
+
Authenticated,
|
|
39
|
+
Unauthenticated,
|
|
40
|
+
}
|
|
@@ -2,6 +2,7 @@ import { Button, Col, Form, Input, Row, Spin } from 'antd'
|
|
|
2
2
|
import { useNavigate } from 'react-router-dom'
|
|
3
3
|
import { useLoginHandler } from '../../common/custom-hooks/use-login-handler'
|
|
4
4
|
import { useConfigContext } from '../context'
|
|
5
|
+
import CompanyLogoSection, { LogoLocationEnum } from '../../common/company-logo'
|
|
5
6
|
|
|
6
7
|
export const ForgotPassword = () => {
|
|
7
8
|
const { config } = useConfigContext()
|
|
@@ -11,7 +12,6 @@ export const ForgotPassword = () => {
|
|
|
11
12
|
const formPadding = config?.loginLayout?.form?.padding
|
|
12
13
|
const titleColor = config?.loginLayout.form.color
|
|
13
14
|
const background = config?.loginLayout?.background
|
|
14
|
-
const logoUrl = config?.siteIdentity?.logoUrl
|
|
15
15
|
const primaryColor = config?.siteLayout?.siteConfigs?.colors?.primary
|
|
16
16
|
|
|
17
17
|
return (
|
|
@@ -26,11 +26,9 @@ export const ForgotPassword = () => {
|
|
|
26
26
|
maxWidth: '100%',
|
|
27
27
|
}}
|
|
28
28
|
>
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
</div>
|
|
33
|
-
)}
|
|
29
|
+
<div className="flex justify-center mb-4">
|
|
30
|
+
<CompanyLogoSection logoUrl={config?.siteIdentity?.logoUrl} location={LogoLocationEnum.Unauthenticated} />
|
|
31
|
+
</div>
|
|
34
32
|
|
|
35
33
|
<div className="font-bold mb-2" style={{ color: titleColor }}>
|
|
36
34
|
Forgot Password?
|
|
@@ -3,6 +3,7 @@ import { useConfigContext } from '../context'
|
|
|
3
3
|
import { useLoginHandler } from '../../common/custom-hooks/use-login-handler'
|
|
4
4
|
import { FaPlus } from 'react-icons/fa'
|
|
5
5
|
import { useNavigate } from 'react-router-dom'
|
|
6
|
+
import CompanyLogoSection, { LogoLocationEnum } from '../../common/company-logo'
|
|
6
7
|
|
|
7
8
|
export function UnauthenticatedLayout() {
|
|
8
9
|
const { config } = useConfigContext()
|
|
@@ -23,7 +24,7 @@ export function UnauthenticatedLayout() {
|
|
|
23
24
|
|
|
24
25
|
const logo = (
|
|
25
26
|
<div className="flex justify-center">
|
|
26
|
-
<
|
|
27
|
+
<CompanyLogoSection logoUrl={siteIdentity?.logoUrl} location={LogoLocationEnum.Unauthenticated} />
|
|
27
28
|
</div>
|
|
28
29
|
)
|
|
29
30
|
|
|
@@ -43,7 +44,9 @@ export function UnauthenticatedLayout() {
|
|
|
43
44
|
|
|
44
45
|
const formSection = (
|
|
45
46
|
<div
|
|
46
|
-
className={`fc-login-container ${
|
|
47
|
+
className={`fc-login-container ${
|
|
48
|
+
loginLayout?.layout === 'center' ? 'w-full' : 'w-1/2'
|
|
49
|
+
} flex items-center justify-center h-screen`}
|
|
47
50
|
>
|
|
48
51
|
<div
|
|
49
52
|
style={{
|
|
@@ -57,7 +60,7 @@ export function UnauthenticatedLayout() {
|
|
|
57
60
|
padding: `${loginLayout?.form?.padding || 16}px`,
|
|
58
61
|
background: loginLayout?.form?.background,
|
|
59
62
|
}}
|
|
60
|
-
className={`fc-login-panel max-h-screen overflow-auto shadow content-center text-center ${
|
|
63
|
+
className={`fc-login-panel max-h-screen overflow-auto shadow content-center text-center space-y-4 ${
|
|
61
64
|
loginLayout?.formStyle === 'full' ? 'h-screen' : ''
|
|
62
65
|
}`}
|
|
63
66
|
>
|
|
@@ -75,7 +78,7 @@ export function UnauthenticatedLayout() {
|
|
|
75
78
|
{loginLayout?.form?.title}
|
|
76
79
|
</div>
|
|
77
80
|
)}
|
|
78
|
-
<Form layout="vertical" onFinish={handleLogin} className=
|
|
81
|
+
<Form layout="vertical" onFinish={handleLogin} className="fc-login-form">
|
|
79
82
|
<div>
|
|
80
83
|
{loginLayout?.form?.fields?.map((field, index) => {
|
|
81
84
|
const isLast = index === loginLayout?.form.fields.length - 1
|
|
@@ -140,7 +143,7 @@ export function UnauthenticatedLayout() {
|
|
|
140
143
|
</div>
|
|
141
144
|
</Form>
|
|
142
145
|
|
|
143
|
-
{loginLayout?.logoPosition === 'bottom' && <div className=
|
|
146
|
+
{loginLayout?.logoPosition === 'bottom' && <div className="fc-login-logo">{logo}</div>}
|
|
144
147
|
</div>
|
|
145
148
|
</div>
|
|
146
149
|
)
|
|
@@ -4,6 +4,7 @@ import { useNavigate, useLocation } from 'react-router-dom'
|
|
|
4
4
|
import { useLoginHandler } from '../../common/custom-hooks/use-login-handler'
|
|
5
5
|
import { useConfigContext } from '../context'
|
|
6
6
|
import { useRef } from 'react'
|
|
7
|
+
import CompanyLogoSection, { LogoLocationEnum } from '../../common/company-logo'
|
|
7
8
|
|
|
8
9
|
export const ResetPassword = () => {
|
|
9
10
|
const { config } = useConfigContext()
|
|
@@ -21,7 +22,6 @@ export const ResetPassword = () => {
|
|
|
21
22
|
const formPadding = config?.loginLayout?.form?.padding
|
|
22
23
|
const titleColor = config?.loginLayout.form.color
|
|
23
24
|
const background = config?.loginLayout?.background
|
|
24
|
-
const logoUrl = config?.siteIdentity?.logoUrl
|
|
25
25
|
const primaryColor = config?.siteLayout?.siteConfigs?.colors?.primary
|
|
26
26
|
const isFirstLoad = useRef(true)
|
|
27
27
|
useEffect(() => {
|
|
@@ -64,11 +64,9 @@ export const ResetPassword = () => {
|
|
|
64
64
|
maxWidth: '100%',
|
|
65
65
|
}}
|
|
66
66
|
>
|
|
67
|
-
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
</div>
|
|
71
|
-
)}
|
|
67
|
+
<div className="flex justify-center mb-4">
|
|
68
|
+
<CompanyLogoSection logoUrl={config?.siteIdentity?.logoUrl} location={LogoLocationEnum.Unauthenticated} />
|
|
69
|
+
</div>
|
|
72
70
|
|
|
73
71
|
<div className="font-bold mb-2" style={{ color: titleColor }}>
|
|
74
72
|
Reset Password
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ReactNode, useState } from 'react'
|
|
1
|
+
import { ReactNode, useState, useTransition } from 'react'
|
|
2
2
|
import { IFormDndLayoutRowHeader } from '../../../../types'
|
|
3
|
-
import { Collapse } from 'antd'
|
|
3
|
+
import { Collapse, Spin } from 'antd'
|
|
4
4
|
import RowHeader from './header'
|
|
5
5
|
|
|
6
6
|
export const LayoutRowConditionalHeaderRenderer = ({
|
|
@@ -11,21 +11,30 @@ export const LayoutRowConditionalHeaderRenderer = ({
|
|
|
11
11
|
header: IFormDndLayoutRowHeader | undefined
|
|
12
12
|
}) => {
|
|
13
13
|
const [isCollapsed, setIsCollapsed] = useState(false)
|
|
14
|
+
const [isPendingTransition, startTransition] = useTransition()
|
|
14
15
|
|
|
15
16
|
if (header?.isCollapsible)
|
|
16
17
|
return (
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
<Spin spinning={isPendingTransition}>
|
|
19
|
+
<Collapse
|
|
20
|
+
className="fc-collapsible-row bg-transparent"
|
|
21
|
+
bordered={false}
|
|
22
|
+
defaultActiveKey={header.defaultCollapsed ? [] : ['1']}
|
|
23
|
+
items={[
|
|
24
|
+
{
|
|
25
|
+
key: '1',
|
|
26
|
+
label: (
|
|
27
|
+
<RowHeader
|
|
28
|
+
{...header}
|
|
29
|
+
isCollapsed={isCollapsed}
|
|
30
|
+
setIsCollapsed={() => startTransition(() => setIsCollapsed((c) => !c))}
|
|
31
|
+
/>
|
|
32
|
+
),
|
|
33
|
+
children,
|
|
34
|
+
},
|
|
35
|
+
]}
|
|
36
|
+
/>
|
|
37
|
+
</Spin>
|
|
29
38
|
)
|
|
30
39
|
|
|
31
40
|
if (header?.name)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Form, Input, Upload } from 'antd'
|
|
1
|
+
import { Form, Input, Spin, Upload } from 'antd'
|
|
2
2
|
import { useCallback, useState } from 'react'
|
|
3
3
|
import { Button_FillerPortal } from '../../../common/button'
|
|
4
4
|
import client from '../../../../api/client'
|
|
@@ -65,14 +65,10 @@ export default function LayoutRenderer_FileUpload({
|
|
|
65
65
|
|
|
66
66
|
return (
|
|
67
67
|
<>
|
|
68
|
-
<Form.Item
|
|
69
|
-
name={formItem.name}
|
|
70
|
-
labelAlign="left"
|
|
71
|
-
className="hidden"
|
|
72
|
-
label={elementProps.hasNoLabel ? '' : elementProps.label}
|
|
73
|
-
>
|
|
68
|
+
<Form.Item name={formItem.name} labelAlign="left" className="hidden">
|
|
74
69
|
<Input />
|
|
75
70
|
</Form.Item>
|
|
71
|
+
{!elementProps.hasNoLabel && elementProps.label && <span>{elementProps.label}</span>}
|
|
76
72
|
{savedSignatureBlobName ? (
|
|
77
73
|
<div
|
|
78
74
|
className={`${ELEMENTS_DEFAULT_CLASS.Upload} text-primary flex items-center gap-2 bg-white rounded w-max px-4 py-1 font-semibold`}
|
|
@@ -96,20 +92,24 @@ export default function LayoutRenderer_FileUpload({
|
|
|
96
92
|
</Button_FillerPortal>
|
|
97
93
|
</div>
|
|
98
94
|
) : elementProps.isDragger ? (
|
|
99
|
-
<
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
95
|
+
<Spin size="small" spinning={loading}>
|
|
96
|
+
<Upload.Dragger {...uploadProps} disabled={isDisabled} beforeUpload={(file) => beforeUpload(file)}>
|
|
97
|
+
<div className="flex flex-col items-center">
|
|
98
|
+
<FaUpload size={24} className="text-primary" />
|
|
99
|
+
<span className="font-semibold mt-2">{elementProps.placeholder}</span>
|
|
100
|
+
<span className="text-opacity-50">{elementProps.hint}</span>
|
|
101
|
+
</div>
|
|
102
|
+
</Upload.Dragger>
|
|
103
|
+
</Spin>
|
|
106
104
|
) : (
|
|
107
|
-
<
|
|
108
|
-
<
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
105
|
+
<Spin size="small" spinning={loading}>
|
|
106
|
+
<Upload {...uploadProps} disabled={isDisabled} beforeUpload={(file) => beforeUpload(file)}>
|
|
107
|
+
<Button_FillerPortal disabled={isDisabled} outline onClick={() => {}} className="w-full">
|
|
108
|
+
<FaUpload />
|
|
109
|
+
{elementProps.placeholder}
|
|
110
|
+
</Button_FillerPortal>
|
|
111
|
+
</Upload>
|
|
112
|
+
</Spin>
|
|
113
113
|
)}
|
|
114
114
|
</>
|
|
115
115
|
)
|
|
@@ -228,7 +228,7 @@ export default function LayoutRenderer_FieldsWithOptions({
|
|
|
228
228
|
<LayoutRenderer_FieldElement formRef={formRef}>
|
|
229
229
|
{() => ({
|
|
230
230
|
...props,
|
|
231
|
-
label: (
|
|
231
|
+
label: props.label && (
|
|
232
232
|
<div className="flex items-center gap-2 w-full">
|
|
233
233
|
<span>{props.label}</span>
|
|
234
234
|
{(props as ISelectElementProps).goToDetails?.enabled &&
|
|
@@ -179,10 +179,13 @@ const renderImageData = (imgFullUrl: string, renderConfig: IDataRender_Image) =>
|
|
|
179
179
|
const renderTags = (data: string[]) => {
|
|
180
180
|
if (!Array.isArray(data)) return '-'
|
|
181
181
|
|
|
182
|
+
console.log(data)
|
|
182
183
|
return (
|
|
183
|
-
<div className="
|
|
184
|
-
{data.map((str) => (
|
|
185
|
-
<span className="bg-gray-200 px-2 rounded-lg text-[11px]">
|
|
184
|
+
<div className="space-x-2">
|
|
185
|
+
{data.map((str, strIdx) => (
|
|
186
|
+
<span key={strIdx} className="bg-gray-200 px-2 py-0.5 rounded-lg text-[11px]">
|
|
187
|
+
{str}
|
|
188
|
+
</span>
|
|
186
189
|
))}
|
|
187
190
|
</div>
|
|
188
191
|
)
|
|
@@ -11,6 +11,7 @@ import { UserAuth } from '../../../../api/user'
|
|
|
11
11
|
import { useBreadcrumb } from '../../../../components/common/custom-hooks/use-breadcrumb.hook'
|
|
12
12
|
import { PageViewTypEnum } from '../../../../enums'
|
|
13
13
|
import { REACT_QUERY_CLIENT } from '../../../../constants'
|
|
14
|
+
import CompanyLogoSection from '../../../../components/common/company-logo'
|
|
14
15
|
|
|
15
16
|
const { Header, Content, Sider } = Layout
|
|
16
17
|
|
|
@@ -147,14 +148,7 @@ export const layoutTemplates = [
|
|
|
147
148
|
{/* Logo */}
|
|
148
149
|
<div className="flex fc-logo">
|
|
149
150
|
<a href="/">
|
|
150
|
-
<
|
|
151
|
-
alt="logo"
|
|
152
|
-
src={config?.siteIdentity?.logoUrl}
|
|
153
|
-
style={{
|
|
154
|
-
maxWidth: isPreview ? '200px' : undefined,
|
|
155
|
-
}}
|
|
156
|
-
className="w-auto h-auto max-w-[140px] sm:max-w-[160px] md:max-w-[180px] lg:max-w-[200px] xl:max-w-[220px]"
|
|
157
|
-
/>
|
|
151
|
+
<CompanyLogoSection logoUrl={config?.siteIdentity?.logoUrl} isPreview={isPreview} />
|
|
158
152
|
</a>
|
|
159
153
|
{/* Mobile Menu */}
|
|
160
154
|
<Drawer
|
|
@@ -348,14 +342,7 @@ export const layoutTemplates = [
|
|
|
348
342
|
{/* Logo */}
|
|
349
343
|
<div className="flex">
|
|
350
344
|
<a href="/">
|
|
351
|
-
<
|
|
352
|
-
alt="logo"
|
|
353
|
-
src={config?.siteIdentity?.logoUrl}
|
|
354
|
-
style={{
|
|
355
|
-
maxWidth: isPreview ? '200px' : undefined,
|
|
356
|
-
}}
|
|
357
|
-
className="w-auto h-auto max-w-[140px] sm:max-w-[160px] md:max-w-[180px] lg:max-w-[200px] xl:max-w-[220px]"
|
|
358
|
-
/>
|
|
345
|
+
<CompanyLogoSection logoUrl={config?.siteIdentity?.logoUrl} isPreview={isPreview} />
|
|
359
346
|
</a>
|
|
360
347
|
{/* Mobile Menu */}
|
|
361
348
|
<Drawer
|
|
@@ -556,6 +543,7 @@ export const layoutTemplates = [
|
|
|
556
543
|
))}
|
|
557
544
|
</Menu>
|
|
558
545
|
)
|
|
546
|
+
|
|
559
547
|
return (
|
|
560
548
|
<Layout className="fc-layout min-h-screen">
|
|
561
549
|
{/* Side Menu */}
|
|
@@ -570,14 +558,7 @@ export const layoutTemplates = [
|
|
|
570
558
|
{!isCollapsed && (
|
|
571
559
|
<div className="flex justify-center p-2 fc-logo">
|
|
572
560
|
<a href="/" className="w-full flex justify-center">
|
|
573
|
-
<
|
|
574
|
-
alt="logo"
|
|
575
|
-
src={config?.siteIdentity?.logoUrl}
|
|
576
|
-
style={{
|
|
577
|
-
maxWidth: isPreview ? '200px' : undefined,
|
|
578
|
-
}}
|
|
579
|
-
className="w-auto h-auto max-w-[140px] sm:max-w-[160px] md:max-w-[180px] lg:max-w-[200px] xl:max-w-[220px]"
|
|
580
|
-
/>
|
|
561
|
+
<CompanyLogoSection logoUrl={config?.siteIdentity?.logoUrl} isPreview={isPreview} />
|
|
581
562
|
</a>
|
|
582
563
|
</div>
|
|
583
564
|
)}
|
|
@@ -641,14 +622,7 @@ export const layoutTemplates = [
|
|
|
641
622
|
{/* Logo */}
|
|
642
623
|
<div className="flex p-2 fc-logo">
|
|
643
624
|
<a href="/">
|
|
644
|
-
<
|
|
645
|
-
alt="logo"
|
|
646
|
-
src={config?.siteIdentity?.logoUrl}
|
|
647
|
-
style={{
|
|
648
|
-
maxWidth: isPreview ? '200px' : undefined,
|
|
649
|
-
}}
|
|
650
|
-
className="w-auto h-auto max-w-[140px] sm:max-w-[160px] md:max-w-[180px] lg:max-w-[200px] xl:max-w-[220px]"
|
|
651
|
-
/>
|
|
625
|
+
<CompanyLogoSection logoUrl={config?.siteIdentity?.logoUrl} isPreview={isPreview} />
|
|
652
626
|
</a>
|
|
653
627
|
</div>
|
|
654
628
|
{/* Mobile Menu Button */}
|