Chart Drawer
This commit is contained in:
parent
01ad6ffa60
commit
5d7db888ec
2 changed files with 62 additions and 54 deletions
|
|
@ -247,29 +247,29 @@ export const chartPaletteExtensionModeOptions = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export const chartSeriesTypeOptions = [
|
export const chartSeriesTypeOptions = [
|
||||||
{ value: 'line', label: 'Line' },
|
{ value: 'line', label: 'Line', icon: '📈' },
|
||||||
{ value: 'stepline', label: 'Stepline' },
|
{ value: 'stepline', label: 'Stepline', icon: '📉' },
|
||||||
{ value: 'bar', label: 'Bar' },
|
{ value: 'bar', label: 'Bar', icon: '📊' },
|
||||||
{ value: 'fullstackedbar', label: 'Fullstackedbar' },
|
{ value: 'fullstackedbar', label: 'Fullstacked Bar', icon: '📚' },
|
||||||
{ value: 'rangebar', label: 'Rangebar' },
|
{ value: 'rangebar', label: 'Range Bar', icon: '📐' },
|
||||||
{ value: 'rangearea', label: 'Rangearea' },
|
{ value: 'rangearea', label: 'Range Area', icon: '🗺️' },
|
||||||
{ value: 'fullstackedarea', label: 'Fullstackedarea' },
|
{ value: 'fullstackedarea', label: 'Fullstacked Area', icon: '⛰️' },
|
||||||
{ value: 'area', label: 'Area' },
|
{ value: 'area', label: 'Area', icon: '🏔️' },
|
||||||
{ value: 'bubble', label: 'Bubble' },
|
{ value: 'bubble', label: 'Bubble', icon: '🫧' },
|
||||||
{ value: 'candlestick', label: 'Candlestick' },
|
{ value: 'candlestick', label: 'Candlestick', icon: '🕯️' },
|
||||||
{ value: 'fullstackedline', label: 'Fullstackedline' },
|
{ value: 'fullstackedline', label: 'Fullstacked Line', icon: '📶' },
|
||||||
{ value: 'fullstackedspline', label: 'Fullstackedspline' },
|
{ value: 'fullstackedspline', label: 'Fullstacked Spline', icon: '〰️📶' },
|
||||||
{ value: 'fullstackedsplinearea', label: 'Fullstackedsplinearea' },
|
{ value: 'fullstackedsplinearea', label: 'Fullstacked Spline Area', icon: '⛰️〰' },
|
||||||
{ value: 'scatter', label: 'Scatter' },
|
{ value: 'scatter', label: 'Scatter', icon: '🔵' },
|
||||||
{ value: 'spline', label: 'Spline' },
|
{ value: 'spline', label: 'Spline', icon: '〰️' },
|
||||||
{ value: 'splinearea', label: 'Splinearea' },
|
{ value: 'splinearea', label: 'Spline Area', icon: '🌄' },
|
||||||
{ value: 'stackedarea', label: 'Stackedarea' },
|
{ value: 'stackedarea', label: 'Stacked Area', icon: '🧱⛰️' },
|
||||||
{ value: 'stackedbar', label: 'Stackedbar' },
|
{ value: 'stackedbar', label: 'Stacked Bar', icon: '🧱📊' },
|
||||||
{ value: 'stackedline', label: 'Stackedline' },
|
{ value: 'stackedline', label: 'Stacked Line', icon: '🧱📈' },
|
||||||
{ value: 'stackedspline', label: 'Stackedspline' },
|
{ value: 'stackedspline', label: 'Stacked Spline', icon: '🧱〰️' },
|
||||||
{ value: 'stackedsplinearea', label: 'Stackedsplinearea' },
|
{ value: 'stackedsplinearea', label: 'Stacked Spline Area', icon: '🧱🌄' },
|
||||||
{ value: 'steparea', label: 'Steparea' },
|
{ value: 'steparea', label: 'Step Area', icon: '🪜' },
|
||||||
{ value: 'stock', label: 'Stock' },
|
{ value: 'stock', label: 'Stock', icon: '💹' },
|
||||||
]
|
]
|
||||||
|
|
||||||
export const chartSeriesSelectionModeOptions = [
|
export const chartSeriesSelectionModeOptions = [
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { Button, FormContainer, Input, Notification, Select, toast } from '@/com
|
||||||
import { Field, FieldArray, Form, Formik, FieldProps } from 'formik'
|
import { Field, FieldArray, Form, Formik, FieldProps } from 'formik'
|
||||||
import { FaMinus, FaPlus, FaTimes, FaSave } from 'react-icons/fa'
|
import { FaMinus, FaPlus, FaTimes, FaSave } from 'react-icons/fa'
|
||||||
import { SelectBoxOption } from '@/types/shared'
|
import { SelectBoxOption } from '@/types/shared'
|
||||||
import { columnSummaryTypeListOptions } from '../admin/listForm/edit/options'
|
import { chartSeriesTypeOptions, columnSummaryTypeListOptions } from '../admin/listForm/edit/options'
|
||||||
import { ChartSeriesDto } from '@/proxy/admin/charts/models'
|
import { ChartSeriesDto } from '@/proxy/admin/charts/models'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
import { useStoreState } from '@/store/store'
|
import { useStoreState } from '@/store/store'
|
||||||
|
|
@ -35,24 +35,15 @@ const ChartDrawer = ({
|
||||||
series: array().of(
|
series: array().of(
|
||||||
object().shape({
|
object().shape({
|
||||||
name: string().required(translate('::App.Platform.ChartDrawer.NameRequired')),
|
name: string().required(translate('::App.Platform.ChartDrawer.NameRequired')),
|
||||||
argumentField: string().required(translate('::App.Platform.ChartDrawer.ArgumentFieldRequired')),
|
argumentField: string().required(
|
||||||
|
translate('::App.Platform.ChartDrawer.ArgumentFieldRequired'),
|
||||||
|
),
|
||||||
valueField: string().required(translate('::App.Platform.ChartDrawer.ValueFieldRequired')),
|
valueField: string().required(translate('::App.Platform.ChartDrawer.ValueFieldRequired')),
|
||||||
summaryType: string().required(translate('::App.Platform.ChartDrawer.SummaryTypeRequired')),
|
summaryType: string().required(translate('::App.Platform.ChartDrawer.SummaryTypeRequired')),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
// Chart type icons
|
|
||||||
const chartTypeIcons = [
|
|
||||||
{ type: 'line', label: 'Line', icon: '📈' },
|
|
||||||
{ type: 'bar', label: 'Bar', icon: '📊' },
|
|
||||||
{ type: 'area', label: 'Area', icon: '🏔️' },
|
|
||||||
{ type: 'scatter', label: 'Scatter', icon: '🔵' },
|
|
||||||
{ type: 'spline', label: 'Spline', icon: '〰️' },
|
|
||||||
{ type: 'stackedbar', label: 'Stacked Bar', icon: '📚' },
|
|
||||||
{ type: 'stackedarea', label: 'Stacked Area', icon: '⛰️' },
|
|
||||||
]
|
|
||||||
|
|
||||||
const newSeriesValue = () => {
|
const newSeriesValue = () => {
|
||||||
return {
|
return {
|
||||||
index: -1,
|
index: -1,
|
||||||
|
|
@ -111,9 +102,14 @@ const ChartDrawer = ({
|
||||||
onSubmit={async (values, { setSubmitting }) => {
|
onSubmit={async (values, { setSubmitting }) => {
|
||||||
try {
|
try {
|
||||||
await onSave(values.series)
|
await onSave(values.series)
|
||||||
toast.push(<Notification type="success">{translate('::App.Platform.ChartDrawer.ChartSaved')}</Notification>, {
|
toast.push(
|
||||||
|
<Notification type="success">
|
||||||
|
{translate('::App.Platform.ChartDrawer.ChartSaved')}
|
||||||
|
</Notification>,
|
||||||
|
{
|
||||||
placement: 'top-end',
|
placement: 'top-end',
|
||||||
})
|
},
|
||||||
|
)
|
||||||
onClose()
|
onClose()
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.push(
|
toast.push(
|
||||||
|
|
@ -186,7 +182,9 @@ const ChartDrawer = ({
|
||||||
>
|
>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<span className="font-semibold text-sm">{translate('::App.Platform.ChartDrawer.Series')} #{index + 1}</span>
|
<span className="font-semibold text-sm">
|
||||||
|
{translate('::App.Platform.ChartDrawer.Series')} #{index + 1}
|
||||||
|
</span>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="xs"
|
size="xs"
|
||||||
|
|
@ -201,7 +199,9 @@ const ChartDrawer = ({
|
||||||
|
|
||||||
{/* Chart Type Selector */}
|
{/* Chart Type Selector */}
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="text-xs font-medium mb-1 block">{translate('::App.Platform.ChartDrawer.ChartType')}</label>
|
<label className="text-xs font-medium mb-1 block">
|
||||||
|
{translate('::App.Platform.ChartDrawer.ChartType')}
|
||||||
|
</label>
|
||||||
<Field name={`series[${index}].type`}>
|
<Field name={`series[${index}].type`}>
|
||||||
{({ field, form }: FieldProps) => (
|
{({ field, form }: FieldProps) => (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -215,33 +215,33 @@ const ChartDrawer = ({
|
||||||
className="w-full px-3 py-2 text-left border rounded hover:bg-white flex items-center gap-2 transition-colors"
|
className="w-full px-3 py-2 text-left border rounded hover:bg-white flex items-center gap-2 transition-colors"
|
||||||
>
|
>
|
||||||
<span className="text-xl">
|
<span className="text-xl">
|
||||||
{chartTypeIcons.find((t) => t.type === field.value)
|
{chartSeriesTypeOptions.find((t) => t.label === field.value)
|
||||||
?.icon || '📊'}
|
?.icon || '📊'}
|
||||||
</span>
|
</span>
|
||||||
<span className="text-sm font-medium">
|
<span className="text-sm font-medium">
|
||||||
{chartTypeIcons.find((t) => t.type === field.value)
|
{chartSeriesTypeOptions.find((t) => t.label === field.value)
|
||||||
?.label || field.value}
|
?.label || field.value}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
{selectedSeriesIndex === index && (
|
{selectedSeriesIndex === index && (
|
||||||
<div className="absolute z-50 mt-1 w-full bg-white border rounded-lg shadow-xl p-2">
|
<div className="absolute z-50 mt-1 w-full bg-white border rounded-lg shadow-xl p-2">
|
||||||
<div className="grid grid-cols-2 gap-2">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
{chartTypeIcons.map((chartType) => (
|
{chartSeriesTypeOptions.map((chartType) => (
|
||||||
<button
|
<button
|
||||||
key={chartType.type}
|
key={chartType.label}
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
form.setFieldValue(field.name, chartType.type)
|
form.setFieldValue(field.name, chartType.label)
|
||||||
setSelectedSeriesIndex(-1)
|
setSelectedSeriesIndex(-1)
|
||||||
}}
|
}}
|
||||||
className={`p-3 rounded-lg hover:bg-blue-50 flex flex-col items-center gap-1 transition-all ${
|
className={`p-2 rounded-lg hover:bg-blue-50 flex items-center gap-2 transition-all ${
|
||||||
field.value === chartType.type
|
field.value === chartType.label
|
||||||
? 'bg-blue-100 ring-2 ring-blue-400'
|
? 'bg-blue-100 ring-2 ring-blue-400'
|
||||||
: 'bg-gray-50'
|
: 'bg-gray-50'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span className="text-2xl">{chartType.icon}</span>
|
<span className="text-xl">{chartType.icon}</span>
|
||||||
<span className="text-xs font-medium text-center">
|
<span className="text-xs font-medium">
|
||||||
{chartType.label}
|
{chartType.label}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -256,7 +256,9 @@ const ChartDrawer = ({
|
||||||
|
|
||||||
{/* Name */}
|
{/* Name */}
|
||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="text-xs font-medium mb-1 block">{translate('::App.Platform.ChartDrawer.Name')}</label>
|
<label className="text-xs font-medium mb-1 block">
|
||||||
|
{translate('::App.Platform.ChartDrawer.Name')}
|
||||||
|
</label>
|
||||||
<Field
|
<Field
|
||||||
size="sm"
|
size="sm"
|
||||||
name={`series[${index}].name`}
|
name={`series[${index}].name`}
|
||||||
|
|
@ -284,7 +286,9 @@ const ChartDrawer = ({
|
||||||
onChange={(option) => {
|
onChange={(option) => {
|
||||||
form.setFieldValue(field.name, option?.value)
|
form.setFieldValue(field.name, option?.value)
|
||||||
}}
|
}}
|
||||||
placeholder={translate('::App.Platform.ChartDrawer.SelectField')}
|
placeholder={translate(
|
||||||
|
'::App.Platform.ChartDrawer.SelectField',
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -308,7 +312,9 @@ const ChartDrawer = ({
|
||||||
onChange={(option) => {
|
onChange={(option) => {
|
||||||
form.setFieldValue(field.name, option?.value)
|
form.setFieldValue(field.name, option?.value)
|
||||||
}}
|
}}
|
||||||
placeholder={translate('::App.Platform.ChartDrawer.SelectField')}
|
placeholder={translate(
|
||||||
|
'::App.Platform.ChartDrawer.SelectField',
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
|
|
@ -351,7 +357,9 @@ const ChartDrawer = ({
|
||||||
<Button variant="solid" loading={isSubmitting} type="submit" className="flex-1">
|
<Button variant="solid" loading={isSubmitting} type="submit" className="flex-1">
|
||||||
<div className="flex items-center justify-center gap-2">
|
<div className="flex items-center justify-center gap-2">
|
||||||
<FaSave />
|
<FaSave />
|
||||||
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::App.Platform.ChartDrawer.Save')}
|
{isSubmitting
|
||||||
|
? translate('::SavingWithThreeDot')
|
||||||
|
: translate('::App.Platform.ChartDrawer.Save')}
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue