Skip to content
45 changes: 45 additions & 0 deletions src/pages/analyticsTableHooks/Edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useQuery } from '@tanstack/react-query'
import React from 'react'
import { useParams } from 'react-router-dom'
import { DefaultEditFormContents, FormBase } from '../../components'
import { SECTIONS_MAP, useOnSubmitEdit } from '../../lib'
import { useBoundResourceQueryFn } from '../../lib/query/useBoundQueryFn'
import { AnalyticsTableHookFormFields } from './form/AnalyticsTableHookFormFields'
import {
AnalyticsTableHookFormValues,
validate,
} from './form/analyticsTableHookSchema'
import { fieldFilters } from './form/fieldFilters'

export const Component = () => {
const modelId = useParams().id as string
const section = SECTIONS_MAP.analyticsTableHook
const queryFn = useBoundResourceQueryFn()

const query = {
resource: 'analyticsTableHooks',
id: modelId,
params: {
fields: fieldFilters.concat(),
},
}

const analyticsTableHookQuery = useQuery({
queryKey: [query],
queryFn: queryFn<AnalyticsTableHookFormValues>,
})
const initialValues = analyticsTableHookQuery.data

return (
<FormBase
onSubmit={useOnSubmitEdit({ section, modelId })}
initialValues={initialValues}
validate={validate}
includeAttributes={false}
>
<DefaultEditFormContents section={section}>
<AnalyticsTableHookFormFields />
</DefaultEditFormContents>
</FormBase>
)
}
23 changes: 23 additions & 0 deletions src/pages/analyticsTableHooks/New.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react'
import { FormBase } from '../../components'
import { DefaultNewFormContents } from '../../components/form/DefaultFormContents'
import { SECTIONS_MAP, useOnSubmitNew } from '../../lib'
import { AnalyticsTableHookFormFields } from './form/AnalyticsTableHookFormFields'
import { initialValues, validate } from './form/analyticsTableHookSchema'

const section = SECTIONS_MAP.analyticsTableHook

export const Component = () => {
return (
<FormBase
onSubmit={useOnSubmitNew({ section })}
initialValues={initialValues}
validate={validate}
includeAttributes={false}
>
<DefaultNewFormContents section={section}>
<AnalyticsTableHookFormFields />
</DefaultNewFormContents>
</FormBase>
)
}
141 changes: 141 additions & 0 deletions src/pages/analyticsTableHooks/form/AnalyticsTableHookFormFields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import i18n from '@dhis2/d2-i18n'
import { RadioFieldFF, SingleSelectFieldFF, TextAreaFieldFF } from '@dhis2/ui'
import React from 'react'
import { Field, useField } from 'react-final-form'
import {
HorizontalFieldGroup,
NameField,
CodeField,
StandardFormField,
StandardFormSection,
StandardFormSectionDescription,
StandardFormSectionTitle,
} from '../../../components'
import { getConstantTranslation, SECTIONS_MAP, useSchema } from '../../../lib'
import { AnalyticsTableHook } from '../../../types/generated'

const section = SECTIONS_MAP.analyticsTableHook

const phaseOptions = [
{
value: AnalyticsTableHook.phase.RESOURCE_TABLE_POPULATED,
label: i18n.t('Resource tables'),
},
{
value: AnalyticsTableHook.phase.ANALYTICS_TABLE_POPULATED,
label: i18n.t('Analytics tables'),
},
]

export const AnalyticsTableHookFormFields = () => {
const schema = useSchema(section.name)
const { input: phaseInput } = useField<string | undefined>('phase', {
subscription: { value: true },
})
const selectedPhase = phaseInput.value

const resourceTableOptions =
schema?.properties.resourceTableType?.constants?.map((constant) => ({
value: constant,
label: getConstantTranslation(constant),
})) ?? []

const analyticsTableOptions =
schema?.properties.analyticsTableType?.constants?.map((constant) => ({
value: constant,
label: getConstantTranslation(constant),
})) ?? []

const showResourceTableField =
selectedPhase === AnalyticsTableHook.phase.RESOURCE_TABLE_POPULATED
const showAnalyticsTableField =
selectedPhase === AnalyticsTableHook.phase.ANALYTICS_TABLE_POPULATED

return (
<>
<StandardFormSection>
<StandardFormSectionTitle>
{i18n.t('Basic information')}
</StandardFormSectionTitle>
<StandardFormSectionDescription>
{i18n.t(
'Set up the basic information for this analytics table hook.'
)}
</StandardFormSectionDescription>
<StandardFormField>
<NameField schemaSection={section} />
</StandardFormField>
<StandardFormField>
<CodeField schemaSection={section} />
</StandardFormField>
<StandardFormField>
<HorizontalFieldGroup
label={i18n.t('Phase')}
required
dataTest="formfields-phase"
>
{phaseOptions.map((option) => (
<Field<string | undefined>
key={option.value}
name="phase"
component={RadioFieldFF}
label={option.label}
type="radio"
value={option.value}
/>
))}
</HorizontalFieldGroup>
</StandardFormField>

{showResourceTableField ? (
<StandardFormField>
<Field
component={SingleSelectFieldFF}
name="resourceTableType"
label={i18n.t('Which resource table')}
options={resourceTableOptions}
required
clearable
inputWidth="400px"
dataTest="formfields-resourceTableType"
/>
</StandardFormField>
) : null}

{showAnalyticsTableField ? (
<StandardFormField>
<Field
component={SingleSelectFieldFF}
name="analyticsTableType"
label={i18n.t('Which analytics table')}
options={analyticsTableOptions}
required
clearable
inputWidth="400px"
dataTest="formfields-analyticsTableType"
/>
</StandardFormField>
) : null}
</StandardFormSection>

<StandardFormSection>
<StandardFormSectionTitle>
{i18n.t('Advanced')}
</StandardFormSectionTitle>
<StandardFormSectionDescription>
{i18n.t('Configure the SQL that should run for this hook.')}
</StandardFormSectionDescription>
<StandardFormField>
<Field
component={TextAreaFieldFF}
name="sql"
label={i18n.t('SQL')}
required
inputWidth="400px"
dataTest="formfields-sql"
/>
</StandardFormField>
</StandardFormSection>
</>
)
}
68 changes: 58 additions & 10 deletions src/pages/analyticsTableHooks/form/analyticsTableHookSchema.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,68 @@
import { z } from 'zod'
import { modelFormSchemas } from '../../../lib'
import { AnalyticsTableHook } from '../../../types/generated'
import {
createFormValidate,
getDefaultsOld,
modelFormSchemas,
} from '../../../lib'
import {
AnalyticsTableHook,
PickWithFieldFilters,
} from '../../../types/generated'
import { fieldFilters } from './fieldFilters'

const { withDefaultListColumns } = modelFormSchemas
const { withDefaultListColumns, identifiable } = modelFormSchemas

const analyticsTableHookBaseSchema = z.object({
name: z.string(),
code: z.string().optional(),
sql: z.string().optional(),
analyticsTableType: z.nativeEnum(AnalyticsTableHook.analyticsTableType),
name: z.string().trim().min(1),
code: z.string().trim().optional(),
sql: z.string().trim().min(1),
analyticsTableType: z
.nativeEnum(AnalyticsTableHook.analyticsTableType)
.optional(),
phase: z.nativeEnum(AnalyticsTableHook.phase),
resourceTableType: z
.nativeEnum(AnalyticsTableHook.resourceTableType)
.optional(),
})

export const analyticsTableHookListSchema = analyticsTableHookBaseSchema.merge(
withDefaultListColumns
)
export const analyticsTableHookFormSchema = identifiable
.merge(analyticsTableHookBaseSchema)
.superRefine((value, context) => {
if (
value.phase === AnalyticsTableHook.phase.RESOURCE_TABLE_POPULATED &&
!value.resourceTableType
) {
context.addIssue({
code: z.ZodIssueCode.custom,
path: ['resourceTableType'],
message: 'Required',
})
}
if (
value.phase ===
AnalyticsTableHook.phase.ANALYTICS_TABLE_POPULATED &&
!value.analyticsTableType
) {
context.addIssue({
code: z.ZodIssueCode.custom,
path: ['analyticsTableType'],
message: 'Required',
})
}
})

export const analyticsTableHookListSchema = analyticsTableHookBaseSchema
.partial({
sql: true,
analyticsTableType: true,
resourceTableType: true,
})
.merge(withDefaultListColumns)

export const initialValues = getDefaultsOld(analyticsTableHookFormSchema)
export const validate = createFormValidate(analyticsTableHookFormSchema)

export type AnalyticsTableHookFormValues = PickWithFieldFilters<
AnalyticsTableHook,
typeof fieldFilters
>
11 changes: 11 additions & 0 deletions src/pages/analyticsTableHooks/form/fieldFilters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DEFAULT_FIELD_FILTERS } from '../../../lib'

export const fieldFilters = [
...DEFAULT_FIELD_FILTERS,
'name',
'code',
'phase',
'resourceTableType',
'analyticsTableType',
'sql',
] as const
1 change: 1 addition & 0 deletions src/pages/analyticsTableHooks/form/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { analyticsTableHookListSchema } from './analyticsTableHookSchema'
export { analyticsTableHookFormSchema } from './analyticsTableHookSchema'
Loading