-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
16e1631
commit 1ad84c6
Showing
4 changed files
with
293 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { DATA_CARD_FIELD_TYPES, type DataCardFieldsProps } from '@odigos/ui-components' | ||
import { compareCondition, type Destination, type DestinationYamlProperties, DISPLAY_TITLES, safeJsonParse, SIGNAL_TYPE } from '@odigos/ui-utils' | ||
|
||
const buildMonitorsList = (exportedSignals: Destination['exportedSignals']): string => | ||
Object.keys(exportedSignals) | ||
.filter((key) => exportedSignals[key as SIGNAL_TYPE]) | ||
.join(', ') | ||
|
||
const buildCard = (destination: Destination, yamlFields: DestinationYamlProperties[]) => { | ||
const { exportedSignals, destinationType, fields } = destination | ||
|
||
const arr: DataCardFieldsProps['data'] = [ | ||
{ title: DISPLAY_TITLES.NAME, value: destinationType.displayName }, | ||
{ title: DISPLAY_TITLES.TYPE, value: destinationType.type }, | ||
{ type: DATA_CARD_FIELD_TYPES.MONITORS, title: DISPLAY_TITLES.MONITORS, value: buildMonitorsList(exportedSignals) }, | ||
{ type: DATA_CARD_FIELD_TYPES.DIVIDER, width: '100%' }, | ||
] | ||
|
||
const parsedFields = safeJsonParse<Record<string, string>>(fields, {}) | ||
const sortedParsedFields = | ||
yamlFields.map((field) => ({ key: field.name, value: parsedFields[field.name] ?? null })).filter((item) => item.value !== null) || | ||
Object.entries(parsedFields).map(([key, value]) => ({ key, value })) | ||
|
||
sortedParsedFields.map(({ key, value }) => { | ||
const { displayName, secret, componentProperties, hideFromReadData, customReadDataLabels } = yamlFields.find((field) => field.name === key) || {} | ||
|
||
const shouldHide = !!hideFromReadData?.length | ||
? compareCondition( | ||
hideFromReadData, | ||
yamlFields.map((field) => ({ name: field.name, value: parsedFields[field.name] ?? null })) | ||
) | ||
: false | ||
|
||
if (!shouldHide) { | ||
const { type } = safeJsonParse(componentProperties, { type: '' }) | ||
const isSecret = (secret || type === 'password') && !!value.length ? new Array(10).fill('•').join('') : '' | ||
|
||
if (!!customReadDataLabels?.length) { | ||
customReadDataLabels.forEach(({ condition, ...custom }) => { | ||
if (condition == value) { | ||
arr.push({ | ||
title: custom.title, | ||
value: custom.value, | ||
}) | ||
} | ||
}) | ||
} else { | ||
arr.push({ | ||
title: displayName || key, | ||
value: isSecret || value, | ||
}) | ||
} | ||
} | ||
}) | ||
|
||
return arr | ||
} | ||
|
||
export { buildCard } |
43 changes: 43 additions & 0 deletions
43
src/containers/destination-drawer/destination-drawer.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import React, { useEffect, useState } from 'react' | ||
import { useDrawerStore } from '../../store' | ||
import type { StoryFn } from '@storybook/react' | ||
import { DestinationDrawer, type DestinationDrawerProps } from '.' | ||
import { ENTITY_TYPES, MOCK_DESTINATION_CATEGORIES, MOCK_DESTINATIONS, sleep } from '@odigos/ui-utils' | ||
|
||
export default { | ||
title: 'Containers/DestinationDrawer', | ||
component: DestinationDrawer, | ||
} | ||
|
||
export const Default: StoryFn<DestinationDrawerProps> = (props) => { | ||
const { setDrawerType, setDrawerEntityId } = useDrawerStore() | ||
|
||
useEffect(() => { | ||
setDrawerType(ENTITY_TYPES.DESTINATION) | ||
setDrawerEntityId(MOCK_DESTINATIONS[0].id) | ||
}, []) | ||
|
||
const [testLoading, setTestLoading] = useState(props.testLoading || false) | ||
const [testResult, setTestResult] = useState(props.testResult || undefined) | ||
|
||
return ( | ||
<DestinationDrawer | ||
{...props} | ||
testLoading={testLoading} | ||
testResult={testResult} | ||
testConnection={async () => { | ||
setTestLoading(true) | ||
await sleep(1000) | ||
setTestResult({ succeeded: true }) | ||
setTestLoading(false) | ||
}} | ||
/> | ||
) | ||
} | ||
|
||
Default.args = { | ||
categories: MOCK_DESTINATION_CATEGORIES, | ||
destinations: MOCK_DESTINATIONS, | ||
updateDestination: () => {}, | ||
deleteDestination: () => {}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import React, { type FC, useMemo, useState } from 'react' | ||
import styled from 'styled-components' | ||
import { buildCard } from './build-card' | ||
import { useDrawerStore } from '../../store' | ||
import type { DestinationFormData } from '../../@types' | ||
import { ConditionDetails, DataCard } from '@odigos/ui-components' | ||
import { OverviewDrawer, useDestinationFormData } from '../../helpers' | ||
import { DestinationForm, type DestinationFormProps } from '../destination-form' | ||
import { | ||
CRUD, | ||
type Destination, | ||
type DestinationCategories, | ||
DestinationYamlProperties, | ||
DISPLAY_TITLES, | ||
ENTITY_TYPES, | ||
safeJsonParse, | ||
} from '@odigos/ui-utils' | ||
|
||
interface DestinationDrawerProps { | ||
categories: DestinationCategories | ||
destinations: Destination[] | ||
updateDestination: (id: string, destination: DestinationFormData) => void | ||
deleteDestination: (id: string) => void | ||
testConnection: DestinationFormProps['testConnection'] | ||
testLoading: DestinationFormProps['testLoading'] | ||
testResult: DestinationFormProps['testResult'] | ||
} | ||
|
||
const FormContainer = styled.div` | ||
width: 100%; | ||
height: 100%; | ||
max-height: calc(100vh - 220px); | ||
overflow: overlay; | ||
overflow-y: auto; | ||
` | ||
|
||
const DataContainer = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 12px; | ||
` | ||
|
||
const DestinationDrawer: FC<DestinationDrawerProps> = ({ | ||
categories, | ||
destinations, | ||
updateDestination, | ||
deleteDestination, | ||
testConnection, | ||
testLoading, | ||
testResult, | ||
}) => { | ||
const { drawerType, drawerEntityId, setDrawerEntityId, setDrawerType } = useDrawerStore() | ||
|
||
const isOpen = drawerType !== ENTITY_TYPES.DESTINATION | ||
const onClose = () => { | ||
setDrawerType(null) | ||
setDrawerEntityId(null) | ||
} | ||
|
||
const [isEditing, setIsEditing] = useState(false) | ||
const [isFormDirty, setIsFormDirty] = useState(false) | ||
// const [thisItem, setThisItem] = useState<Destination | undefined>(undefined) | ||
|
||
const { | ||
formData, | ||
formErrors, | ||
handleFormChange, | ||
resetFormData, | ||
validateForm, | ||
loadFormWithDrawerItem, | ||
yamlFields, | ||
setYamlFields, | ||
dynamicFields, | ||
setDynamicFields, | ||
} = useDestinationFormData({ | ||
// preLoadedFields: thisItem?.fields, | ||
// TODO: supportedSignals: thisDestination?.supportedSignals, | ||
// currently, the real "supportedSignals" is being used by "destination" passed as prop to "DestinationFormBody" | ||
}) | ||
|
||
const thisItem = useMemo(() => { | ||
if (isOpen) return null | ||
|
||
const found = destinations?.find((x) => x.id === drawerEntityId) | ||
if (!!found) { | ||
loadFormWithDrawerItem(found) | ||
|
||
const fields: DestinationYamlProperties[] = [] | ||
const parsedCategories: typeof categories = JSON.parse(JSON.stringify(categories)) | ||
|
||
for (const category of parsedCategories) { | ||
const autoFilledFields = safeJsonParse<{ [key: string]: string }>(found.fields, {}) | ||
const idx = category.items.findIndex((item) => item.type === found.destinationType.type) | ||
|
||
if (idx !== -1) { | ||
fields.push( | ||
...category.items[idx].fields.map((field) => ({ | ||
...field, | ||
initialValue: autoFilledFields[field.name], | ||
})) | ||
) | ||
} | ||
} | ||
|
||
setYamlFields(fields) | ||
} | ||
|
||
return found | ||
}, [isOpen, drawerEntityId, destinations]) | ||
|
||
if (!thisItem) return null | ||
|
||
const thisOptionType = categories | ||
.map(({ items }) => items.filter(({ type }) => type === thisItem.destinationType.type)) | ||
.filter((arr) => !!arr.length)?.[0]?.[0] | ||
|
||
const handleEdit = (bool?: boolean) => { | ||
setIsEditing(typeof bool === 'boolean' ? bool : true) | ||
} | ||
|
||
const handleCancel = () => { | ||
setIsEditing(false) | ||
setIsFormDirty(false) | ||
loadFormWithDrawerItem(thisItem) | ||
} | ||
|
||
const handleDelete = () => { | ||
deleteDestination(drawerEntityId as string) | ||
setIsEditing(false) | ||
setIsFormDirty(false) | ||
resetFormData() | ||
// close drawer, all other cases are handled in OverviewDrawer | ||
onClose() | ||
} | ||
|
||
const handleSave = (newTitle: string) => { | ||
if (validateForm({ withAlert: true, alertTitle: CRUD.UPDATE })) { | ||
const title = newTitle !== thisItem.destinationType.displayName ? newTitle : '' | ||
handleFormChange('name', title) | ||
updateDestination(drawerEntityId as string, { ...formData, name: title }) | ||
setIsEditing(false) | ||
setIsFormDirty(false) | ||
} | ||
} | ||
|
||
return ( | ||
<OverviewDrawer | ||
title={thisItem.name || thisItem.destinationType.displayName} | ||
iconSrc={thisItem.destinationType.imageUrl} | ||
isEdit={isEditing} | ||
isFormDirty={isFormDirty} | ||
onEdit={handleEdit} | ||
onSave={handleSave} | ||
onDelete={handleDelete} | ||
onCancel={handleCancel} | ||
> | ||
{isEditing ? ( | ||
<FormContainer> | ||
<DestinationForm | ||
isUpdate | ||
categoryItem={thisOptionType} | ||
formData={formData} | ||
formErrors={formErrors} | ||
handleFormChange={(...params) => { | ||
setIsFormDirty(true) | ||
handleFormChange(...params) | ||
}} | ||
dynamicFields={dynamicFields} | ||
setDynamicFields={(...params) => { | ||
setIsFormDirty(true) | ||
setDynamicFields(...params) | ||
}} | ||
validateForm={validateForm} | ||
testConnection={testConnection} | ||
testLoading={testLoading} | ||
testResult={testResult} | ||
/> | ||
</FormContainer> | ||
) : ( | ||
<DataContainer> | ||
<ConditionDetails conditions={thisItem.conditions || []} /> | ||
<DataCard title={DISPLAY_TITLES.DESTINATION_DETAILS} data={!!thisItem ? buildCard(thisItem, yamlFields) : []} /> | ||
</DataContainer> | ||
)} | ||
</OverviewDrawer> | ||
) | ||
} | ||
|
||
export { DestinationDrawer, type DestinationDrawerProps } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters