From e3a816549940221e9f6efe5bdd9677c5fe02cade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:11:23 +0300 Subject: [PATCH] =?UTF-8?q?Chart=20komponenti=20d=C3=BCzenlemesi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ListForms/Chart/ChartSeriesDto.cs | 13 +- .../ListFormJsonRowAppService.cs | 122 ++++++-- .../Queries/ChartSeries.cs | 5 + .../Queries/SelectQueryManager.cs | 4 +- ui/src/proxy/admin/charts/models.ts | 6 +- ui/src/proxy/form/models.ts | 26 +- .../admin/listForm/edit/ChartTabSeries.tsx | 22 +- .../JsonRowOpDialogAnnotation.tsx | 2 +- .../JsonRowOpDialogAxis.tsx | 2 +- .../JsonRowOpDialogCommand.tsx | 2 +- .../JsonRowOpDialogDatabase.tsx | 2 +- .../JsonRowOpDialogEditForm.tsx | 2 +- .../JsonRowOpDialogExtraFilter.tsx | 4 +- .../JsonRowOpDialogPane.tsx | 2 +- .../JsonRowOpDialogSeries.tsx | 15 +- .../JsonRowOpDialogSubForm.tsx | 2 +- .../JsonRowOpDialogWidget.tsx | 2 +- ui/src/views/list/Chart.tsx | 279 +++++++----------- ui/src/views/list/ChartSeriesDialog.tsx | 279 ++++++++++++++++++ ui/src/views/list/ChartSeriesDialog1.tsx | 278 +++++++++++++++++ ui/src/views/list/List.tsx | 1 + 21 files changed, 823 insertions(+), 247 deletions(-) create mode 100644 ui/src/views/list/ChartSeriesDialog.tsx create mode 100644 ui/src/views/list/ChartSeriesDialog1.tsx diff --git a/api/src/Kurs.Platform.Application.Contracts/ListForms/Chart/ChartSeriesDto.cs b/api/src/Kurs.Platform.Application.Contracts/ListForms/Chart/ChartSeriesDto.cs index df1fe1c0..cd682153 100644 --- a/api/src/Kurs.Platform.Application.Contracts/ListForms/Chart/ChartSeriesDto.cs +++ b/api/src/Kurs.Platform.Application.Contracts/ListForms/Chart/ChartSeriesDto.cs @@ -91,11 +91,6 @@ public class ChartSeriesDto /// FullStackedBarSeries,BubbleSeries, /// public string ValueField { get; set; } - /// Değer özetleme işlevini belirtir. - /// Accepted Values: 'avg' | 'count' | 'custom' | 'max' | 'min' | 'sum' - /// Default Value: 'sum' - /// - public string SummaryType { get; set; } = "sum"; /// Serinin görünür olup olmayacağını belirtir. /// public bool Visible { get; set; } = true; @@ -126,4 +121,12 @@ public class ChartSeriesDto // valueErrorBar public ChartLabelDto Label { get; set; } + + /// Değer özetleme işlevini belirtir. + /// Accepted Values: 'avg' | 'count' | 'custom' | 'max' | 'min' | 'sum' + /// Default Value: 'sum' + /// + public string SummaryType { get; set; } = "sum"; + /// 'Kullanıcı Adı' + public string UserId { get; set; } } \ No newline at end of file diff --git a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormJsonRowAppService.cs b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormJsonRowAppService.cs index 88af5104..c3ea77fb 100644 --- a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormJsonRowAppService.cs +++ b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormJsonRowAppService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.Json; using System.Threading.Tasks; using Kurs.Platform.Entities; @@ -8,6 +9,7 @@ using Kurs.Platform.Queries; using Microsoft.AspNetCore.Authorization; using Volo.Abp; using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; using static Kurs.Platform.PlatformConsts; namespace Kurs.Platform.ListForms.Administration; @@ -19,37 +21,121 @@ namespace Kurs.Platform.ListForms.Administration; public class ListFormJsonRowAppService : PlatformAppService { private readonly IRepository repository; + private readonly ICurrentUser currentUser; + private readonly string userId; public ListFormJsonRowAppService( - IRepository _repository) : base() + IRepository _repository, + ICurrentUser _currentUser + ) : base() { repository = _repository; + currentUser = _currentUser; + userId = currentUser.Name; + } public async Task GetAllAsync(Guid id, string field) { var listForm = await GetAsync(id); - return field switch + switch (field) { - ListFormEditTabs.Database.Select.SelectFieldsDefaultValuesJsonRow => listForm.SelectFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.SelectFieldsDefaultValueJson), - ListFormEditTabs.Database.Insert.InsertFieldsDefaultValuesJsonRow => listForm.InsertFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.InsertFieldsDefaultValueJson), - ListFormEditTabs.Database.Update.UpdateFieldsDefaultValuesJsonRow => listForm.UpdateFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.UpdateFieldsDefaultValueJson), - ListFormEditTabs.Database.Delete.DeleteFieldsDefaultValuesJsonRow => listForm.DeleteFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.DeleteFieldsDefaultValueJson), - ListFormEditTabs.Database.Insert.FormFieldsDefaultValuesJsonRow => listForm.FormFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.FormFieldsDefaultValueJson), - ListFormEditTabs.Edit.EditingFormFieldsJsonRow => listForm.EditingFormJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.EditingFormJson), - ListFormEditTabs.CommandColumnsJsonRow => listForm.CommandColumnJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.CommandColumnJson), - ListFormEditTabs.SubFormJsonRow => listForm.SubFormsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.SubFormsJson), - ListFormEditTabs.WidgetForm => listForm.WidgetsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.WidgetsJson), - ListFormEditTabs.ExtraFilterForm => listForm.ExtraFilterJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.ExtraFilterJson), + case ListFormEditTabs.Database.Select.SelectFieldsDefaultValuesJsonRow: + return listForm.SelectFieldsDefaultValueJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.SelectFieldsDefaultValueJson) ?? []; - ListFormEditTabs.ChartSeries.GeneralJsonRow => listForm.SeriesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.SeriesJson), - ListFormEditTabs.ChartAxis.ValueAxisJsonRow => listForm.ValueAxisJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.ValueAxisJson), - ListFormEditTabs.ChartPanes.PanesJsonRow => listForm.PanesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.PanesJson), - ListFormEditTabs.ChartAnnotations.GeneralJsonRow => listForm.AnnotationsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.AnnotationsJson), + case ListFormEditTabs.Database.Insert.InsertFieldsDefaultValuesJsonRow: + return listForm.InsertFieldsDefaultValueJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.InsertFieldsDefaultValueJson) ?? []; - _ => throw new UserFriendlyException(L[AppErrorCodes.ParameterNotValid]), - }; + case ListFormEditTabs.Database.Update.UpdateFieldsDefaultValuesJsonRow: + return listForm.UpdateFieldsDefaultValueJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.UpdateFieldsDefaultValueJson) ?? []; + + case ListFormEditTabs.Database.Delete.DeleteFieldsDefaultValuesJsonRow: + return listForm.DeleteFieldsDefaultValueJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.DeleteFieldsDefaultValueJson) ?? []; + + case ListFormEditTabs.Database.Insert.FormFieldsDefaultValuesJsonRow: + return listForm.FormFieldsDefaultValueJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.FormFieldsDefaultValueJson) ?? []; + + case ListFormEditTabs.Edit.EditingFormFieldsJsonRow: + return listForm.EditingFormJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.EditingFormJson) ?? []; + + case ListFormEditTabs.CommandColumnsJsonRow: + return listForm.CommandColumnJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.CommandColumnJson) ?? []; + + case ListFormEditTabs.SubFormJsonRow: + return listForm.SubFormsJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.SubFormsJson) ?? []; + + case ListFormEditTabs.WidgetForm: + return listForm.WidgetsJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.WidgetsJson) ?? []; + + case ListFormEditTabs.ExtraFilterForm: + return listForm.ExtraFilterJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.ExtraFilterJson) ?? []; + + case ListFormEditTabs.ChartSeries.GeneralJsonRow: + return listForm.SeriesJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.SeriesJson) ?? []; + + case ListFormEditTabs.ChartAxis.ValueAxisJsonRow: + return listForm.ValueAxisJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.ValueAxisJson) ?? []; + + case ListFormEditTabs.ChartPanes.PanesJsonRow: + return listForm.PanesJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.PanesJson) ?? []; + + case ListFormEditTabs.ChartAnnotations.GeneralJsonRow: + return listForm.AnnotationsJson.IsNullOrWhiteSpace() + ? [] + : JsonSerializer.Deserialize>(listForm.AnnotationsJson) ?? []; + + default: + throw new UserFriendlyException(L[AppErrorCodes.ParameterNotValid]); + } + + + // return field switch + // { + // ListFormEditTabs.Database.Select.SelectFieldsDefaultValuesJsonRow => listForm.SelectFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.SelectFieldsDefaultValueJson), + // ListFormEditTabs.Database.Insert.InsertFieldsDefaultValuesJsonRow => listForm.InsertFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.InsertFieldsDefaultValueJson), + // ListFormEditTabs.Database.Update.UpdateFieldsDefaultValuesJsonRow => listForm.UpdateFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.UpdateFieldsDefaultValueJson), + // ListFormEditTabs.Database.Delete.DeleteFieldsDefaultValuesJsonRow => listForm.DeleteFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.DeleteFieldsDefaultValueJson), + // ListFormEditTabs.Database.Insert.FormFieldsDefaultValuesJsonRow => listForm.FormFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.FormFieldsDefaultValueJson), + // ListFormEditTabs.Edit.EditingFormFieldsJsonRow => listForm.EditingFormJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.EditingFormJson), + // ListFormEditTabs.CommandColumnsJsonRow => listForm.CommandColumnJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.CommandColumnJson), + // ListFormEditTabs.SubFormJsonRow => listForm.SubFormsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.SubFormsJson), + // ListFormEditTabs.WidgetForm => listForm.WidgetsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.WidgetsJson), + // ListFormEditTabs.ExtraFilterForm => listForm.ExtraFilterJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.ExtraFilterJson), + + // ListFormEditTabs.ChartSeries.GeneralJsonRow => listForm.SeriesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.SeriesJson), + // ListFormEditTabs.ChartAxis.ValueAxisJsonRow => listForm.ValueAxisJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.ValueAxisJson), + // ListFormEditTabs.ChartPanes.PanesJsonRow => listForm.PanesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.PanesJson), + // ListFormEditTabs.ChartAnnotations.GeneralJsonRow => listForm.AnnotationsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize>(listForm.AnnotationsJson), + + // _ => throw new UserFriendlyException(L[AppErrorCodes.ParameterNotValid]), + // }; } public async Task CreateAsync(Guid id, CrudFieldsDefaultValueJsonItemDto model) diff --git a/api/src/Kurs.Platform.Domain/Queries/ChartSeries.cs b/api/src/Kurs.Platform.Domain/Queries/ChartSeries.cs index 94d8d593..614a4c58 100644 --- a/api/src/Kurs.Platform.Domain/Queries/ChartSeries.cs +++ b/api/src/Kurs.Platform.Domain/Queries/ChartSeries.cs @@ -90,6 +90,10 @@ public class ChartSeries : ValueObject [JsonPropertyName("Label")] public ChartLabel Label { get; private set; } = new(); + [JsonInclude] + [JsonPropertyName("UserId")] + public string UserId { get; private set; } + // JSON + EF Core için parametresiz public ctor public ChartSeries() { } @@ -116,5 +120,6 @@ public class ChartSeries : ValueObject yield return Visible; yield return Width; yield return Label; + yield return UserId; } } diff --git a/api/src/Kurs.Platform.Domain/Queries/SelectQueryManager.cs b/api/src/Kurs.Platform.Domain/Queries/SelectQueryManager.cs index aa597fac..81f3cb42 100644 --- a/api/src/Kurs.Platform.Domain/Queries/SelectQueryManager.cs +++ b/api/src/Kurs.Platform.Domain/Queries/SelectQueryManager.cs @@ -766,8 +766,8 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager var seriesList = JsonSerializer.Deserialize>(listform.SeriesJson); - if (seriesList == null || !seriesList.Any()) - throw new ArgumentException("Series list is empty!"); + if (seriesList == null || seriesList.Count == 0) + return null; // ArgumentField listesi var argumentFields = seriesList.Select(s => s.ArgumentField).Distinct().ToList(); diff --git a/ui/src/proxy/admin/charts/models.ts b/ui/src/proxy/admin/charts/models.ts index 1a942af9..0cc16aef 100644 --- a/ui/src/proxy/admin/charts/models.ts +++ b/ui/src/proxy/admin/charts/models.ts @@ -1,5 +1,5 @@ import { AuditedEntityDto } from '@/proxy/abp' -import { PermissionCrudDto } from '@/proxy/form/models' +import { PermissionCrudDto, SummaryTypeEnum } from '@/proxy/form/models' export interface BreakDto { endValue: number @@ -299,6 +299,7 @@ export interface ChartScrollBarDto { } export interface ChartSeriesDto { + index: number argumentField?: string axis?: string barOverlapGroup?: string @@ -316,10 +317,11 @@ export interface ChartSeriesDto { showInLegend: boolean type?: string valueField?: string - summaryType?: string + summaryType?: SummaryTypeEnum visible: boolean width: number label: ChartLabelDto + userId?: string } export interface ChartSizeDto { diff --git a/ui/src/proxy/form/models.ts b/ui/src/proxy/form/models.ts index 77b20468..3eed9b2b 100644 --- a/ui/src/proxy/form/models.ts +++ b/ui/src/proxy/form/models.ts @@ -44,6 +44,7 @@ import { ChartZoomAndPanDto, } from '../admin/charts/models' import { ListViewLayoutType } from '@/views/admin/listForm/edit/types' +import { SeriesType } from 'devextreme/common/charts' //1 export interface SelectListItem { @@ -367,30 +368,7 @@ export interface GridPivotOptionDto { showFilterFields: boolean showChart: boolean chartHeight: number - chartCommonSeriesType: - | 'area' - | 'bar' - | 'bubble' - | 'candlestick' - | 'fullstackedarea' - | 'fullstackedbar' - | 'fullstackedline' - | 'fullstackedspline' - | 'fullstackedsplinearea' - | 'line' - | 'rangearea' - | 'rangebar' - | 'scatter' - | 'spline' - | 'splinearea' - | 'stackedarea' - | 'stackedbar' - | 'stackedline' - | 'stackedspline' - | 'stackedsplinearea' - | 'steparea' - | 'stepline' - | 'stock' + chartCommonSeriesType: SeriesType } export interface GridEditingDto { diff --git a/ui/src/views/admin/listForm/edit/ChartTabSeries.tsx b/ui/src/views/admin/listForm/edit/ChartTabSeries.tsx index 3dd0cd94..e1a47887 100644 --- a/ui/src/views/admin/listForm/edit/ChartTabSeries.tsx +++ b/ui/src/views/admin/listForm/edit/ChartTabSeries.tsx @@ -10,6 +10,7 @@ import { Tabs, Notification, toast, + Badge, } from '@/components/ui' import TBody from '@/components/ui/Table/TBody' import THead from '@/components/ui/Table/THead' @@ -153,6 +154,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) { }} /> + Type Name Argument Field @@ -204,6 +206,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) { /> + {row.userId && } {row.type} {row.name} {row.argumentField} @@ -320,7 +323,10 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) { @@ -331,7 +337,10 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) { form={form} isClearable={true} options={fieldList} - value={fieldList.find((option) => option.value === values.commonSeriesSettingsDto.argumentField)} + value={fieldList.find( + (option) => + option.value === values.commonSeriesSettingsDto.argumentField, + )} onChange={(option) => form.setFieldValue(field.name, option?.value)} menuPlacement="auto" maxMenuHeight={150} @@ -342,7 +351,10 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) { @@ -353,7 +365,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) { form={form} isClearable={true} options={fieldList} - value={fieldList.find((option) => option.value === values.commonSeriesSettingsDto.valueField)} + value={fieldList.find( + (option) => option.value === values.commonSeriesSettingsDto.valueField, + )} onChange={(option) => form.setFieldValue(field.name, option?.value)} menuPlacement="auto" maxMenuHeight={150} diff --git a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAnnotation.tsx b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAnnotation.tsx index 96e6efe3..1d0e7081 100644 --- a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAnnotation.tsx +++ b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAnnotation.tsx @@ -169,7 +169,7 @@ function JsonRowOpDialogAnnotation({ {({ touched, errors, values, isSubmitting }) => (
-
+
General diff --git a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAxis.tsx b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAxis.tsx index 5989b218..ac8a1703 100644 --- a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAxis.tsx +++ b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogAxis.tsx @@ -185,7 +185,7 @@ function JsonRowOpDialogAxis({ return ( -
+
( -
+
( -
+
( -
+
( -
+
( -
+
( -
+
{({ field, form }: FieldProps) => ( - option.value === values.summaryType, + (option: any) => option.value === values.summaryType, )} onChange={(option) => form.setFieldValue(field.name, option?.value)} /> diff --git a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogSubForm.tsx b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogSubForm.tsx index f8f967bd..54fc1c26 100644 --- a/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogSubForm.tsx +++ b/ui/src/views/admin/listForm/edit/json-row-operations/JsonRowOpDialogSubForm.tsx @@ -123,7 +123,7 @@ function JsonRowOpDialogSubForm({ {({ touched, errors, values, isSubmitting }) => ( -
+
( -
+
{ - const { listFormCode, filter, isSubForm, level, gridDto } = props + // State UserId güncellemesi için + const { userName } = useStoreState((s) => s.auth.user) + const { id, listFormCode, filter, isSubForm, level, gridDto, refreshGridDto } = props const { translate } = useLocalization() const { checkPermission } = usePermission() const isPwaMode = usePWA() - const [series, setSeries] = useState([]) const initialized = useRef(false) const [searchParams] = useSearchParams() @@ -44,38 +56,45 @@ const Chart = (props: ChartProps) => { const params = useParams() const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? '' + const [openDialog, setOpenDialog] = useState(false) + const [fieldList, setFieldList] = useState([]) + const [searchText, setSearchText] = useState('') const [prevValue, setPrevValue] = useState('') const [urlSearchParams, setUrlSearchParams] = useState( searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(), ) - const schema = object().shape({ - series: array().of( - object().shape({ - name: string().required('Name Required'), - argumentField: string().required('Argument Field Required'), - valueField: string().required('Value Field Required'), - summaryType: string().required('Summary Type Required'), - }), - ), - }) + const [allSeries, setAllSeries] = useState([]) + + const [userSeries, setUserSeries] = useState([]) + const [oldSeries, setOldSeries] = useState([]) + + useEffect(() => { + if (gridDto && !initialized.current) { + const initialSeries = gridDto.gridOptions.seriesDto.map((s, index) => ({ ...s, index })) + + setAllSeries(initialSeries) + setUserSeries(initialSeries.filter((s) => s.userId === userName)) + setOldSeries(initialSeries.filter((s) => s.userId === userName)) + + initialized.current = true + } + }, [gridDto]) useEffect(() => { if (!gridDto) return + if (!allSeries) return + if (!initialized.current) return + + const seriesDto = userSeries.length > 0 ? userSeries : allSeries.length > 0 ? allSeries : [] const gridOptions = { ...gridDto.gridOptions, - seriesDto: series ?? gridDto.gridOptions.seriesDto, + seriesDto, } - const dataSource = createSelectDataSource( - gridOptions, - listFormCode, - urlSearchParams, - [], - true, - ) + const dataSource = createSelectDataSource(gridOptions, listFormCode, urlSearchParams, [], true) const options = { dataSource: dataSource, @@ -106,7 +125,7 @@ const Chart = (props: ChartProps) => { valueAxis: gridDto.gridOptions.valueAxisDto, tooltip: gridDto.gridOptions.tooltipDto, - series: buildSeriesDto(series ?? gridDto.gridOptions.seriesDto), + series: buildSeriesDto(seriesDto), panes: gridDto.gridOptions.panesDto?.length > 0 ? gridDto.gridOptions.panesDto : undefined, commonSeriesSettings: gridDto.gridOptions.commonSeriesSettingsDto, @@ -121,7 +140,7 @@ const Chart = (props: ChartProps) => { } setChartOptions(options) - }, [gridDto, series, searchParams, urlSearchParams]) + }, [gridDto, allSeries, initialized.current, searchParams, urlSearchParams]) const onFilter = useCallback( (value?: string) => { @@ -169,50 +188,64 @@ const Chart = (props: ChartProps) => { [gridDto, urlSearchParams, searchText], ) - const newSeriesValue = () => { - return { - 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: true, - backgroundColor: '#f05b41', - customizeText: '', - format: 'decimal', - font: { - color: '#FFFFFF', - family: '"Segoe UI", "Helvetica Neue", "Trebuchet MS", Verdana, sans-serif', - size: 12, - weight: 400, - }, - }, + const getFields = async () => { + if (!props.listFormCode) return + try { + const resp = await getListFormFields({ + listFormCode: props.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( + + Alanlar getirilemedi {error.toString()} + , + { placement: 'top-end' }, + ) } } useEffect(() => { - if (gridDto && !initialized.current) { - setSeries(gridDto.gridOptions.seriesDto) - initialized.current = true - } - }, [gridDto]) + if (props.listFormCode) getFields() + }, [props.listFormCode]) - const [openDialog, setOpenDialog] = useState(false) + const onSave = async (newSeries: ChartSeriesDto[]) => { + // 1. Silinecek serileri bul (oldSeries var ama newSeries yok) + const toDelete = oldSeries.filter((old) => !newSeries.some((s) => s.index === old.index)) + + // Index kaymasını önlemek için büyükten küçüğe sırala + toDelete.sort((a, b) => b.index - a.index) + + for (const old of toDelete) { + await deleteListFormJsonRow(id, ListFormEditTabs.ChartSeries.GeneralJsonRow, old.index) + } + + // 2. Yeni veya güncellenen serileri kaydet + for (const series of newSeries) { + const input: ListFormJsonRowDto = { + index: series.index, + fieldName: ListFormEditTabs.ChartSeries.GeneralJsonRow, + itemChartSeries: series, + } + + if (series.index === -1) { + await postListFormJsonRow(id, input) + } else { + await putListFormJsonRow(id, input) + } + } + + // 3. Yeniden yükle + if (props.refreshGridDto) { + initialized.current = false + await props.refreshGridDto() + } + } return ( @@ -252,26 +285,24 @@ const Chart = (props: ChartProps) => { }} className="p-1 pl-6 pr-2 border border-1 outline-none text-xs text-gray-700 dark:text-gray-200 placeholder-gray-400 rounded" /> - - @@ -299,109 +330,13 @@ const Chart = (props: ChartProps) => {
- setOpenDialog(false)} width={600}> - 0 ? series : [newSeriesValue()], - }} - validationSchema={schema} - onSubmit={(values, { setSubmitting }) => { - setSeries(values.series) - - setSubmitting(true) - try { - toast.push({'Chart güncellendi'}, { - placement: 'top-end', - }) - setOpenDialog(false) // kaydettikten sonra dialogu kapat - } catch (error: any) { - toast.push( - - Hata - {error} - , - { placement: 'top-end' }, - ) - } finally { - setSubmitting(false) - } - }} - > - {({ setFieldValue, values, isSubmitting }) => ( - - - {/* Kaydırılabilir içerik */} -
- - {({ remove }) => ( -
- {values.series.map((_, index) => ( -
- - - - - - - - - - - - - -
- ))} -
- )} -
-
- - {/* Footer */} -
- - -
-
- - )} -
-
+ setOpenDialog(false)} + initialSeries={allSeries.filter((s) => s.userId === userName)} + fieldList={fieldList} + onSave={onSave} + />
)} diff --git a/ui/src/views/list/ChartSeriesDialog.tsx b/ui/src/views/list/ChartSeriesDialog.tsx new file mode 100644 index 00000000..3b3b1f91 --- /dev/null +++ b/ui/src/views/list/ChartSeriesDialog.tsx @@ -0,0 +1,279 @@ +import { Button, FormContainer, Input, Notification, Select, Dialog, toast } from '@/components/ui' +import { Field, FieldArray, Form, Formik, FieldProps } from 'formik' +import { FaMinus, FaPlus } from 'react-icons/fa' +import { SelectBoxOption } from '@/shared/types' +import { + chartSeriesTypeOptions, + columnSummaryTypeListOptions, +} from '../admin/listForm/edit/options' +import { ChartSeriesDto } from '@/proxy/admin/charts/models' +import { useLocalization } from '@/utils/hooks/useLocalization' +import { useStoreState } from '@/store/store' +import { object, array, string } from 'yup' +import { SummaryTypeEnum } from '@/proxy/form/models' + +interface ChartSeriesDialogProps { + open: boolean + onClose: () => void + initialSeries: ChartSeriesDto[] + fieldList: SelectBoxOption[] + onSave: (series: ChartSeriesDto[]) => void +} + +const schema = object().shape({ + series: array().of( + object().shape({ + name: string().required('Name Required'), + argumentField: string().required('Argument Field Required'), + valueField: string().required('Value Field Required'), + summaryType: string().required('Summary Type Required'), + }), + ), +}) + +const ChartSeriesDialog = ({ + open, + onClose, + initialSeries, + fieldList, + onSave, +}: ChartSeriesDialogProps) => { + const { translate } = useLocalization() + + // State UserId güncellemesi için + const { userName } = useStoreState((s) => s.auth.user) + + const newSeriesValue = () => { + return { + index: -1, + type: 'line', + name: '', + argumentField: '', + valueField: '', + summaryType: SummaryTypeEnum.Sum, + axis: '', + barOverlapGroup: '', + barPadding: 0, + barWidth: 0, + color: '', + cornerRadius: 0, + dashStyle: 'solid', + ignoreEmptyPoints: false, + pane: '', + rangeValue1Field: '', + rangeValue2Field: '', + selectionMode: 'none', + showInLegend: true, + visible: true, + width: 2, + label: { + visible: true, + backgroundColor: '#f05b41', + customizeText: '', + format: 'decimal', + font: { + color: '#FFFFFF', + family: '"Segoe UI", "Helvetica Neue", "Trebuchet MS", Verdana, sans-serif', + size: 12, + weight: 400, + }, + }, + userId: userName ?? '', + } + } + + return ( + +
+ 0 ? initialSeries : [newSeriesValue()], + }} + validationSchema={schema} + onSubmit={(values, { setSubmitting }) => { + try { + onSave(values.series) + toast.push({'Chart güncellendi'}, { + placement: 'top-end', + }) + onClose() + } catch (error: any) { + toast.push( + + Hata + {error} + , + { placement: 'top-end' }, + ) + } finally { + setSubmitting(false) + } + }} + > + {({ setFieldValue, values, isSubmitting }) => ( +
+ + {/* Header */} +
+ +
+ {/* Kaydırılabilir içerik */} +
+ + {({ remove }) => ( +
+
+
#
+
Type
+
Name
+
Argument Field
+
Value Field
+
Summary Type
+
#
+
+ {values.series.map((_, index) => ( +
+
+
+ {values.series[index].index} +
+ +
+ + {({ field, form }: FieldProps) => ( + option.value === field.value, + )} + onChange={(option) => + form.setFieldValue(field.name, option?.value) + } + menuPlacement="auto" + maxMenuHeight={150} + /> + )} + +
+ +
+ + {({ field, form }: FieldProps) => ( + option.value === field.value, + )} + onChange={(option) => + form.setFieldValue(field.name, option?.value) + } + /> + )} + +
+ +
+
+
+
+ ))} +
+ )} +
+
+ {/* Footer */} +
+ +
+
+
+ )} +
+
+
+ ) +} + +export default ChartSeriesDialog diff --git a/ui/src/views/list/ChartSeriesDialog1.tsx b/ui/src/views/list/ChartSeriesDialog1.tsx new file mode 100644 index 00000000..82de65de --- /dev/null +++ b/ui/src/views/list/ChartSeriesDialog1.tsx @@ -0,0 +1,278 @@ +import { Button, FormContainer, Input, Notification, Select, Dialog, toast } from '@/components/ui' +import { Field, FieldArray, Form, Formik, FieldProps } from 'formik' +import { FaMinus, FaPlus } from 'react-icons/fa' +import { SelectBoxOption } from '@/shared/types' +import { + chartSeriesTypeOptions, + columnSummaryTypeListOptions, +} from '../admin/listForm/edit/options' +import { ChartSeriesDto } from '@/proxy/admin/charts/models' +import { useLocalization } from '@/utils/hooks/useLocalization' +import { useStoreState } from '@/store/store' +import { object, array, string } from 'yup' + +interface ChartSeriesDialog1 { + open: boolean + onClose: () => void + initialSeries: ChartSeriesDto[] + fieldList: SelectBoxOption[] + onSave: (series: ChartSeriesDto[]) => void +} + +const schema = object().shape({ + series: array().of( + object().shape({ + name: string().required('Name Required'), + argumentField: string().required('Argument Field Required'), + valueField: string().required('Value Field Required'), + summaryType: string().required('Summary Type Required'), + }), + ), +}) + +const ChartSeriesDialog1 = ({ + open, + onClose, + initialSeries, + fieldList, + onSave, +}: ChartSeriesDialog1) => { + const { translate } = useLocalization() + + // State UserId güncellemesi için + const { userName } = useStoreState((s) => s.auth.user) + + const newSeriesValue = () => { + return { + index: -1, + type: 'line', + name: '', + argumentField: '', + valueField: '', + summaryType: 'sum', + axis: '', + barOverlapGroup: '', + barPadding: 0, + barWidth: 0, + color: '', + cornerRadius: 0, + dashStyle: 'solid', + ignoreEmptyPoints: false, + pane: '', + rangeValue1Field: '', + rangeValue2Field: '', + selectionMode: 'none', + showInLegend: true, + visible: true, + width: 2, + label: { + visible: true, + backgroundColor: '#f05b41', + customizeText: '', + format: 'decimal', + font: { + color: '#FFFFFF', + family: '"Segoe UI", "Helvetica Neue", "Trebuchet MS", Verdana, sans-serif', + size: 12, + weight: 400, + }, + }, + userId: userName ?? '', + } + } + + return ( + +
+ 0 ? initialSeries : [newSeriesValue()], + }} + validationSchema={schema} + onSubmit={(values, { setSubmitting }) => { + try { + onSave(values.series) + toast.push({'Chart güncellendi'}, { + placement: 'top-end', + }) + onClose() + } catch (error: any) { + toast.push( + + Hata + {error} + , + { placement: 'top-end' }, + ) + } finally { + setSubmitting(false) + } + }} + > + {({ setFieldValue, values, isSubmitting }) => ( +
+ + {/* Header */} +
+ +
+ {/* Kaydırılabilir içerik */} +
+ + {({ remove }) => ( +
+
+
#
+
Type
+
Name
+
Argument Field
+
Value Field
+
Summary Type
+
#
+
+ {values.series.map((_, index) => ( +
+
+
+ {values.series[index].index} +
+ +
+ + {({ field, form }: FieldProps) => ( + option.value === field.value, + )} + onChange={(option) => + form.setFieldValue(field.name, option?.value) + } + menuPlacement="auto" + maxMenuHeight={150} + /> + )} + +
+ +
+ + {({ field, form }: FieldProps) => ( + option.value === field.value, + )} + onChange={(option) => + form.setFieldValue(field.name, option?.value) + } + /> + )} + +
+ +
+
+
+
+ ))} +
+ )} +
+
+ {/* Footer */} +
+ +
+
+
+ )} +
+
+
+ ) +} + +export default ChartSeriesDialog1 diff --git a/ui/src/views/list/List.tsx b/ui/src/views/list/List.tsx index 1c2a7bd2..57dadc2b 100644 --- a/ui/src/views/list/List.tsx +++ b/ui/src/views/list/List.tsx @@ -168,6 +168,7 @@ const List = () => { /> ) : viewMode === 'chart' ? (