erp-platform/ui/src/views/admin/chart/ChartEdit.tsx
2025-09-25 17:40:16 +03:00

1534 lines
58 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Alert,
Button,
Card,
Checkbox,
Dialog,
FormContainer,
FormItem,
Input,
Notification,
Select,
Tabs,
toast,
} from '@/components/ui'
import TabContent from '@/components/ui/Tabs/TabContent'
import TabList from '@/components/ui/Tabs/TabList'
import TabNav from '@/components/ui/Tabs/TabNav'
import { getRoles, getUsers } from '@/services/identity.service'
import {
deleteChartJsonItem,
getChartByCode,
putChartJsonItem,
putCharts,
} from '@/services/chart.service'
import { SelectBoxOption } from '@/shared/types'
import { useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import setNull from '@/utils/setNull'
import { Field, FieldArray, FieldProps, Form, Formik, FormikProps, getIn } from 'formik'
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useParams } from 'react-router-dom'
import { object, string } from 'yup'
import {
chartAnnotationTypeListOptions,
chartArgumentAxisPositionListOptions,
chartArgumentAxisTypeListOptions,
chartBreakStyleLineListOptions,
chartSeriesDashStyleOptions,
chartSeriesSelectionModeOptions,
chartSeriesTypeOptions,
chartTitleWordWrapListOptions,
} from './options'
import { ChartDialogType, ChartOperation } from './types'
import { IdentityRoleDto, IdentityUserDto } from '@/proxy/admin/models'
import {
BreakDto,
ChartAnnotationDto,
ChartEditDto,
ChartPanesDto,
ChartSeriesDto,
ChartValueAxisDto,
} from '@/proxy/charts/models'
import { Container } from '@/components/shared'
import ChartEditDetailsTab from './edit/ChartTabDetails'
import ChartEditDatabaseTab from './edit/ChartTabDatabase'
import ChartEditCommonSettingsTab from './edit/ChartTabCommonSettings'
import ChartEditPermissionsTab from './edit/ChartTabPermissions'
import ChartEditSeriesTab from './edit/ChartTabSeries'
import ChartEditAxisTab from './edit/ChartTabAxis'
import ChartEditPanesTab from './edit/ChartTabPanes'
import ChartEditCrosshairTab from './edit/ChartTabCrosshair'
import ChartTabAnimation from './edit/ChartTabAnimation'
import ChartEditExportTab from './edit/ChartTabExport'
import ChartTabLegend from './edit/ChartTabLegend'
import ChartTabAnnotations from './edit/ChartTabAnnotations'
import ChartEditZoomAndPanTab from './edit/ChartTabZoomAndPan'
import { getDataSources } from '@/proxy/data-source'
import { tooltipFormatListOptions } from '@/shared/options'
import { FaMinus } from 'react-icons/fa'
import { ROUTES_ENUM } from '@/routes/route.constant'
const chartPanesValidationSchema = object().shape({
name: string().required(),
})
const chartSeriesValidationSchema = object().shape({
name: string().required(),
})
const chartAxisValidationSchema = object().shape({
name: string().required(),
title: string().required(),
})
const chartAnnotationsValidationSchema = object().shape({
name: string().required(),
})
const fieldFeedback = (form: FormikProps<BreakDto>, name: string) => {
const error = getIn(form.errors, name)
const touch = getIn(form.touched, name)
return {
errorMessage: error || '',
invalid: typeof touch === 'undefined' ? false : error && touch,
}
}
const chartValidationSchema = object().shape({
cultureName: string().required(),
chartCode: string().required(),
})
export interface DatabaseOperation {
isOpen: ChartDialogType
id: string
operation: ChartOperation
index: number
panesValues?: ChartPanesDto
seriesValues?: ChartSeriesDto
annotationsValues?: ChartAnnotationDto
axisValues?: ChartValueAxisDto
}
const defaultDatabaseOperation: DatabaseOperation = {
isOpen: '',
id: '',
operation: 'select',
index: -1,
}
export interface ConfirmDelete {
isOpen: boolean
id: string
index: number
fieldName: ChartDialogType
}
const defaultConfirmDelete: ConfirmDelete = {
isOpen: false,
id: '',
index: -1,
fieldName: 'pane',
}
function ChartEdit() {
const { chartCode } = useParams()
const { translate } = useLocalization()
const [dataSourceList, setDataSourceList] = useState<SelectBoxOption[]>([])
const languages = useStoreState((state) => state.abpConfig.config?.localization.languages)
const permissions: Record<string, boolean> | undefined = useStoreState(
(state) => state.abpConfig.config?.auth.grantedPolicies,
)
const [chartValues, setChartValues] = useState<ChartEditDto>()
const [langOptions, setLangOptions] = useState<SelectBoxOption[]>([])
const [roleList, setRoleList] = useState<SelectBoxOption[]>([])
const [userList, setUserList] = useState<SelectBoxOption[]>([])
const [permissionOptions, setPermissionOptions] = useState<SelectBoxOption[]>([])
const [confirmDelete, setConfirmDelete] = useState<ConfirmDelete>(defaultConfirmDelete)
const [databaseOperationsModalData, setDatabaseOperationsModalData] =
useState<DatabaseOperation>(defaultDatabaseOperation)
const onSubmit = async (editType: string, values: Partial<ChartEditDto>): Promise<void> => {
try {
await putCharts({
...chartValues,
...values, // sadece güncellenen tab'ın değerleri override edilir
} as ChartEditDto) // chartValues null olamaz çünkü form ancak chartValues yüklendikten sonra render ediliyor
toast.push(
<Notification type="success" duration={2000}>
{`${editType} kaydedildi.`}
</Notification>,
{ placement: 'top-end' },
)
await getChartValues()
} catch (error) {
toast.push(<Notification type="danger">Hata: {String(error)}</Notification>)
}
}
const valueAxisList = () => {
return chartValues?.valueAxisDto.map((key: ChartValueAxisDto) => ({
value: key.name,
label: key.name,
}))
}
const valuePaneList = () => {
return chartValues?.panesDto.map((key: ChartPanesDto) => ({
value: key.name,
label: key.name,
}))
}
const SeriesList = () => {
return chartValues?.seriesDto.map((key: ChartSeriesDto) => ({
value: key.name,
label: key.name,
}))
}
useEffect(() => {
if (languages) {
setLangOptions(
languages.map((lang) => ({
value: lang.cultureName,
label: lang.displayName,
})),
)
}
}, [languages])
useEffect(() => {
if (permissions) {
setPermissionOptions(
Object.keys(permissions).map((key) => {
return {
value: key,
label: key,
}
}),
)
}
}, [permissions])
const getRoleList = async () => {
const response = await getRoles()
if (response.data?.items) {
setRoleList(
response.data.items.map((role: IdentityRoleDto) => ({
value: role.id,
label: role.name,
})),
)
}
}
const getUserList = async () => {
const response = await getUsers()
if (response.data?.items) {
setUserList(
response.data.items.map((user: IdentityUserDto) => ({
value: user.id,
label: user.name,
})),
)
}
}
const getChartValues = async () => {
if (!chartCode) return
const res = await getChartByCode(chartCode)
setNull(res.data)
setChartValues(res.data)
}
const getDataSourceList = async () => {
const response = await getDataSources()
if (response.data?.items) {
setDataSourceList(
response.data.items.map((a) => ({
value: a.code,
label: a.code,
})),
)
}
}
useEffect(() => {
getChartValues()
getRoleList()
getUserList()
getDataSourceList()
}, [chartCode])
return chartValues && roleList && userList && permissionOptions ? (
<Container>
<Helmet
titleTemplate="%s | Sözsoft Kurs Platform"
title={chartCode}
defaultTitle="Sözsoft Kurs Platform"
></Helmet>
<Formik
initialValues={{ ...chartValues }}
validationSchema={chartValidationSchema}
onSubmit={async (values, { resetForm, setSubmitting }) => {
setSubmitting(true)
await putCharts({ ...values })
toast.push(
<Notification type="success" duration={2000}>
{'Chart Bilgileri Kaydedildi.'}
</Notification>,
{
placement: 'top-end',
},
)
setSubmitting(false)
}}
>
{({ touched, errors, resetForm, isSubmitting, values }) => (
<Form>
<FormContainer size="sm">
<div className="lg:flex items-center justify-between mb-4 gap-3">
<div className="mb-4 lg:mb-0">
<h4>
<Link
to={ROUTES_ENUM.protected.admin.chart.replace('::chartCode', chartCode || '')}
>
🔙 {chartCode}
</Link>
</h4>
{chartValues.isTenant && (
<Alert showIcon className="mb-4" type="warning">
Bu bir MULTI TENANT form'dur, veri kaybı olmaması için, sorgularda TENANTID
parametresini kullanmayı unutmayınız.
</Alert>
)}
</div>
</div>
<Tabs defaultValue="details" variant="pill">
<TabList className="flex-wrap border-b mb-2 bg-slate-50">
<TabNav value="details">Details</TabNav>
<TabNav value="database">Database</TabNav>
<TabNav value="permissions">Permissions</TabNav>
<TabNav value="commonSettings">Common</TabNav>
<TabNav value="series">Series</TabNav>
<TabNav value="axis">Axis</TabNav>
<TabNav value="panes">Panes</TabNav>
<TabNav value="animationsOptions">Animations</TabNav>
<TabNav value="crosshairOptions">Crosshair</TabNav>
<TabNav value="exportSettings">Export</TabNav>
<TabNav value="legendSettings">Legend</TabNav>
<TabNav value="zoomAndPanSettings">Zoom & Pan</TabNav>
<TabNav value="annotations">Annotations</TabNav>
</TabList>
<TabContent value="details">
<ChartEditDetailsTab
values={values}
errors={errors}
touched={touched}
langOptions={langOptions}
roleList={roleList}
userList={userList}
/>
</TabContent>
<TabContent value="database">
<ChartEditDatabaseTab
values={values}
errors={errors}
touched={touched}
dataSourceList={dataSourceList}
/>
</TabContent>
<TabContent value="commonSettings">
<ChartEditCommonSettingsTab values={values} errors={errors} touched={touched} />
</TabContent>
<TabContent value="permissions">
<ChartEditPermissionsTab
values={values}
errors={errors}
touched={touched}
permissionOptions={permissionOptions}
/>
</TabContent>
<TabContent value="series">
<ChartEditSeriesTab
values={values}
errors={errors}
touched={touched}
chartValues={chartValues}
setDatabaseOperationsModalData={setDatabaseOperationsModalData}
setConfirmDelete={setConfirmDelete}
valueAxisList={valueAxisList}
valuePaneList={valuePaneList}
/>
</TabContent>
<TabContent value="axis">
<ChartEditAxisTab
values={values}
errors={errors}
touched={touched}
chartValues={chartValues}
setDatabaseOperationsModalData={setDatabaseOperationsModalData}
setConfirmDelete={setConfirmDelete}
/>
</TabContent>
<TabContent value="panes">
<ChartEditPanesTab
values={values}
errors={errors}
touched={touched}
chartValues={chartValues}
setDatabaseOperationsModalData={setDatabaseOperationsModalData}
setConfirmDelete={setConfirmDelete}
/>
</TabContent>
<TabContent value="animationsOptions">
<ChartTabAnimation values={values} errors={errors} touched={touched} />
</TabContent>
<TabContent value="crosshairOptions">
<ChartEditCrosshairTab values={values} errors={errors} touched={touched} />
</TabContent>
<TabContent value="exportSettings">
<ChartEditExportTab errors={errors} touched={touched} />
</TabContent>
<TabContent value="legendSettings">
<ChartTabLegend values={values} errors={errors} touched={touched} />
</TabContent>
<TabContent value="zoomAndPanSettings">
<ChartEditZoomAndPanTab values={values} errors={errors} touched={touched} />
</TabContent>
<TabContent value="annotations">
<ChartTabAnnotations
values={values}
errors={errors}
touched={touched}
chartValues={chartValues}
setDatabaseOperationsModalData={setDatabaseOperationsModalData}
setConfirmDelete={setConfirmDelete}
SeriesList={SeriesList}
/>
</TabContent>
</Tabs>
<div className="mt-4">
<Button block variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</FormContainer>
</Form>
)}
</Formik>
<Dialog
id="paneOperation"
contentClassName="pb-2 px-2"
isOpen={databaseOperationsModalData.isOpen == 'pane'}
onClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
onRequestClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
>
<h5 className="mb-4">{databaseOperationsModalData.index === -1 ? 'Add' : 'Update'}</h5>
<Formik
initialValues={
databaseOperationsModalData.panesValues ?? {
id: '',
backgroundColor: '',
height: 250,
name: '',
}
}
validationSchema={chartPanesValidationSchema}
onSubmit={async (values, { setSubmitting }) => {
setSubmitting(true)
await putChartJsonItem({
id: chartValues.id,
chartCode: chartValues.chartCode,
index: databaseOperationsModalData.index,
fieldName: 'pane',
itemPane: { ...values },
})
toast.push(
<Notification type="success" duration={2000}>
{databaseOperationsModalData.index === -1
? 'Kayıt eklendi.'
: 'Kayıt Değiştirildi.'}
</Notification>,
{
placement: 'top-end',
},
)
getChartValues()
setSubmitting(false)
setDatabaseOperationsModalData(defaultDatabaseOperation)
}}
>
{({ touched, errors, resetForm, isSubmitting, values }) => (
<Form>
<FormContainer>
<div className="max-h-96 overflow-y-auto p-2">
<FormItem
label="Name"
invalid={errors.name && touched.name}
errorMessage={errors.name}
>
<Field type="text" name="name" component={Input} />
</FormItem>
<FormItem
label="Background Color"
invalid={errors.backgroundColor && touched.backgroundColor}
errorMessage={errors.backgroundColor}
>
<Field type="text" name="backgroundColor" component={Input} />
</FormItem>
<FormItem
label="Height"
invalid={errors.height && touched.height}
errorMessage={errors.height}
>
<Field type="number" name="height" component={Input} />
</FormItem>
</div>
<div className="text-right mt-4">
<Button block variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</FormContainer>
</Form>
)}
</Formik>
</Dialog>
<Dialog
id="seriesOperation"
width={900}
contentClassName="pb-2 px-2"
isOpen={databaseOperationsModalData.isOpen == 'serie'}
onClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
onRequestClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
>
<h5 className="mb-4">{databaseOperationsModalData.index === -1 ? 'Add' : 'Update'}</h5>
<Formik
initialValues={
databaseOperationsModalData.seriesValues ?? {
id: '',
argumentField: '',
axis: '',
barOverlapGroup: '',
barPadding: 0,
barWidth: 0,
color: '',
cornerRadius: 0,
dashStyle: 'solid',
ignoreEmptyPoints: false,
name: '',
pane: '',
rangeValue1Field: '',
rangeValue2Field: '',
selectionMode: 'none',
showInLegend: true,
type: 'line',
valueField: '',
visible: true,
width: 2,
label: {
visible: false,
backgroundColor: '#f05b41',
customizeText: '',
format: '',
font: null,
},
}
}
validationSchema={chartSeriesValidationSchema}
onSubmit={async (values, { resetForm, setSubmitting }) => {
setSubmitting(true)
await putChartJsonItem({
chartCode: chartValues.chartCode,
id: chartValues.id,
index: databaseOperationsModalData.index,
fieldName: 'serie',
itemSerie: { ...values } as ChartSeriesDto,
})
toast.push(
<Notification type="success" duration={2000}>
{databaseOperationsModalData.index === -1
? 'Kayıt eklendi.'
: 'Kayıt Değiştirildi.'}
</Notification>,
{
placement: 'top-end',
},
)
getChartValues()
setSubmitting(false)
setDatabaseOperationsModalData(defaultDatabaseOperation)
}}
>
{({ touched, errors, resetForm, isSubmitting, values }) => (
<Form>
<FormContainer>
<div className="max-h-96 overflow-y-auto p-2">
<FormItem
label="Visible"
invalid={errors.visible && touched.visible}
errorMessage={errors.visible}
>
<Field name="visible" component={Checkbox} />
</FormItem>
<FormItem
label="Show In Legend"
invalid={errors.showInLegend && touched.showInLegend}
errorMessage={errors.showInLegend}
>
<Field name="showInLegend" component={Checkbox} />
</FormItem>
<FormItem
label="Ignore Empty Points"
invalid={errors.ignoreEmptyPoints && touched.ignoreEmptyPoints}
errorMessage={errors.ignoreEmptyPoints}
>
<Field name="ignoreEmptyPoints" component={Checkbox} />
</FormItem>
<FormItem
label="Type"
invalid={errors.type && touched.type}
errorMessage={errors.type}
>
<Field type="text" name="type">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartSeriesTypeOptions}
isClearable={true}
value={chartSeriesTypeOptions.filter(
(option) => option.value === values.type,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Name"
invalid={errors.name && touched.name}
errorMessage={errors.name}
>
<Field type="text" name="name" component={Input} />
</FormItem>
<FormItem
label="Argument Field"
invalid={errors.argumentField && touched.argumentField}
errorMessage={errors.argumentField}
>
<Field type="text" name="argumentField" component={Input} />
</FormItem>
<FormItem
label="Value Field"
invalid={errors.valueField && touched.valueField}
errorMessage={errors.valueField}
>
<Field type="text" name="valueField" component={Input} />
</FormItem>
<FormItem
label="Axis"
invalid={errors.axis && touched.axis}
errorMessage={errors.axis}
>
<Field type="text" name="axis">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={valueAxisList()}
isClearable={true}
value={valueAxisList()?.find((option) => option.value === values.axis)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Pane"
invalid={errors.pane && touched.pane}
errorMessage={errors.pane}
>
<Field type="text" name="pane">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={valuePaneList()}
isClearable={true}
value={valuePaneList()?.find((option) => option.value === values.pane)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Type"
invalid={errors.dashStyle && touched.dashStyle}
errorMessage={errors.dashStyle}
>
<Field type="text" name="dashStyle">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartSeriesDashStyleOptions}
isClearable={true}
value={chartSeriesDashStyleOptions.filter(
(option) => option.value === values.dashStyle,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Color"
invalid={errors.color && touched.color}
errorMessage={errors.color}
>
<Field type="text" name="color" component={Input} />
</FormItem>
<FormItem
label="Selection Mode"
invalid={errors.selectionMode && touched.selectionMode}
errorMessage={errors.selectionMode}
>
<Field type="text" name="selectionMode">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartSeriesSelectionModeOptions}
isClearable={true}
value={chartSeriesSelectionModeOptions.filter(
(option) => option.value === values.selectionMode,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Width"
invalid={errors.width && touched.width}
errorMessage={errors.width}
>
<Field type="number" name="width" component={Input} />
</FormItem>
<FormItem
label="Corner Radius"
invalid={errors.cornerRadius && touched.cornerRadius}
errorMessage={errors.cornerRadius}
>
<Field type="number" name="cornerRadius" component={Input} />
</FormItem>
<Card className="my-2" header="Label">
<FormItem label="Label Visible">
<Field name="label.visible" component={Checkbox} />
</FormItem>
<FormItem
label="Background Color"
invalid={errors.label?.backgroundColor && touched.label?.backgroundColor}
errorMessage={errors.label?.backgroundColor}
>
<Field type="text" name="label.backgroundColor" component={Input} />
</FormItem>
<FormItem
label="Format"
invalid={errors.label?.format && touched.label?.format}
errorMessage={errors.label?.format}
>
<Field type="text" name="label.format">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={tooltipFormatListOptions}
isClearable={true}
value={tooltipFormatListOptions.filter(
(option) => option.value === values.label.format,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Customize Text"
invalid={errors.label?.customizeText && touched.label?.customizeText}
errorMessage={errors.label?.customizeText}
>
<Field type="text" name="label.customizeText" component={Input} />
</FormItem>
</Card>
</div>
<div className="text-right mt-4">
<Button block variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</FormContainer>
</Form>
)}
</Formik>
</Dialog>
<Dialog
id="axisOperation"
width={900}
contentClassName="pb-2 px-2"
isOpen={databaseOperationsModalData.isOpen == 'axis'}
onClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
onRequestClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
>
<h5 className="mb-4">{databaseOperationsModalData.index === -1 ? 'Add' : 'Update'}</h5>
<Formik
initialValues={
databaseOperationsModalData.axisValues ?? {
grid: {
color: '#d3d3d3',
visible: false,
width: 1,
},
name: '',
position: '',
title: '',
valueType: '',
visible: false,
width: 0,
breaks: [
{
startValue: 0,
endValue: 0,
},
],
breakStyle: {
color: '#ababab',
line: 'waved',
width: 5,
},
type: '',
autoBreaksEnabled: false,
maxAutoBreakCount: 0,
}
}
validationSchema={chartAxisValidationSchema}
onSubmit={async (values, { setSubmitting }) => {
setSubmitting(true)
await putChartJsonItem({
chartCode: chartValues.chartCode,
id: chartValues.id,
index: databaseOperationsModalData.index,
fieldName: 'axis',
itemAxis: { ...values },
})
toast.push(
<Notification type="success" duration={2000}>
{databaseOperationsModalData.index === -1
? 'Kayıt eklendi.'
: 'Kayıt Değiştirildi.'}
</Notification>,
{
placement: 'top-end',
},
)
getChartValues()
setSubmitting(false)
setDatabaseOperationsModalData(defaultDatabaseOperation)
}}
>
{({ touched, errors, resetForm, isSubmitting, values }) => {
const breaks = values.breaks
return (
<Form>
<FormContainer>
<div className="max-h-96 overflow-y-auto p-2">
<FormItem
label="Visible"
invalid={errors.visible && touched.visible}
errorMessage={errors.visible}
>
<Field name="visible" component={Checkbox} />
</FormItem>
<FormItem
label="Value Type"
invalid={errors.valueType && touched.valueType}
errorMessage={errors.valueType}
>
<Field type="text" name="valueType">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartArgumentAxisTypeListOptions}
isClearable={true}
value={chartArgumentAxisTypeListOptions.filter(
(option) => option.value === values.valueType,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Type"
invalid={errors.type && touched.type}
errorMessage={errors.type}
>
<Field type="text" name="type">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartArgumentAxisTypeListOptions}
isClearable={true}
value={chartArgumentAxisTypeListOptions.filter(
(option) => option.value === values.type,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Position"
invalid={errors.position && touched.position}
errorMessage={errors.position}
>
<Field type="text" name="position">
{({ field, form }: FieldProps<IdentityRoleDto>) => (
<Select
field={field}
form={form}
options={chartArgumentAxisPositionListOptions}
isClearable={true}
value={chartArgumentAxisPositionListOptions.filter(
(option) => option.value === values.position,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Name"
invalid={errors.name && touched.name}
errorMessage={errors.name}
>
<Field type="text" name="name" component={Input} />
</FormItem>
<FormItem
label="Title"
invalid={errors.title && touched.title}
errorMessage={errors.title}
>
<Field type="text" name="title" component={Input} />
</FormItem>
<FormItem
label="Width"
invalid={errors.width && touched.width}
errorMessage={errors.width}
>
<Field type="number" name="width" component={Input} />
</FormItem>
<Tabs defaultValue="grid" variant="pill">
<TabList>
<TabNav value="grid">Grid</TabNav>
<TabNav value="breakStyle">Break Style</TabNav>
<TabNav value="breaks">Breaks</TabNav>
</TabList>
<div className="pt-4">
<TabContent value="grid">
<FormItem
label="Visible"
invalid={errors.grid?.visible && touched.grid?.visible}
errorMessage={errors.grid?.visible}
>
<Field name="grid.visible" component={Checkbox} />
</FormItem>
<FormItem
label="Color"
invalid={errors.grid?.color && touched.grid?.color}
errorMessage={errors.grid?.color}
>
<Field type="text" name="grid.color" component={Input} />
</FormItem>
<FormItem
label="Width"
invalid={errors.grid?.width && touched.grid?.width}
errorMessage={errors.grid?.width}
>
<Field type="number" name="grid.width" component={Input} />
</FormItem>
</TabContent>
<TabContent value="breakStyle">
<FormItem
label="Color"
invalid={errors.breakStyle?.color && touched.breakStyle?.color}
errorMessage={errors.breakStyle?.color}
>
<Field type="text" name="breakStyle.color" component={Input} />
</FormItem>
<FormItem
label="Width"
invalid={errors.breakStyle?.width && touched.breakStyle?.width}
errorMessage={errors.breakStyle?.width}
>
<Field type="number" name="breakStyle.width" component={Input} />
</FormItem>
<FormItem
label="Line"
invalid={errors.breakStyle?.line && touched.breakStyle?.line}
errorMessage={errors.breakStyle?.line}
>
<Field type="text" name="breakStyle.line">
{({ field, form }: FieldProps<IdentityRoleDto>) => (
<Select
field={field}
form={form}
options={chartBreakStyleLineListOptions}
isClearable={true}
value={chartBreakStyleLineListOptions.filter(
(option) => option.value === values.breakStyle.line,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/>
)}
</Field>
</FormItem>
</TabContent>
<TabContent value="breaks">
<FieldArray name="breaks">
{({ form, remove, push }) => (
<div>
{breaks && breaks.length > 0
? breaks.map((_, index) => {
const startValueFeedBack = fieldFeedback(
form,
`breaks[${index}].startValue`,
)
const endValueFeedBack = fieldFeedback(
form,
`breaks[${index}].endValue`,
)
return (
<div key={index}>
<FormItem
layout="inline"
label="Start Value"
invalid={startValueFeedBack.invalid}
errorMessage={startValueFeedBack.errorMessage}
>
<Field
invalid={startValueFeedBack.invalid}
name={`breaks[${index}].startValue`}
type="number"
component={Input}
/>
</FormItem>
<FormItem
layout="inline"
label="End Value"
invalid={endValueFeedBack.invalid}
errorMessage={endValueFeedBack.errorMessage}
>
<Field
invalid={endValueFeedBack.invalid}
name={`breaks[${index}].endValue`}
type="number"
component={Input}
/>
</FormItem>
<Button
shape="circle"
type="button"
size="sm"
icon={<FaMinus />}
onClick={() => remove(index)}
/>
</div>
)
})
: null}
<div>
<Button
type="button"
className="ltr:mr-2 rtl:ml-2"
onClick={() => {
push({
startValue: 0,
endValue: 0,
})
}}
>
Add Break
</Button>
</div>
</div>
)}
</FieldArray>
</TabContent>
</div>
</Tabs>
</div>
<div className="text-right mt-4">
<Button block variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</FormContainer>
</Form>
)
}}
</Formik>
</Dialog>
<Dialog
id="annotationOperation"
width={900}
contentClassName="pb-2 px-2"
isOpen={databaseOperationsModalData.isOpen == 'annotation'}
onClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
onRequestClose={() => setDatabaseOperationsModalData(defaultDatabaseOperation)}
>
<h5 className="mb-4">{databaseOperationsModalData.index === -1 ? 'Add' : 'Update'}</h5>
<Formik
initialValues={
databaseOperationsModalData.annotationsValues ?? {
argument: '',
border: {
color: '#d3d3d3',
cornerRadius: 0,
dashStyle: 'solid',
visible: false,
width: 1,
},
color: '',
description: '',
font: {
color: '#FFFFFF',
family: '"Segoe UI", "Helvetica Neue", "Trebuchet MS", Verdana, sans-serif',
size: 12,
weight: 400,
},
height: 0,
image: '',
name: '',
offsetX: 0,
offsetY: 0,
paddingLeftRight: 0,
paddingTopBottom: 0,
series: '',
text: '',
tooltipEnabled: false,
type: '',
value: '',
width: 0,
wordWrap: '',
x: 0,
y: 0,
}
}
validationSchema={chartAnnotationsValidationSchema}
onSubmit={async (values, { resetForm, setSubmitting }) => {
setSubmitting(true)
await putChartJsonItem({
chartCode: chartValues.chartCode,
id: chartValues.id,
index: databaseOperationsModalData.index,
fieldName: 'annotation',
itemAnnotation: { ...values },
})
toast.push(
<Notification type="success" duration={2000}>
{databaseOperationsModalData.index === -1
? 'Kayıt eklendi.'
: 'Kayıt Değiştirildi.'}
</Notification>,
{
placement: 'top-end',
},
)
getChartValues()
setSubmitting(false)
setDatabaseOperationsModalData(defaultDatabaseOperation)
}}
>
{({ touched, errors, resetForm, isSubmitting, values }) => (
<Form>
<FormContainer>
<div className="max-h-96 overflow-y-auto p-2">
<Tabs defaultValue="annotations_general">
<TabList>
<TabNav value="annotations_general">General</TabNav>
<TabNav value="annotations_border">Border</TabNav>
</TabList>
<TabContent value="annotations_general">
<FormItem
label="Tooltip Enabled"
invalid={errors.tooltipEnabled && touched.tooltipEnabled}
errorMessage={errors.tooltipEnabled}
>
<Field name="tooltipEnabled" component={Checkbox} />
</FormItem>
<FormItem
label="Type"
invalid={errors.type && touched.type}
errorMessage={errors.type}
>
<Field type="text" name="type">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartAnnotationTypeListOptions}
isClearable={true}
value={chartAnnotationTypeListOptions.filter(
(option) => option.value === values.type,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Series"
invalid={errors.series && touched.series}
errorMessage={errors.series}
>
<Field type="text" name="type">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={SeriesList()}
isClearable={true}
value={SeriesList()?.find((option) => option.value === values.series)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Name"
invalid={errors.name && touched.name}
errorMessage={errors.name}
>
<Field type="text" name="name" component={Input} />
</FormItem>
<FormItem
label="Text"
invalid={errors.text && touched.text}
errorMessage={errors.text}
>
<Field type="text" name="text" component={Input} />
</FormItem>
<FormItem
label="Value"
invalid={errors.value && touched.value}
errorMessage={errors.value}
>
<Field type="text" name="value" component={Input} />
</FormItem>
<FormItem
label="Argument"
invalid={errors.argument && touched.argument}
errorMessage={errors.argument}
>
<Field name="argument" component={Input} />
</FormItem>
<FormItem
label="Color"
invalid={errors.color && touched.color}
errorMessage={errors.color}
>
<Field type="text" name="color" component={Input} />
</FormItem>
<FormItem
label="Word Wrap"
invalid={errors.wordWrap && touched.wordWrap}
errorMessage={errors.wordWrap}
>
<Field type="text" name="wordWrap">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartTitleWordWrapListOptions}
isClearable={true}
value={chartTitleWordWrapListOptions.filter(
(option) => option.value === values.wordWrap,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Description"
invalid={errors.description && touched.description}
errorMessage={errors.description}
>
<Field type="text" name="description" component={Input} />
</FormItem>
<FormItem
label="Image"
invalid={errors.image && touched.image}
errorMessage={errors.image}
>
<Field type="text" name="image" component={Input} />
</FormItem>
<FormItem
label="Width"
invalid={errors.width && touched.width}
errorMessage={errors.width}
>
<Field type="number" name="width" component={Input} />
</FormItem>
<FormItem
label="Height"
invalid={errors.height && touched.height}
errorMessage={errors.height}
>
<Field type="number" name="height" component={Input} />
</FormItem>
<FormItem
label="Padding Left/Right"
invalid={errors.paddingLeftRight && touched.paddingLeftRight}
errorMessage={errors.paddingLeftRight}
>
<Field type="number" name="paddingLeftRight" component={Input} />
</FormItem>
<FormItem
label="Padding Top/Bottom"
invalid={errors.paddingTopBottom && touched.paddingTopBottom}
errorMessage={errors.paddingTopBottom}
>
<Field type="number" name="paddingTopBottom" component={Input} />
</FormItem>
<FormItem label="X" invalid={errors.x && touched.x} errorMessage={errors.x}>
<Field type="number" name="x" component={Input} />
</FormItem>
<FormItem label="Y" invalid={errors.y && touched.y} errorMessage={errors.y}>
<Field type="number" name="y" component={Input} />
</FormItem>
<FormItem
label="OffsetX"
invalid={errors.offsetX && touched.offsetX}
errorMessage={errors.offsetX}
>
<Field type="number" name="offsetX" component={Input} />
</FormItem>
<FormItem
label="OffsetY"
invalid={errors.offsetY && touched.offsetY}
errorMessage={errors.offsetY}
>
<Field type="number" name="offsetY" component={Input} />
</FormItem>
</TabContent>
<TabContent value="annotations_border">
<FormItem
label="Visible"
invalid={errors.border?.visible && touched.border?.visible}
errorMessage={errors.border?.visible}
>
<Field name="border.visible" component={Checkbox} />
</FormItem>
<FormItem
label="Color"
invalid={errors.border?.color && touched.border?.color}
errorMessage={errors.border?.color}
>
<Field type="text" name="border.color" component={Input} />
</FormItem>
<FormItem
label="Dash Style"
invalid={errors.border?.dashStyle && touched.border?.dashStyle}
errorMessage={errors.border?.dashStyle}
>
<Field type="text" name="border.dashStyle">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={chartSeriesDashStyleOptions}
isClearable={true}
value={chartSeriesDashStyleOptions.filter(
(option) => option.value === values.border.dashStyle,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Width"
invalid={errors.border?.width && touched.border?.width}
errorMessage={errors.border?.width}
>
<Field type="number" name="border.width" component={Input} />
</FormItem>
</TabContent>
</Tabs>
</div>
<div className="text-right mt-4">
<Button block variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</FormContainer>
</Form>
)}
</Formik>
</Dialog>
<Dialog
id="confirmDelete"
isOpen={confirmDelete.isOpen}
onClose={() => setConfirmDelete(defaultConfirmDelete)}
onRequestClose={() => setConfirmDelete(defaultConfirmDelete)}
>
<h5 className="mb-4">Delete</h5>
<p>Silmek istediğinize emin misiniz?</p>
<div className="text-right mt-6">
<Button
className="ltr:mr-2 rtl:ml-2"
variant="plain"
onClick={() => {
setConfirmDelete(defaultConfirmDelete)
}}
>
Cancel
</Button>
<Button
variant="solid"
onClick={async () => {
if (chartCode == null) return
await deleteChartJsonItem(
confirmDelete.id,
chartCode,
confirmDelete.index,
confirmDelete.fieldName,
)
toast.push(
<Notification type="success" duration={2000}>
{translate('::ListForms.KayitSilindi')}
</Notification>,
{
placement: 'top-end',
},
)
getChartValues()
setConfirmDelete(defaultConfirmDelete)
}}
>
Delete
</Button>
</div>
</Dialog>
</Container>
) : (
<></>
)
}
export default ChartEdit