Chart Series Summary Type eklendi
This commit is contained in:
parent
d136fb2447
commit
531b924f5e
7 changed files with 103 additions and 61 deletions
|
|
@ -91,6 +91,11 @@ public class ChartSeriesDto
|
||||||
/// FullStackedBarSeries,BubbleSeries,
|
/// FullStackedBarSeries,BubbleSeries,
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string ValueField { get; set; }
|
public string ValueField { get; set; }
|
||||||
|
/// <summary> Değer özetleme işlevini belirtir.
|
||||||
|
/// Accepted Values: 'avg' | 'count' | 'custom' | 'max' | 'min' | 'sum'
|
||||||
|
/// Default Value: 'sum'
|
||||||
|
/// </summary>
|
||||||
|
public string SummaryType { get; set; } = "sum";
|
||||||
/// <summary> Serinin görünür olup olmayacağını belirtir.
|
/// <summary> Serinin görünür olup olmayacağını belirtir.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Visible { get; set; } = true;
|
public bool Visible { get; set; } = true;
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,8 @@ public class ChartSeries : ValueObject
|
||||||
public string Type { get; private set; }
|
public string Type { get; private set; }
|
||||||
[JsonPropertyName("ValueField")]
|
[JsonPropertyName("ValueField")]
|
||||||
public string ValueField { get; private set; }
|
public string ValueField { get; private set; }
|
||||||
|
[JsonPropertyName("SummaryType")]
|
||||||
|
public string SummaryType { get; private set; }
|
||||||
[JsonPropertyName("Visible")]
|
[JsonPropertyName("Visible")]
|
||||||
public bool Visible { get; private set; } = true;
|
public bool Visible { get; private set; } = true;
|
||||||
[JsonPropertyName("Width")]
|
[JsonPropertyName("Width")]
|
||||||
|
|
@ -69,6 +71,7 @@ public class ChartSeries : ValueObject
|
||||||
yield return ShowInLegend;
|
yield return ShowInLegend;
|
||||||
yield return Type;
|
yield return Type;
|
||||||
yield return ValueField;
|
yield return ValueField;
|
||||||
|
yield return SummaryType;
|
||||||
yield return Visible;
|
yield return Visible;
|
||||||
yield return Width;
|
yield return Width;
|
||||||
yield return Label;
|
yield return Label;
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,7 @@ export interface ChartSeriesDto {
|
||||||
showInLegend: boolean
|
showInLegend: boolean
|
||||||
type?: string
|
type?: string
|
||||||
valueField?: string
|
valueField?: string
|
||||||
|
summaryType?: string
|
||||||
visible: boolean
|
visible: boolean
|
||||||
width: number
|
width: number
|
||||||
label: ChartLabelDto
|
label: ChartLabelDto
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
<Th>Name</Th>
|
<Th>Name</Th>
|
||||||
<Th>Argument Field</Th>
|
<Th>Argument Field</Th>
|
||||||
<Th>Value Field</Th>
|
<Th>Value Field</Th>
|
||||||
|
<Th>Summary Type</Th>
|
||||||
<Th>Pane</Th>
|
<Th>Pane</Th>
|
||||||
<Th>Axis</Th>
|
<Th>Axis</Th>
|
||||||
</Tr>
|
</Tr>
|
||||||
|
|
@ -207,6 +208,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
<Td>{row.name}</Td>
|
<Td>{row.name}</Td>
|
||||||
<Td>{row.argumentField}</Td>
|
<Td>{row.argumentField}</Td>
|
||||||
<Td>{row.valueField}</Td>
|
<Td>{row.valueField}</Td>
|
||||||
|
<Td>{row.summaryType}</Td>
|
||||||
<Td>{row.pane}</Td>
|
<Td>{row.pane}</Td>
|
||||||
<Td>{row.axis}</Td>
|
<Td>{row.axis}</Td>
|
||||||
</Tr>
|
</Tr>
|
||||||
|
|
@ -215,11 +217,11 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
</Table>
|
</Table>
|
||||||
</Card>
|
</Card>
|
||||||
<JsonRowOpDialogSeries
|
<JsonRowOpDialogSeries
|
||||||
listFormCode={listFormValues.listFormCode!}
|
|
||||||
isOpen={isJsonRowOpDialogOpen}
|
isOpen={isJsonRowOpDialogOpen}
|
||||||
setIsOpen={setIsJsonRowOpDialogOpen}
|
setIsOpen={setIsJsonRowOpDialogOpen}
|
||||||
data={jsonRowOpModalData}
|
data={jsonRowOpModalData}
|
||||||
setData={setJsonRowOpModalData}
|
setData={setJsonRowOpModalData}
|
||||||
|
fieldList={fieldList}
|
||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value="series_common">
|
<TabContent value="series_common">
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import {
|
||||||
chartSeriesDashStyleOptions,
|
chartSeriesDashStyleOptions,
|
||||||
chartSeriesSelectionModeOptions,
|
chartSeriesSelectionModeOptions,
|
||||||
chartSeriesTypeOptions,
|
chartSeriesTypeOptions,
|
||||||
|
columnSummaryTypeListOptions,
|
||||||
} from '../options'
|
} from '../options'
|
||||||
import { ChartPanesDto, ChartSeriesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models'
|
import { ChartPanesDto, ChartSeriesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models'
|
||||||
import { getListFormFields } from '@/services/admin/list-form-field.service'
|
import { getListFormFields } from '@/services/admin/list-form-field.service'
|
||||||
|
|
@ -41,8 +42,9 @@ const schema = object().shape({
|
||||||
ignoreEmptyPoints: boolean().notRequired(),
|
ignoreEmptyPoints: boolean().notRequired(),
|
||||||
type: string().notRequired(),
|
type: string().notRequired(),
|
||||||
name: string().required('Name Required'),
|
name: string().required('Name Required'),
|
||||||
argumentField: string().notRequired(),
|
argumentField: string().required('Argument Field Required'),
|
||||||
valueField: string().notRequired(),
|
valueField: string().required('Value Field Required'),
|
||||||
|
summaryType: string().required('Summary Type Required'),
|
||||||
axis: string().notRequired(),
|
axis: string().notRequired(),
|
||||||
pane: string().notRequired(),
|
pane: string().notRequired(),
|
||||||
dashStyle: string().notRequired(),
|
dashStyle: string().notRequired(),
|
||||||
|
|
@ -68,21 +70,20 @@ const schema = object().shape({
|
||||||
})
|
})
|
||||||
|
|
||||||
function JsonRowOpDialogSeries({
|
function JsonRowOpDialogSeries({
|
||||||
listFormCode,
|
|
||||||
isOpen,
|
isOpen,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
data,
|
data,
|
||||||
setData,
|
setData,
|
||||||
|
fieldList,
|
||||||
}: {
|
}: {
|
||||||
listFormCode: string
|
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
setIsOpen: Dispatch<SetStateAction<boolean>>
|
setIsOpen: Dispatch<SetStateAction<boolean>>
|
||||||
data: JsonRowDialogData | undefined
|
data: JsonRowDialogData | undefined
|
||||||
setData: Dispatch<SetStateAction<JsonRowDialogData | undefined>>
|
setData: Dispatch<SetStateAction<JsonRowDialogData | undefined>>
|
||||||
|
fieldList?: SelectBoxOption[]
|
||||||
}) {
|
}) {
|
||||||
const { translate } = useLocalization()
|
const { translate } = useLocalization()
|
||||||
const { setJsonValue } = useStoreActions((a) => a.admin)
|
const { setJsonValue } = useStoreActions((a) => a.admin)
|
||||||
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
|
||||||
|
|
||||||
const handleClose = async (e?: any) => {
|
const handleClose = async (e?: any) => {
|
||||||
if (e) {
|
if (e) {
|
||||||
|
|
@ -117,44 +118,6 @@ function JsonRowOpDialogSeries({
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
const getFields = async () => {
|
|
||||||
if (!listFormCode) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const resp = await getListFormFields({
|
|
||||||
listFormCode,
|
|
||||||
sorting: 'ListOrderNo',
|
|
||||||
maxResultCount: 1000,
|
|
||||||
})
|
|
||||||
if (resp.data?.items) {
|
|
||||||
const fieldNames = groupBy(resp?.data?.items, 'fieldName')
|
|
||||||
setFieldList(
|
|
||||||
Object.keys(fieldNames).map((a) => ({
|
|
||||||
value: a,
|
|
||||||
label: a,
|
|
||||||
})),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger" duration={2000}>
|
|
||||||
Alanlar getirilemedi
|
|
||||||
{error.toString()}
|
|
||||||
</Notification>,
|
|
||||||
{
|
|
||||||
placement: 'top-end',
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
useEffect(() => {
|
|
||||||
if (isOpen && data) {
|
|
||||||
getFields()
|
|
||||||
}
|
|
||||||
}, [isOpen, data])
|
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
@ -310,7 +273,7 @@ function JsonRowOpDialogSeries({
|
||||||
form={form}
|
form={form}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
options={fieldList}
|
options={fieldList}
|
||||||
value={fieldList.find(
|
value={fieldList?.find(
|
||||||
(option) => option.value === values.argumentField,
|
(option) => option.value === values.argumentField,
|
||||||
)}
|
)}
|
||||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||||
|
|
@ -334,7 +297,7 @@ function JsonRowOpDialogSeries({
|
||||||
form={form}
|
form={form}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
options={fieldList}
|
options={fieldList}
|
||||||
value={fieldList.find((option) => option.value === values.valueField)}
|
value={fieldList?.find((option) => option.value === values.valueField)}
|
||||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||||
menuPlacement="auto"
|
menuPlacement="auto"
|
||||||
maxMenuHeight={150}
|
maxMenuHeight={150}
|
||||||
|
|
@ -343,6 +306,38 @@ function JsonRowOpDialogSeries({
|
||||||
</Field>
|
</Field>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
||||||
|
<FormItem
|
||||||
|
label={translate('::ListForms.ListFormFieldEdit.PivotSettingSummaryType')}
|
||||||
|
invalid={
|
||||||
|
errors.summaryType &&
|
||||||
|
touched.summaryType
|
||||||
|
}
|
||||||
|
errorMessage={errors.summaryType}
|
||||||
|
>
|
||||||
|
<Field
|
||||||
|
type="text"
|
||||||
|
autoComplete="off"
|
||||||
|
name="summaryType"
|
||||||
|
placeholder={translate(
|
||||||
|
'::ListForms.ListFormFieldEdit.PivotSettingSummaryType',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={columnSummaryTypeListOptions}
|
||||||
|
value={columnSummaryTypeListOptions.filter(
|
||||||
|
(option: any) =>
|
||||||
|
option.value === values.summaryType,
|
||||||
|
)}
|
||||||
|
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</FormItem>
|
||||||
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Axis"
|
label="Axis"
|
||||||
invalid={errors.axis && touched.axis}
|
invalid={errors.axis && touched.axis}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ import { Helmet } from 'react-helmet'
|
||||||
import { useParams, useSearchParams } from 'react-router-dom'
|
import { useParams, useSearchParams } from 'react-router-dom'
|
||||||
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
|
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
|
||||||
import { GridDto } from '@/proxy/form/models'
|
import { GridDto } from '@/proxy/form/models'
|
||||||
|
import { usePermission } from '@/utils/hooks/usePermission'
|
||||||
|
import { Button } from '@/components/ui'
|
||||||
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
|
import { usePWA } from '@/utils/hooks/usePWA'
|
||||||
|
import { FaInfoCircle } from 'react-icons/fa'
|
||||||
|
|
||||||
interface ChartProps extends CommonProps, Meta {
|
interface ChartProps extends CommonProps, Meta {
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
|
|
@ -22,6 +27,8 @@ interface ChartProps extends CommonProps, Meta {
|
||||||
const Chart = (props: ChartProps) => {
|
const Chart = (props: ChartProps) => {
|
||||||
const { listFormCode, filter, isSubForm, level, gridDto } = props
|
const { listFormCode, filter, isSubForm, level, gridDto } = props
|
||||||
const { translate } = useLocalization()
|
const { translate } = useLocalization()
|
||||||
|
const { checkPermission } = usePermission()
|
||||||
|
const isPwaMode = usePWA()
|
||||||
|
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
const [chartOptions, setChartOptions] = useState<any>()
|
const [chartOptions, setChartOptions] = useState<any>()
|
||||||
|
|
@ -33,10 +40,10 @@ const Chart = (props: ChartProps) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!gridDto) return
|
if (!gridDto) return
|
||||||
|
|
||||||
console.log(
|
// console.log(
|
||||||
gridDto.gridOptions?.seriesDto?.map((s) => `${s.argumentField} asc false`).join(', '),
|
// gridDto.gridOptions?.seriesDto?.map((s) => `${s.argumentField} asc false`).join(', '),
|
||||||
)
|
// )
|
||||||
console.log(gridDto.gridOptions?.seriesDto?.map((s) => `${s.valueField} count`).join(', '))
|
// console.log(gridDto.gridOptions?.seriesDto?.map((s) => `${s.valueField} count`).join(', '))
|
||||||
|
|
||||||
const dataSource = createSelectDataSource(
|
const dataSource = createSelectDataSource(
|
||||||
gridDto.gridOptions,
|
gridDto.gridOptions,
|
||||||
|
|
@ -59,7 +66,9 @@ const Chart = (props: ChartProps) => {
|
||||||
//theme: s(chartDto.commonDto?.theme, 'generic.light'),
|
//theme: s(chartDto.commonDto?.theme, 'generic.light'),
|
||||||
|
|
||||||
title: gridDto.gridOptions.titleDto,
|
title: gridDto.gridOptions.titleDto,
|
||||||
size: gridDto.gridOptions.sizeDto?.useSize ? gridDto.gridOptions.sizeDto : null,
|
size: gridDto.gridOptions.sizeDto?.useSize
|
||||||
|
? { width: gridDto.gridOptions.sizeDto.width, height: gridDto.gridOptions.sizeDto.height }
|
||||||
|
: { width: '100%', height: window.innerHeight - 210 },
|
||||||
legend: gridDto.gridOptions.legendDto,
|
legend: gridDto.gridOptions.legendDto,
|
||||||
margin: gridDto.gridOptions.marginDto,
|
margin: gridDto.gridOptions.marginDto,
|
||||||
adaptiveLayout: gridDto.gridOptions.adaptivelayoutDto,
|
adaptiveLayout: gridDto.gridOptions.adaptivelayoutDto,
|
||||||
|
|
@ -74,7 +83,7 @@ const Chart = (props: ChartProps) => {
|
||||||
valueAxis: gridDto.gridOptions.valueAxisDto,
|
valueAxis: gridDto.gridOptions.valueAxisDto,
|
||||||
tooltip: gridDto.gridOptions.tooltipDto,
|
tooltip: gridDto.gridOptions.tooltipDto,
|
||||||
|
|
||||||
series:gridDto.gridOptions.seriesDto,
|
series: gridDto.gridOptions.seriesDto,
|
||||||
// gridDto.gridOptions.seriesDto?.length > 0
|
// gridDto.gridOptions.seriesDto?.length > 0
|
||||||
// ? gridDto.gridOptions.seriesDto.map((s) => ({
|
// ? gridDto.gridOptions.seriesDto.map((s) => ({
|
||||||
// argumentField: 'key',
|
// argumentField: 'key',
|
||||||
|
|
@ -106,7 +115,32 @@ const Chart = (props: ChartProps) => {
|
||||||
></Helmet>
|
></Helmet>
|
||||||
)}
|
)}
|
||||||
{_listFormCode && chartOptions && (
|
{_listFormCode && chartOptions && (
|
||||||
|
<div className="p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 ">
|
||||||
|
<div className="flex justify-end items-center">
|
||||||
|
<div className="relative pb-1 flex gap-1 border-b-1">
|
||||||
|
{checkPermission(gridDto?.gridOptions.permissionDto.u) && (
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
variant={'default'}
|
||||||
|
className="text-sm"
|
||||||
|
onClick={() => {
|
||||||
|
window.open(
|
||||||
|
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(
|
||||||
|
':listFormCode',
|
||||||
|
listFormCode,
|
||||||
|
),
|
||||||
|
isPwaMode ? '_self' : '_blank',
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
title="Form Manager"
|
||||||
|
>
|
||||||
|
<FaInfoCircle className="w-3 h-3" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<DxChart key={'DxChart' + _listFormCode} {...chartOptions}></DxChart>
|
<DxChart key={'DxChart' + _listFormCode} {...chartOptions}></DxChart>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import classNames from 'classnames'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
import { GridDto } from '@/proxy/form/models'
|
import { GridDto } from '@/proxy/form/models'
|
||||||
import Card from './Card'
|
import Card from './Card'
|
||||||
import { Button } from '@/components/ui'
|
import { Badge, Button } from '@/components/ui'
|
||||||
import Pivot from './Pivot'
|
import Pivot from './Pivot'
|
||||||
import { getList } from '@/services/form.service'
|
import { getList } from '@/services/form.service'
|
||||||
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
|
import { useCurrentMenuIcon } from '@/utils/hooks/useCurrentMenuIcon'
|
||||||
|
|
@ -73,6 +73,8 @@ const List = () => {
|
||||||
<h4 className="text-slate-700 text-sm font-medium leading-none">
|
<h4 className="text-slate-700 text-sm font-medium leading-none">
|
||||||
{translate('::' + gridDto?.gridOptions?.title) || ''}
|
{translate('::' + gridDto?.gridOptions?.title) || ''}
|
||||||
</h4>
|
</h4>
|
||||||
|
●
|
||||||
|
<Badge content={viewMode} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{gridDto?.gridOptions?.description === gridDto?.gridOptions?.title ? (
|
{gridDto?.gridOptions?.description === gridDto?.gridOptions?.title ? (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue