@tellescope/react-components 1.205.0 → 1.207.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/lib/cjs/Forms/form_responses.d.ts +6 -2
- package/lib/cjs/Forms/form_responses.d.ts.map +1 -1
- package/lib/cjs/Forms/form_responses.js +8 -7
- package/lib/cjs/Forms/form_responses.js.map +1 -1
- package/lib/cjs/Forms/forms.d.ts +5 -1
- package/lib/cjs/Forms/forms.d.ts.map +1 -1
- package/lib/cjs/Forms/forms.js +12 -8
- package/lib/cjs/Forms/forms.js.map +1 -1
- package/lib/cjs/Forms/hooks.d.ts.map +1 -1
- package/lib/cjs/Forms/hooks.js +4 -5
- package/lib/cjs/Forms/hooks.js.map +1 -1
- package/lib/cjs/Forms/inputs.d.ts +8 -3
- package/lib/cjs/Forms/inputs.d.ts.map +1 -1
- package/lib/cjs/Forms/inputs.js +51 -34
- package/lib/cjs/Forms/inputs.js.map +1 -1
- package/lib/cjs/displays.d.ts +2 -0
- package/lib/cjs/displays.d.ts.map +1 -1
- package/lib/cjs/displays.js.map +1 -1
- package/lib/cjs/inputs_shared.d.ts.map +1 -1
- package/lib/cjs/inputs_shared.js +25 -1
- package/lib/cjs/inputs_shared.js.map +1 -1
- package/lib/cjs/layout.d.ts +2 -1
- package/lib/cjs/layout.d.ts.map +1 -1
- package/lib/cjs/layout.js +2 -2
- package/lib/cjs/layout.js.map +1 -1
- package/lib/cjs/state.d.ts +37 -0
- package/lib/cjs/state.d.ts.map +1 -1
- package/lib/cjs/state.js +19 -3
- package/lib/cjs/state.js.map +1 -1
- package/lib/esm/Forms/form_responses.d.ts +6 -2
- package/lib/esm/Forms/form_responses.d.ts.map +1 -1
- package/lib/esm/Forms/form_responses.js +8 -7
- package/lib/esm/Forms/form_responses.js.map +1 -1
- package/lib/esm/Forms/forms.d.ts +5 -1
- package/lib/esm/Forms/forms.d.ts.map +1 -1
- package/lib/esm/Forms/forms.js +12 -8
- package/lib/esm/Forms/forms.js.map +1 -1
- package/lib/esm/Forms/hooks.d.ts.map +1 -1
- package/lib/esm/Forms/hooks.js +4 -5
- package/lib/esm/Forms/hooks.js.map +1 -1
- package/lib/esm/Forms/inputs.d.ts +8 -3
- package/lib/esm/Forms/inputs.d.ts.map +1 -1
- package/lib/esm/Forms/inputs.js +51 -34
- package/lib/esm/Forms/inputs.js.map +1 -1
- package/lib/esm/displays.d.ts +2 -0
- package/lib/esm/displays.d.ts.map +1 -1
- package/lib/esm/displays.js.map +1 -1
- package/lib/esm/inputs_shared.d.ts.map +1 -1
- package/lib/esm/inputs_shared.js +25 -1
- package/lib/esm/inputs_shared.js.map +1 -1
- package/lib/esm/layout.d.ts +2 -1
- package/lib/esm/layout.d.ts.map +1 -1
- package/lib/esm/layout.js +2 -2
- package/lib/esm/layout.js.map +1 -1
- package/lib/esm/state.d.ts +37 -0
- package/lib/esm/state.d.ts.map +1 -1
- package/lib/esm/state.js +15 -0
- package/lib/esm/state.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/src/Forms/form_responses.tsx +9 -8
- package/src/Forms/forms.tsx +13 -2
- package/src/Forms/hooks.tsx +1 -3
- package/src/Forms/inputs.tsx +38 -5
- package/src/displays.tsx +2 -0
- package/src/inputs_shared.tsx +17 -1
- package/src/layout.tsx +3 -2
- package/src/state.tsx +22 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellescope/react-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.207.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"@reduxjs/toolkit": "^1.6.2",
|
|
48
48
|
"@stripe/react-stripe-js": "^2.9.0",
|
|
49
49
|
"@stripe/stripe-js": "^1.52.1",
|
|
50
|
-
"@tellescope/constants": "^1.
|
|
51
|
-
"@tellescope/sdk": "^1.
|
|
52
|
-
"@tellescope/types-client": "^1.
|
|
53
|
-
"@tellescope/types-models": "^1.
|
|
54
|
-
"@tellescope/types-utilities": "^1.
|
|
55
|
-
"@tellescope/utilities": "^1.
|
|
56
|
-
"@tellescope/validation": "^1.
|
|
50
|
+
"@tellescope/constants": "^1.207.0",
|
|
51
|
+
"@tellescope/sdk": "^1.207.0",
|
|
52
|
+
"@tellescope/types-client": "^1.207.0",
|
|
53
|
+
"@tellescope/types-models": "^1.207.0",
|
|
54
|
+
"@tellescope/types-utilities": "^1.207.0",
|
|
55
|
+
"@tellescope/utilities": "^1.207.0",
|
|
56
|
+
"@tellescope/validation": "^1.207.0",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
|
58
58
|
"@typescript-eslint/parser": "^4.33.0",
|
|
59
59
|
"css-to-react-native": "^3.0.0",
|
|
@@ -80,11 +80,11 @@
|
|
|
80
80
|
"yup": "^0.32.10"
|
|
81
81
|
},
|
|
82
82
|
"peerDependencies": {
|
|
83
|
-
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
84
|
-
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
83
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
84
|
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
85
85
|
"react-native": "^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.71.0"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "ddf48910e1681e4fc241e85af98f4c6a0f3f42bb",
|
|
88
88
|
"publishConfig": {
|
|
89
89
|
"access": "public"
|
|
90
90
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from "react"
|
|
1
|
+
import React, { useEffect } from "react"
|
|
2
2
|
import { Divider, Grid, Typography } from "@mui/material"
|
|
3
3
|
import { Enduser, FormResponse } from "@tellescope/types-client"
|
|
4
4
|
import { form_response_value_to_string, formatted_date, getOrgnizationLogoURL, remove_script_tags, user_display_name } from "@tellescope/utilities"
|
|
5
|
-
import { DownloadFileIconButton, LabeledIconButton, SecureImage, useEndusers, useOrganization, useResolvedSession, useSession, useUsers, value_is_loaded } from "../index"
|
|
5
|
+
import { DownloadFileIconButton, ImageProps, LabeledIconButton, SecureImage, useEndusers, useOrganization, useResolvedSession, useSession, useUsers, value_is_loaded } from "../index"
|
|
6
6
|
import CloseIcon from '@mui/icons-material/Close';
|
|
7
7
|
import { DatabaseSelectResponse, FormResponseAnswerAddress, FormResponseValueAnswer } from "@tellescope/types-models"
|
|
8
8
|
import { Image } from "../layout"
|
|
@@ -64,6 +64,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
|
|
|
64
64
|
: (
|
|
65
65
|
<SecureImage secureName={a.value.secureName} onImageClick={onImageClick}
|
|
66
66
|
style={{ maxHeight: 400, maxWidth: 400 }}
|
|
67
|
+
crossOrigin="anonymous"
|
|
67
68
|
/>
|
|
68
69
|
)
|
|
69
70
|
}
|
|
@@ -181,7 +182,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
|
|
|
181
182
|
)
|
|
182
183
|
)
|
|
183
184
|
|
|
184
|
-
export const OrganizationLogo = () => {
|
|
185
|
+
export const OrganizationLogo = ({ crossOrigin } : { crossOrigin?: ImageProps['crossOrigin'] }) => {
|
|
185
186
|
const [organizationLoading] = useOrganization()
|
|
186
187
|
|
|
187
188
|
if (!value_is_loaded(organizationLoading)) return null
|
|
@@ -190,7 +191,7 @@ export const OrganizationLogo = () => {
|
|
|
190
191
|
const logoURL = getOrgnizationLogoURL(organizationLoading.value)
|
|
191
192
|
|
|
192
193
|
return (
|
|
193
|
-
<Image
|
|
194
|
+
<Image crossOrigin={crossOrigin}
|
|
194
195
|
src={logoURL}
|
|
195
196
|
alt=""
|
|
196
197
|
maxWidth={400}
|
|
@@ -199,12 +200,12 @@ export const OrganizationLogo = () => {
|
|
|
199
200
|
)
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
export const ResolveOrganizationLogo = ({ logoURL } : { logoURL?: string }) => {
|
|
203
|
+
export const ResolveOrganizationLogo = ({ logoURL, crossOrigin } : { logoURL?: string, crossOrigin?: ImageProps['crossOrigin'] }) => {
|
|
203
204
|
const session = useResolvedSession()
|
|
204
205
|
|
|
205
206
|
if (logoURL) {
|
|
206
207
|
return (
|
|
207
|
-
<Image
|
|
208
|
+
<Image crossOrigin={crossOrigin}
|
|
208
209
|
src={logoURL}
|
|
209
210
|
alt=""
|
|
210
211
|
maxWidth={400}
|
|
@@ -215,7 +216,7 @@ export const ResolveOrganizationLogo = ({ logoURL } : { logoURL?: string }) => {
|
|
|
215
216
|
|
|
216
217
|
if (session.type === 'enduser') return null
|
|
217
218
|
|
|
218
|
-
return <OrganizationLogo />
|
|
219
|
+
return <OrganizationLogo crossOrigin={crossOrigin} />
|
|
219
220
|
}
|
|
220
221
|
|
|
221
222
|
interface FormResponse_T {
|
|
@@ -245,7 +246,7 @@ export const FormResponseView = ({ showAnswerInline=true, logoURL, enduser, onCl
|
|
|
245
246
|
<div style={{ textAlign: 'center' }}>
|
|
246
247
|
{!hideHeader &&
|
|
247
248
|
<>
|
|
248
|
-
<ResolveOrganizationLogo logoURL={logoURL} />
|
|
249
|
+
<ResolveOrganizationLogo logoURL={logoURL} crossOrigin="anonymous" />
|
|
249
250
|
|
|
250
251
|
<h2 style={{
|
|
251
252
|
fontSize: 20,
|
package/src/Forms/forms.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
|
|
2
2
|
import { Button, CircularProgress, FileBlob, FileUploadHandler, Flex, LinearProgress, LoadingButton, Modal, Paper, Styled, Typography, form_display_text_for_language, useFileUpload, useFormResponses, useSession } from "../index"
|
|
3
3
|
import { useListForFormFields, useOrganizationTheme, useTellescopeForm, WithOrganizationTheme, Response, FileResponse, NextFieldLogicOptions } from "./hooks"
|
|
4
4
|
import { ChangeHandler, FormInputs } from "./types"
|
|
5
|
-
import { AddressInput, AllergiesInput, AppointmentBookingInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, defaultButtonStyles } from "./inputs"
|
|
5
|
+
import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, defaultButtonStyles } from "./inputs"
|
|
6
6
|
import { PRIMARY_HEX } from "@tellescope/constants"
|
|
7
7
|
import { FormResponse, FormField, Form, Enduser } from "@tellescope/types-client"
|
|
8
8
|
import { FormResponseAnswerFileValue, OrganizationTheme } from "@tellescope/types-models"
|
|
@@ -35,6 +35,7 @@ export const TellescopeFormContainer = ({ businessId, organizationIds, ...props
|
|
|
35
35
|
|
|
36
36
|
const TellescopeFormContainerWithTheme: typeof TellescopeFormContainer = ({ children, language, onChangeLanguage, style, hideBg, backgroundColor, hideLogo, logoHeight }) => {
|
|
37
37
|
const theme = useOrganizationTheme()
|
|
38
|
+
console.log('logoHeight',logoHeight)
|
|
38
39
|
|
|
39
40
|
const formContent = (
|
|
40
41
|
<Flex flex={1} column>
|
|
@@ -96,12 +97,13 @@ export interface TellescopeFormProps extends ReturnType<typeof useTellescopeForm
|
|
|
96
97
|
enduser?: Partial<Enduser>,
|
|
97
98
|
groupId?: string,
|
|
98
99
|
groupInstance?: string,
|
|
100
|
+
logoHeight?: number,
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
const LOGO_HEIGHT = 40
|
|
102
104
|
export const TellescopeForm = (props : TellescopeFormProps & Styled & { hideBg?: boolean, theme?: OrganizationTheme, inputStyle?: React.CSSProperties }) => (
|
|
103
105
|
<WithOrganizationTheme>
|
|
104
|
-
<TellescopeFormWithContext {...props} />
|
|
106
|
+
<TellescopeFormWithContext {...props} logoHeight={props?.logoHeight || props?.form?.customization?.logoHeight} />
|
|
105
107
|
</WithOrganizationTheme>
|
|
106
108
|
)
|
|
107
109
|
|
|
@@ -137,6 +139,7 @@ export const QuestionForField = ({
|
|
|
137
139
|
logicOptions,
|
|
138
140
|
uploadingFiles, setUploadingFiles, handleFileUpload,
|
|
139
141
|
groupFields,
|
|
142
|
+
AddToDatabase,
|
|
140
143
|
} : {
|
|
141
144
|
spacing?: number,
|
|
142
145
|
form?: Form,
|
|
@@ -154,6 +157,7 @@ export const QuestionForField = ({
|
|
|
154
157
|
uploadingFiles: { fieldId: string }[]
|
|
155
158
|
setUploadingFiles: React.Dispatch<React.SetStateAction<{ fieldId: string }[]>>,
|
|
156
159
|
groupFields?: FormField[],
|
|
160
|
+
AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
|
|
157
161
|
} & Pick<TellescopeFormProps, "rootResponseId" | "goToNextField" | "groupId" | "groupInstance" | "submit" | "formResponseId" | 'enduserId' | 'isPreviousDisabled' | 'goToPreviousField' | 'enduser' | 'handleDatabaseSelect' | 'onAddFile' | 'onFieldChange' | 'fields' | 'customInputs' | 'responses' | 'selectedFiles' | 'validateField'>) => {
|
|
158
162
|
const String = customInputs?.['string'] ?? StringInput
|
|
159
163
|
const StringLong = customInputs?.['stringLong'] ?? StringLongInput
|
|
@@ -325,6 +329,7 @@ export const QuestionForField = ({
|
|
|
325
329
|
<DatabaseSelect field={field} disabled={value.disabled} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Database Select'>}
|
|
326
330
|
onDatabaseSelect={handleDatabaseSelect}
|
|
327
331
|
responses={responses} form={form}
|
|
332
|
+
AddToDatabase={AddToDatabase}
|
|
328
333
|
/>
|
|
329
334
|
)
|
|
330
335
|
: field.type === 'Medications' ? (
|
|
@@ -332,6 +337,7 @@ export const QuestionForField = ({
|
|
|
332
337
|
)
|
|
333
338
|
: field.type === 'Insurance' ? (
|
|
334
339
|
<Insurance field={field} value={value.answer.value as any} form={form}
|
|
340
|
+
onDatabaseSelect={handleDatabaseSelect}
|
|
335
341
|
enduser={enduser} responses={responses} // for filtering insurers by state
|
|
336
342
|
onChange={(v, fieldId) => (onFieldChange as ChangeHandler<'Insurance'>)({
|
|
337
343
|
...v,
|
|
@@ -381,6 +387,7 @@ export const QuestionForField = ({
|
|
|
381
387
|
questionGroupSize={field.options?.subFields?.length}
|
|
382
388
|
uploadingFiles={uploadingFiles} setUploadingFiles={setUploadingFiles}
|
|
383
389
|
handleFileUpload={handleFileUpload}
|
|
390
|
+
AddToDatabase={AddToDatabase}
|
|
384
391
|
/>
|
|
385
392
|
</Flex>
|
|
386
393
|
)
|
|
@@ -692,6 +699,7 @@ const TellescopeFormWithContext: typeof TellescopeForm = (props) => {
|
|
|
692
699
|
return (
|
|
693
700
|
<TellescopeFormContainer style={props.style} dontAddContext
|
|
694
701
|
hideBg={props.hideBg || props.form?.customization?.hideBg}
|
|
702
|
+
logoHeight={props.logoHeight}
|
|
695
703
|
backgroundColor={props.backgroundColor}
|
|
696
704
|
hideLogo={props?.customization?.hideLogo}
|
|
697
705
|
>
|
|
@@ -918,6 +926,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
|
|
|
918
926
|
updatedAt?: Date,
|
|
919
927
|
otherEnduserIds?: string[],
|
|
920
928
|
onBulkErrors?: (errors: { enduserId: string, message: string }[]) => void,
|
|
929
|
+
AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
|
|
921
930
|
}> = ({
|
|
922
931
|
customInputs,
|
|
923
932
|
submitErrorMessage,
|
|
@@ -969,6 +978,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
|
|
|
969
978
|
groupId,
|
|
970
979
|
groupInstance,
|
|
971
980
|
uploadingFiles, setUploadingFiles, handleFileUpload,
|
|
981
|
+
AddToDatabase,
|
|
972
982
|
...props
|
|
973
983
|
}) => {
|
|
974
984
|
const list = useListForFormFields(fields, responses, { form: props.form, gender: enduser?.gender })
|
|
@@ -1051,6 +1061,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
|
|
|
1051
1061
|
groupId={groupId} groupInstance={groupInstance}
|
|
1052
1062
|
uploadingFiles={uploadingFiles} setUploadingFiles={setUploadingFiles}
|
|
1053
1063
|
handleFileUpload={handleFileUpload}
|
|
1064
|
+
AddToDatabase={AddToDatabase}
|
|
1054
1065
|
/>
|
|
1055
1066
|
</Flex>
|
|
1056
1067
|
</Flex>
|
package/src/Forms/hooks.tsx
CHANGED
|
@@ -653,9 +653,7 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
|
|
|
653
653
|
? (
|
|
654
654
|
(f.options?.default && !isNaN(parseInt(f.options.default)))
|
|
655
655
|
? parseInt(f.options.default)
|
|
656
|
-
:
|
|
657
|
-
? undefined
|
|
658
|
-
: (f.options?.from || 1)
|
|
656
|
+
: undefined // shows no selection on slider
|
|
659
657
|
)
|
|
660
658
|
: f.type === 'Related Contacts'
|
|
661
659
|
? (f.isOptional ? [] : [{ relationships: f?.options?.relatedContactTypes?.length === 1 ? [{ type: f.options.relatedContactTypes[0] as EnduserRelationship['type'], id: ''! } ] : [] }])
|
package/src/Forms/inputs.tsx
CHANGED
|
@@ -532,10 +532,10 @@ export const NumberInput = ({ field, value, onChange, form, ...props }: FormInpu
|
|
|
532
532
|
)
|
|
533
533
|
}
|
|
534
534
|
|
|
535
|
-
export const InsuranceInput = ({ field, value, onChange, form, responses, enduser, ...props }: FormInputProps<'Insurance'>) => {
|
|
535
|
+
export const InsuranceInput = ({ field, onDatabaseSelect, value, onChange, form, responses, enduser, ...props }: FormInputProps<'Insurance'>) => {
|
|
536
536
|
const session = useResolvedSession()
|
|
537
537
|
|
|
538
|
-
const [payers, setPayers] = useState<{ id: string, name: string, type?: string, state?: string }[]>([])
|
|
538
|
+
const [payers, setPayers] = useState<{ id: string, name: string, databaseRecord?: DatabaseRecord, type?: string, state?: string }[]>([])
|
|
539
539
|
const [query, setQuery] = useState('')
|
|
540
540
|
|
|
541
541
|
const addressQuestion = useMemo(() => responses?.find(r => {
|
|
@@ -567,6 +567,7 @@ export const InsuranceInput = ({ field, value, onChange, form, responses, enduse
|
|
|
567
567
|
name: c.values.find(v => v.label?.trim()?.toLowerCase() === 'name')?.value?.toString() || '',
|
|
568
568
|
state: c.values.find(v => v.label?.trim()?.toLowerCase() === 'state')?.value?.toString() || '',
|
|
569
569
|
type: c.values.find(v => v.label?.trim()?.toLowerCase() === 'type')?.value?.toString() || '',
|
|
570
|
+
databaseRecord: c,
|
|
570
571
|
}))
|
|
571
572
|
.filter(c => !c.state || !state || (c.state === state))
|
|
572
573
|
))
|
|
@@ -613,6 +614,11 @@ export const InsuranceInput = ({ field, value, onChange, form, responses, enduse
|
|
|
613
614
|
: (e, v) => {
|
|
614
615
|
if (v) { setQuery(v) }
|
|
615
616
|
|
|
617
|
+
const databaseRecord = payers.find(p => p.name === v)?.databaseRecord
|
|
618
|
+
if (databaseRecord) {
|
|
619
|
+
onDatabaseSelect?.([databaseRecord])
|
|
620
|
+
}
|
|
621
|
+
|
|
616
622
|
onChange({
|
|
617
623
|
...value,
|
|
618
624
|
payerName: v || '',
|
|
@@ -1864,7 +1870,18 @@ const useDatabaseChoices = ({ databaseId='', field, otherAnswers } : { databaseI
|
|
|
1864
1870
|
})
|
|
1865
1871
|
}, [session, field, databaseId, renderCount])
|
|
1866
1872
|
|
|
1873
|
+
const addChoice = useCallback((record: DatabaseRecord) => {
|
|
1874
|
+
if (!choicesForDatabase[databaseId]) {
|
|
1875
|
+
choicesForDatabase[databaseId] = {
|
|
1876
|
+
done: false,
|
|
1877
|
+
records: [],
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
choicesForDatabase[databaseId].records!.push(record)
|
|
1881
|
+
}, [choicesForDatabase, databaseId])
|
|
1882
|
+
|
|
1867
1883
|
return {
|
|
1884
|
+
addChoice,
|
|
1868
1885
|
doneLoading: choicesForDatabase[databaseId]?.done ?? false,
|
|
1869
1886
|
choices: [
|
|
1870
1887
|
...choicesForDatabase[databaseId]?.records ?? [],
|
|
@@ -1915,11 +1932,17 @@ const get_other_answers = (_value?: DatabaseSelectResponse[], typing?: string) =
|
|
|
1915
1932
|
return []
|
|
1916
1933
|
}
|
|
1917
1934
|
|
|
1918
|
-
export
|
|
1935
|
+
export interface AddToDatabaseProps {
|
|
1936
|
+
databaseId: string,
|
|
1937
|
+
onAdd: (record: DatabaseRecord) => void
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
export const DatabaseSelectInput = ({ AddToDatabase, field, value: _value, onChange, onDatabaseSelect, responses, size, disabled }: FormInputProps<'Database Select'> & {
|
|
1919
1941
|
responses: FormResponseValue[],
|
|
1942
|
+
AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
|
|
1920
1943
|
}) => {
|
|
1921
1944
|
const [typing, setTyping] = useState('')
|
|
1922
|
-
const { choices, doneLoading } = useDatabaseChoices({
|
|
1945
|
+
const { addChoice, choices, doneLoading } = useDatabaseChoices({
|
|
1923
1946
|
databaseId: field.options?.databaseId,
|
|
1924
1947
|
field,
|
|
1925
1948
|
otherAnswers: get_other_answers(_value, field?.options?.other ? typing : undefined),
|
|
@@ -2010,6 +2033,7 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
|
|
|
2010
2033
|
|
|
2011
2034
|
if (!doneLoading) return <LinearProgress />
|
|
2012
2035
|
return (
|
|
2036
|
+
<>
|
|
2013
2037
|
<Autocomplete id={field.id} freeSolo={false} size={size}
|
|
2014
2038
|
componentsProps={{ popper: { sx: { wordBreak: "break-word" } } } }
|
|
2015
2039
|
options={filteredChoices} multiple={true}
|
|
@@ -2022,7 +2046,11 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
|
|
|
2022
2046
|
disabled={disabled}
|
|
2023
2047
|
onChange={(_, v) => {
|
|
2024
2048
|
if (v.length && onDatabaseSelect) {
|
|
2025
|
-
onDatabaseSelect(
|
|
2049
|
+
onDatabaseSelect(
|
|
2050
|
+
field.options?.radio
|
|
2051
|
+
? [v[v.length - 1]] // if radio, only last selected
|
|
2052
|
+
: v
|
|
2053
|
+
)
|
|
2026
2054
|
}
|
|
2027
2055
|
return onChange(
|
|
2028
2056
|
(
|
|
@@ -2055,6 +2083,11 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
|
|
|
2055
2083
|
))
|
|
2056
2084
|
}
|
|
2057
2085
|
/>
|
|
2086
|
+
|
|
2087
|
+
{AddToDatabase && field?.options?.allowAddToDatabase && (
|
|
2088
|
+
<AddToDatabase databaseId={field.options?.databaseId!} onAdd={addChoice} />
|
|
2089
|
+
)}
|
|
2090
|
+
</>
|
|
2058
2091
|
)
|
|
2059
2092
|
}
|
|
2060
2093
|
|
package/src/displays.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
value_is_loaded,
|
|
9
9
|
useUsers,
|
|
10
10
|
convertHEIC,
|
|
11
|
+
ImageProps,
|
|
11
12
|
} from "./index"
|
|
12
13
|
|
|
13
14
|
import { Avatar, AvatarProps, Styled } from "./mui"
|
|
@@ -72,6 +73,7 @@ export const SecureImage = ({ secureName, placeholder, onImageClick, ...props }
|
|
|
72
73
|
secureName: string,
|
|
73
74
|
alt?: string,
|
|
74
75
|
onImageClick?: (args: { src: string }) => void,
|
|
76
|
+
crossOrigin?: ImageProps['crossOrigin'],
|
|
75
77
|
} & ImageDimensions & Styled) => {
|
|
76
78
|
const loadedImage = useFileForSecureName({ secureName })
|
|
77
79
|
|
package/src/inputs_shared.tsx
CHANGED
|
@@ -9,6 +9,7 @@ import { AgentRecord, AllergyCode, AppointmentBookingPage, AppointmentLocation,
|
|
|
9
9
|
import { Button, Checkbox, Flex, HoverPaper, LoadingButton, LoadingData, ScrollingList, SearchTextInput, Typography, useAgentRecords, useAllergyCodes, useAppointmentBookingPages, useAppointmentLocations, useAutomationTriggers, useCalendarEventTemplates, useCallHoldQueues, useChatRooms, useDatabaseRecords, useDatabases, useDiagnosisCodes, useEnduserCustomTypes, useEnduserOrders, useEndusers, useFaxLogs, useFiles, useFormGroups, useForms, useForums, useJourneys, useManagedContentRecords, useMessageTemplateSnippets, useNotifications, useOrganization, useOrganizations, usePrescriptionRoutes, useResolvedSession, useSession, useSuggestedContacts, useTemplates, useTicketQueues, useTickets, useUsers, useWaitlists, value_is_loaded } from "."
|
|
10
10
|
import { SxProps } from "@mui/material"
|
|
11
11
|
import { AccessPermissions, ListOfStringsWithQualifier } from "@tellescope/types-models"
|
|
12
|
+
import { phoneValidator } from "@tellescope/validation"
|
|
12
13
|
|
|
13
14
|
export type FilterV2 = Record<string, any>
|
|
14
15
|
export type FiltersV2 = Record<string, FilterV2>
|
|
@@ -885,7 +886,22 @@ export const EnduserSearch = (props: Omit<GenericSearchProps<Enduser>, 'filterKe
|
|
|
885
886
|
if (((session.userInfo as any)?.access as AccessPermissions)?.users?.read === ALL_ACCESS && !value_is_loaded(usersLoading)) return null
|
|
886
887
|
return (
|
|
887
888
|
<ModelSearchInput filterKey="endusers" {...props}
|
|
888
|
-
searchAPI={
|
|
889
|
+
searchAPI={async ({ search }) => {
|
|
890
|
+
// handle case of formatted phone number in search bar by parsing to standard phone format and searching explicitly by phone
|
|
891
|
+
// in this case, also search by generic search term in case user is intending to search by something else (e.g. externalId)
|
|
892
|
+
try {
|
|
893
|
+
const phone = phoneValidator.validate()(search.query)
|
|
894
|
+
if (phone) {
|
|
895
|
+
return (
|
|
896
|
+
await Promise.all([
|
|
897
|
+
session.api.endusers.getSome({ filter: { phone }}),
|
|
898
|
+
session.api.endusers.getSome({ search }),
|
|
899
|
+
])
|
|
900
|
+
).flatMap(v => v)
|
|
901
|
+
}
|
|
902
|
+
} catch(err) {}
|
|
903
|
+
return session.api.endusers.getSome({ search })
|
|
904
|
+
}}
|
|
889
905
|
onLoad={addLocalElements}
|
|
890
906
|
attachSearchableFields={t => {
|
|
891
907
|
const users = t.assignedTo?.map(userId => findUser(userId, { batch: true })).filter(u => u) as User[]
|
package/src/layout.tsx
CHANGED
|
@@ -41,9 +41,10 @@ export interface ImageProps extends ImageDimensions, Styled {
|
|
|
41
41
|
src: string,
|
|
42
42
|
alt?: string,
|
|
43
43
|
onClick?: () => void,
|
|
44
|
+
crossOrigin?: 'anonymous' | 'use-credentials',
|
|
44
45
|
}
|
|
45
|
-
export const Image = ({ src, alt, style, onClick, ...props }: ImageProps) => (
|
|
46
|
-
<img src={src} alt={alt} onClick={onClick} style={{ cursor: !!onClick ? 'pointer' : undefined, ...props, ...style }} />
|
|
46
|
+
export const Image = ({ src, alt, style, onClick, crossOrigin, ...props }: ImageProps) => (
|
|
47
|
+
<img crossOrigin={crossOrigin} src={src} alt={alt} onClick={onClick} style={{ cursor: !!onClick ? 'pointer' : undefined, ...props, ...style }} />
|
|
47
48
|
)
|
|
48
49
|
|
|
49
50
|
export interface VideoProps extends Styled {
|
package/src/state.tsx
CHANGED
|
@@ -99,6 +99,7 @@ import {
|
|
|
99
99
|
EnduserEligibilityResult,
|
|
100
100
|
AgentRecord,
|
|
101
101
|
Waitlist,
|
|
102
|
+
AIConversation,
|
|
102
103
|
} from "@tellescope/types-client"
|
|
103
104
|
|
|
104
105
|
import {
|
|
@@ -366,6 +367,7 @@ const integrationLogsSlice = createSliceForList<IntegrationLog, 'integration_log
|
|
|
366
367
|
const enduserEligibilityResultsSlice = createSliceForList<EnduserEligibilityResult, 'enduser_eligibility_results'>('enduser_eligibility_results')
|
|
367
368
|
const agentRecordsSlice = createSliceForList<AgentRecord, 'agent_records'>('agent_records')
|
|
368
369
|
const waitlistsSlice = createSliceForList<Waitlist, 'waitlists'>('waitlists')
|
|
370
|
+
const aiConversationsSlice = createSliceForList<AIConversation, 'ai_conversations'>('ai_conversations')
|
|
369
371
|
|
|
370
372
|
const roleBasedAccessPermissionsSlice = createSliceForList<RoleBasedAccessPermission, 'role_based_access_permissions'>('role_based_access_permissions')
|
|
371
373
|
|
|
@@ -374,6 +376,7 @@ const userLogsSlice = createSliceForList<UserLog, 'user_logs'>('user_logs')
|
|
|
374
376
|
|
|
375
377
|
export const sharedConfig = {
|
|
376
378
|
reducer: {
|
|
379
|
+
ai_conversations: aiConversationsSlice.reducer,
|
|
377
380
|
agent_records: agentRecordsSlice.reducer,
|
|
378
381
|
enduser_eligibility_results: enduserEligibilityResultsSlice.reducer,
|
|
379
382
|
integration_logs: integrationLogsSlice.reducer,
|
|
@@ -1312,6 +1315,25 @@ export const useEnduserEligibilityResults = (options={} as HookOptions<EnduserEl
|
|
|
1312
1315
|
)
|
|
1313
1316
|
}
|
|
1314
1317
|
|
|
1318
|
+
export const useAIConversations = (options={} as HookOptions<AIConversation>) => {
|
|
1319
|
+
const session = useSession()
|
|
1320
|
+
|
|
1321
|
+
return useListStateHook('ai_conversations', useTypedSelector(s => s.ai_conversations), session, aiConversationsSlice,
|
|
1322
|
+
{
|
|
1323
|
+
loadQuery: session.api.ai_conversations.getSome,
|
|
1324
|
+
findOne: session.api.ai_conversations.getOne,
|
|
1325
|
+
findByIds: session.api.ai_conversations.getByIds,
|
|
1326
|
+
addOne: session.api.ai_conversations.createOne,
|
|
1327
|
+
addSome: session.api.ai_conversations.createSome,
|
|
1328
|
+
deleteOne: session.api.ai_conversations.deleteOne,
|
|
1329
|
+
updateOne: session.api.ai_conversations.updateOne,
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
...options,
|
|
1333
|
+
},
|
|
1334
|
+
)
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1315
1337
|
export const useAgentRecords = (options={} as HookOptions<AgentRecord>) => {
|
|
1316
1338
|
const session = useSession()
|
|
1317
1339
|
|