Chart komponenti düzenlemesi
This commit is contained in:
parent
ae9ce38478
commit
e3a8165499
21 changed files with 823 additions and 247 deletions
|
|
@ -91,11 +91,6 @@ 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;
|
||||||
|
|
@ -126,4 +121,12 @@ public class ChartSeriesDto
|
||||||
// valueErrorBar
|
// valueErrorBar
|
||||||
|
|
||||||
public ChartLabelDto Label { get; set; }
|
public ChartLabelDto Label { 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";
|
||||||
|
/// <example>'Kullanıcı Adı'</example>
|
||||||
|
public string UserId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Kurs.Platform.Entities;
|
using Kurs.Platform.Entities;
|
||||||
|
|
@ -8,6 +9,7 @@ using Kurs.Platform.Queries;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Volo.Abp;
|
using Volo.Abp;
|
||||||
using Volo.Abp.Domain.Repositories;
|
using Volo.Abp.Domain.Repositories;
|
||||||
|
using Volo.Abp.Users;
|
||||||
using static Kurs.Platform.PlatformConsts;
|
using static Kurs.Platform.PlatformConsts;
|
||||||
|
|
||||||
namespace Kurs.Platform.ListForms.Administration;
|
namespace Kurs.Platform.ListForms.Administration;
|
||||||
|
|
@ -19,37 +21,121 @@ namespace Kurs.Platform.ListForms.Administration;
|
||||||
public class ListFormJsonRowAppService : PlatformAppService
|
public class ListFormJsonRowAppService : PlatformAppService
|
||||||
{
|
{
|
||||||
private readonly IRepository<ListForm, Guid> repository;
|
private readonly IRepository<ListForm, Guid> repository;
|
||||||
|
private readonly ICurrentUser currentUser;
|
||||||
|
private readonly string userId;
|
||||||
|
|
||||||
public ListFormJsonRowAppService(
|
public ListFormJsonRowAppService(
|
||||||
IRepository<ListForm, Guid> _repository) : base()
|
IRepository<ListForm, Guid> _repository,
|
||||||
|
ICurrentUser _currentUser
|
||||||
|
) : base()
|
||||||
{
|
{
|
||||||
repository = _repository;
|
repository = _repository;
|
||||||
|
currentUser = _currentUser;
|
||||||
|
userId = currentUser.Name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<dynamic> GetAllAsync(Guid id, string field)
|
public async Task<dynamic> GetAllAsync(Guid id, string field)
|
||||||
{
|
{
|
||||||
var listForm = await GetAsync(id);
|
var listForm = await GetAsync(id);
|
||||||
|
|
||||||
return field switch
|
switch (field)
|
||||||
{
|
{
|
||||||
ListFormEditTabs.Database.Select.SelectFieldsDefaultValuesJsonRow => listForm.SelectFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.SelectFieldsDefaultValueJson),
|
case ListFormEditTabs.Database.Select.SelectFieldsDefaultValuesJsonRow:
|
||||||
ListFormEditTabs.Database.Insert.InsertFieldsDefaultValuesJsonRow => listForm.InsertFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.InsertFieldsDefaultValueJson),
|
return listForm.SelectFieldsDefaultValueJson.IsNullOrWhiteSpace()
|
||||||
ListFormEditTabs.Database.Update.UpdateFieldsDefaultValuesJsonRow => listForm.UpdateFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.UpdateFieldsDefaultValueJson),
|
? []
|
||||||
ListFormEditTabs.Database.Delete.DeleteFieldsDefaultValuesJsonRow => listForm.DeleteFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.DeleteFieldsDefaultValueJson),
|
: JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.SelectFieldsDefaultValueJson) ?? [];
|
||||||
ListFormEditTabs.Database.Insert.FormFieldsDefaultValuesJsonRow => listForm.FormFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.FormFieldsDefaultValueJson),
|
|
||||||
ListFormEditTabs.Edit.EditingFormFieldsJsonRow => listForm.EditingFormJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<EditingFormDto>>(listForm.EditingFormJson),
|
|
||||||
ListFormEditTabs.CommandColumnsJsonRow => listForm.CommandColumnJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<CommandColumnDto>>(listForm.CommandColumnJson),
|
|
||||||
ListFormEditTabs.SubFormJsonRow => listForm.SubFormsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<SubFormDto>>(listForm.SubFormsJson),
|
|
||||||
ListFormEditTabs.WidgetForm => listForm.WidgetsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<WidgetEditDto>>(listForm.WidgetsJson),
|
|
||||||
ListFormEditTabs.ExtraFilterForm => listForm.ExtraFilterJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ExtraFilterEditDto>>(listForm.ExtraFilterJson),
|
|
||||||
|
|
||||||
ListFormEditTabs.ChartSeries.GeneralJsonRow => listForm.SeriesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartSeriesDto>>(listForm.SeriesJson),
|
case ListFormEditTabs.Database.Insert.InsertFieldsDefaultValuesJsonRow:
|
||||||
ListFormEditTabs.ChartAxis.ValueAxisJsonRow => listForm.ValueAxisJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartValueAxisDto>>(listForm.ValueAxisJson),
|
return listForm.InsertFieldsDefaultValueJson.IsNullOrWhiteSpace()
|
||||||
ListFormEditTabs.ChartPanes.PanesJsonRow => listForm.PanesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartPanesDto>>(listForm.PanesJson),
|
? []
|
||||||
ListFormEditTabs.ChartAnnotations.GeneralJsonRow => listForm.AnnotationsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartAnnotationDto>>(listForm.AnnotationsJson),
|
: JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.InsertFieldsDefaultValueJson) ?? [];
|
||||||
|
|
||||||
_ => throw new UserFriendlyException(L[AppErrorCodes.ParameterNotValid]),
|
case ListFormEditTabs.Database.Update.UpdateFieldsDefaultValuesJsonRow:
|
||||||
};
|
return listForm.UpdateFieldsDefaultValueJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.UpdateFieldsDefaultValueJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.Database.Delete.DeleteFieldsDefaultValuesJsonRow:
|
||||||
|
return listForm.DeleteFieldsDefaultValueJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.DeleteFieldsDefaultValueJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.Database.Insert.FormFieldsDefaultValuesJsonRow:
|
||||||
|
return listForm.FormFieldsDefaultValueJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.FormFieldsDefaultValueJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.Edit.EditingFormFieldsJsonRow:
|
||||||
|
return listForm.EditingFormJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<EditingFormDto>>(listForm.EditingFormJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.CommandColumnsJsonRow:
|
||||||
|
return listForm.CommandColumnJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<CommandColumnDto>>(listForm.CommandColumnJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.SubFormJsonRow:
|
||||||
|
return listForm.SubFormsJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<SubFormDto>>(listForm.SubFormsJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.WidgetForm:
|
||||||
|
return listForm.WidgetsJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<WidgetEditDto>>(listForm.WidgetsJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.ExtraFilterForm:
|
||||||
|
return listForm.ExtraFilterJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<ExtraFilterEditDto>>(listForm.ExtraFilterJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.ChartSeries.GeneralJsonRow:
|
||||||
|
return listForm.SeriesJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<ChartSeriesDto>>(listForm.SeriesJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.ChartAxis.ValueAxisJsonRow:
|
||||||
|
return listForm.ValueAxisJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<ChartValueAxisDto>>(listForm.ValueAxisJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.ChartPanes.PanesJsonRow:
|
||||||
|
return listForm.PanesJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<ChartPanesDto>>(listForm.PanesJson) ?? [];
|
||||||
|
|
||||||
|
case ListFormEditTabs.ChartAnnotations.GeneralJsonRow:
|
||||||
|
return listForm.AnnotationsJson.IsNullOrWhiteSpace()
|
||||||
|
? []
|
||||||
|
: JsonSerializer.Deserialize<List<ChartAnnotationDto>>(listForm.AnnotationsJson) ?? [];
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UserFriendlyException(L[AppErrorCodes.ParameterNotValid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return field switch
|
||||||
|
// {
|
||||||
|
// ListFormEditTabs.Database.Select.SelectFieldsDefaultValuesJsonRow => listForm.SelectFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.SelectFieldsDefaultValueJson),
|
||||||
|
// ListFormEditTabs.Database.Insert.InsertFieldsDefaultValuesJsonRow => listForm.InsertFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.InsertFieldsDefaultValueJson),
|
||||||
|
// ListFormEditTabs.Database.Update.UpdateFieldsDefaultValuesJsonRow => listForm.UpdateFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.UpdateFieldsDefaultValueJson),
|
||||||
|
// ListFormEditTabs.Database.Delete.DeleteFieldsDefaultValuesJsonRow => listForm.DeleteFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.DeleteFieldsDefaultValueJson),
|
||||||
|
// ListFormEditTabs.Database.Insert.FormFieldsDefaultValuesJsonRow => listForm.FormFieldsDefaultValueJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<FieldsDefaultValueDto>>(listForm.FormFieldsDefaultValueJson),
|
||||||
|
// ListFormEditTabs.Edit.EditingFormFieldsJsonRow => listForm.EditingFormJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<EditingFormDto>>(listForm.EditingFormJson),
|
||||||
|
// ListFormEditTabs.CommandColumnsJsonRow => listForm.CommandColumnJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<CommandColumnDto>>(listForm.CommandColumnJson),
|
||||||
|
// ListFormEditTabs.SubFormJsonRow => listForm.SubFormsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<SubFormDto>>(listForm.SubFormsJson),
|
||||||
|
// ListFormEditTabs.WidgetForm => listForm.WidgetsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<WidgetEditDto>>(listForm.WidgetsJson),
|
||||||
|
// ListFormEditTabs.ExtraFilterForm => listForm.ExtraFilterJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ExtraFilterEditDto>>(listForm.ExtraFilterJson),
|
||||||
|
|
||||||
|
// ListFormEditTabs.ChartSeries.GeneralJsonRow => listForm.SeriesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartSeriesDto>>(listForm.SeriesJson),
|
||||||
|
// ListFormEditTabs.ChartAxis.ValueAxisJsonRow => listForm.ValueAxisJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartValueAxisDto>>(listForm.ValueAxisJson),
|
||||||
|
// ListFormEditTabs.ChartPanes.PanesJsonRow => listForm.PanesJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartPanesDto>>(listForm.PanesJson),
|
||||||
|
// ListFormEditTabs.ChartAnnotations.GeneralJsonRow => listForm.AnnotationsJson.IsNullOrWhiteSpace() ? [] : JsonSerializer.Deserialize<List<ChartAnnotationDto>>(listForm.AnnotationsJson),
|
||||||
|
|
||||||
|
// _ => throw new UserFriendlyException(L[AppErrorCodes.ParameterNotValid]),
|
||||||
|
// };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task CreateAsync(Guid id, CrudFieldsDefaultValueJsonItemDto model)
|
public async Task CreateAsync(Guid id, CrudFieldsDefaultValueJsonItemDto model)
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,10 @@ public class ChartSeries : ValueObject
|
||||||
[JsonPropertyName("Label")]
|
[JsonPropertyName("Label")]
|
||||||
public ChartLabel Label { get; private set; } = new();
|
public ChartLabel Label { get; private set; } = new();
|
||||||
|
|
||||||
|
[JsonInclude]
|
||||||
|
[JsonPropertyName("UserId")]
|
||||||
|
public string UserId { get; private set; }
|
||||||
|
|
||||||
// JSON + EF Core için parametresiz public ctor
|
// JSON + EF Core için parametresiz public ctor
|
||||||
public ChartSeries() { }
|
public ChartSeries() { }
|
||||||
|
|
||||||
|
|
@ -116,5 +120,6 @@ public class ChartSeries : ValueObject
|
||||||
yield return Visible;
|
yield return Visible;
|
||||||
yield return Width;
|
yield return Width;
|
||||||
yield return Label;
|
yield return Label;
|
||||||
|
yield return UserId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -766,8 +766,8 @@ public class SelectQueryManager : PlatformDomainService, ISelectQueryManager
|
||||||
|
|
||||||
var seriesList = JsonSerializer.Deserialize<List<ChartSeries>>(listform.SeriesJson);
|
var seriesList = JsonSerializer.Deserialize<List<ChartSeries>>(listform.SeriesJson);
|
||||||
|
|
||||||
if (seriesList == null || !seriesList.Any())
|
if (seriesList == null || seriesList.Count == 0)
|
||||||
throw new ArgumentException("Series list is empty!");
|
return null;
|
||||||
|
|
||||||
// ArgumentField listesi
|
// ArgumentField listesi
|
||||||
var argumentFields = seriesList.Select(s => s.ArgumentField).Distinct().ToList();
|
var argumentFields = seriesList.Select(s => s.ArgumentField).Distinct().ToList();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { AuditedEntityDto } from '@/proxy/abp'
|
import { AuditedEntityDto } from '@/proxy/abp'
|
||||||
import { PermissionCrudDto } from '@/proxy/form/models'
|
import { PermissionCrudDto, SummaryTypeEnum } from '@/proxy/form/models'
|
||||||
|
|
||||||
export interface BreakDto {
|
export interface BreakDto {
|
||||||
endValue: number
|
endValue: number
|
||||||
|
|
@ -299,6 +299,7 @@ export interface ChartScrollBarDto {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChartSeriesDto {
|
export interface ChartSeriesDto {
|
||||||
|
index: number
|
||||||
argumentField?: string
|
argumentField?: string
|
||||||
axis?: string
|
axis?: string
|
||||||
barOverlapGroup?: string
|
barOverlapGroup?: string
|
||||||
|
|
@ -316,10 +317,11 @@ export interface ChartSeriesDto {
|
||||||
showInLegend: boolean
|
showInLegend: boolean
|
||||||
type?: string
|
type?: string
|
||||||
valueField?: string
|
valueField?: string
|
||||||
summaryType?: string
|
summaryType?: SummaryTypeEnum
|
||||||
visible: boolean
|
visible: boolean
|
||||||
width: number
|
width: number
|
||||||
label: ChartLabelDto
|
label: ChartLabelDto
|
||||||
|
userId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChartSizeDto {
|
export interface ChartSizeDto {
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import {
|
||||||
ChartZoomAndPanDto,
|
ChartZoomAndPanDto,
|
||||||
} from '../admin/charts/models'
|
} from '../admin/charts/models'
|
||||||
import { ListViewLayoutType } from '@/views/admin/listForm/edit/types'
|
import { ListViewLayoutType } from '@/views/admin/listForm/edit/types'
|
||||||
|
import { SeriesType } from 'devextreme/common/charts'
|
||||||
|
|
||||||
//1
|
//1
|
||||||
export interface SelectListItem {
|
export interface SelectListItem {
|
||||||
|
|
@ -367,30 +368,7 @@ export interface GridPivotOptionDto {
|
||||||
showFilterFields: boolean
|
showFilterFields: boolean
|
||||||
showChart: boolean
|
showChart: boolean
|
||||||
chartHeight: number
|
chartHeight: number
|
||||||
chartCommonSeriesType:
|
chartCommonSeriesType: SeriesType
|
||||||
| 'area'
|
|
||||||
| 'bar'
|
|
||||||
| 'bubble'
|
|
||||||
| 'candlestick'
|
|
||||||
| 'fullstackedarea'
|
|
||||||
| 'fullstackedbar'
|
|
||||||
| 'fullstackedline'
|
|
||||||
| 'fullstackedspline'
|
|
||||||
| 'fullstackedsplinearea'
|
|
||||||
| 'line'
|
|
||||||
| 'rangearea'
|
|
||||||
| 'rangebar'
|
|
||||||
| 'scatter'
|
|
||||||
| 'spline'
|
|
||||||
| 'splinearea'
|
|
||||||
| 'stackedarea'
|
|
||||||
| 'stackedbar'
|
|
||||||
| 'stackedline'
|
|
||||||
| 'stackedspline'
|
|
||||||
| 'stackedsplinearea'
|
|
||||||
| 'steparea'
|
|
||||||
| 'stepline'
|
|
||||||
| 'stock'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GridEditingDto {
|
export interface GridEditingDto {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import {
|
||||||
Tabs,
|
Tabs,
|
||||||
Notification,
|
Notification,
|
||||||
toast,
|
toast,
|
||||||
|
Badge,
|
||||||
} from '@/components/ui'
|
} from '@/components/ui'
|
||||||
import TBody from '@/components/ui/Table/TBody'
|
import TBody from '@/components/ui/Table/TBody'
|
||||||
import THead from '@/components/ui/Table/THead'
|
import THead from '@/components/ui/Table/THead'
|
||||||
|
|
@ -153,6 +154,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Th>
|
</Th>
|
||||||
|
<Th></Th>
|
||||||
<Th>Type</Th>
|
<Th>Type</Th>
|
||||||
<Th>Name</Th>
|
<Th>Name</Th>
|
||||||
<Th>Argument Field</Th>
|
<Th>Argument Field</Th>
|
||||||
|
|
@ -204,6 +206,7 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Td>
|
</Td>
|
||||||
|
<Td>{row.userId && <Badge content={row.userId} />}</Td>
|
||||||
<Td>{row.type}</Td>
|
<Td>{row.type}</Td>
|
||||||
<Td>{row.name}</Td>
|
<Td>{row.name}</Td>
|
||||||
<Td>{row.argumentField}</Td>
|
<Td>{row.argumentField}</Td>
|
||||||
|
|
@ -320,7 +323,10 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Argument Field"
|
label="Argument Field"
|
||||||
invalid={errors.commonSeriesSettingsDto?.argumentField && touched.commonSeriesSettingsDto?.argumentField}
|
invalid={
|
||||||
|
errors.commonSeriesSettingsDto?.argumentField &&
|
||||||
|
touched.commonSeriesSettingsDto?.argumentField
|
||||||
|
}
|
||||||
errorMessage={errors.commonSeriesSettingsDto?.argumentField}
|
errorMessage={errors.commonSeriesSettingsDto?.argumentField}
|
||||||
>
|
>
|
||||||
<Field type="text" name="commonSeriesSettingsDto.argumentField">
|
<Field type="text" name="commonSeriesSettingsDto.argumentField">
|
||||||
|
|
@ -331,7 +337,10 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
form={form}
|
form={form}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
options={fieldList}
|
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)}
|
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||||
menuPlacement="auto"
|
menuPlacement="auto"
|
||||||
maxMenuHeight={150}
|
maxMenuHeight={150}
|
||||||
|
|
@ -342,7 +351,10 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Value Field"
|
label="Value Field"
|
||||||
invalid={errors.commonSeriesSettingsDto?.valueField && touched.commonSeriesSettingsDto?.valueField}
|
invalid={
|
||||||
|
errors.commonSeriesSettingsDto?.valueField &&
|
||||||
|
touched.commonSeriesSettingsDto?.valueField
|
||||||
|
}
|
||||||
errorMessage={errors.commonSeriesSettingsDto?.valueField}
|
errorMessage={errors.commonSeriesSettingsDto?.valueField}
|
||||||
>
|
>
|
||||||
<Field type="text" name="valueField">
|
<Field type="text" name="valueField">
|
||||||
|
|
@ -353,7 +365,9 @@ function ChartTabSeries(props: FormEditProps & { listFormCode: string }) {
|
||||||
form={form}
|
form={form}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
options={fieldList}
|
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)}
|
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||||
menuPlacement="auto"
|
menuPlacement="auto"
|
||||||
maxMenuHeight={150}
|
maxMenuHeight={150}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ function JsonRowOpDialogAnnotation({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<Tabs defaultValue="annotations_general">
|
<Tabs defaultValue="annotations_general">
|
||||||
<TabList>
|
<TabList>
|
||||||
<TabNav value="annotations_general">General</TabNav>
|
<TabNav value="annotations_general">General</TabNav>
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ function JsonRowOpDialogAxis({
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Visible"
|
label="Visible"
|
||||||
invalid={errors.visible && touched.visible}
|
invalid={errors.visible && touched.visible}
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@ function JsonRowOpDialogCommand({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Button Position"
|
label="Button Position"
|
||||||
invalid={errors.buttonPosition && touched.buttonPosition}
|
invalid={errors.buttonPosition && touched.buttonPosition}
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ function JsonRowOpDialogDatabase({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Field Name"
|
label="Field Name"
|
||||||
invalid={errors.fieldName && touched.fieldName}
|
invalid={errors.fieldName && touched.fieldName}
|
||||||
|
|
|
||||||
|
|
@ -197,7 +197,7 @@ function JsonRowOpDialogEditForm({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-[90vh] overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<div className="grid grid-cols-5 gap-4 w-full">
|
<div className="grid grid-cols-5 gap-4 w-full">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Order"
|
label="Order"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import {
|
||||||
Select,
|
Select,
|
||||||
toast,
|
toast,
|
||||||
} from '@/components/ui'
|
} from '@/components/ui'
|
||||||
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
|
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
|
||||||
import { SelectBoxOption } from '@/shared/types'
|
import { SelectBoxOption } from '@/shared/types'
|
||||||
import { useStoreActions, useStoreState } from '@/store'
|
import { useStoreActions, useStoreState } from '@/store'
|
||||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||||
|
|
@ -177,7 +177,7 @@ function JsonRowOpDialogExtraFilter({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-full overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Field Name"
|
label="Field Name"
|
||||||
invalid={errors.fieldName && touched.fieldName}
|
invalid={errors.fieldName && touched.fieldName}
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ function JsonRowOpDialogPane({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Name"
|
label="Name"
|
||||||
invalid={errors.name && touched.name}
|
invalid={errors.name && touched.name}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import {
|
||||||
chartSeriesTypeOptions,
|
chartSeriesTypeOptions,
|
||||||
columnSummaryTypeListOptions,
|
columnSummaryTypeListOptions,
|
||||||
} from '../options'
|
} from '../options'
|
||||||
import { ChartPanesDto, ChartSeriesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models'
|
import { ChartPanesDto, ChartValueAxisDto } from '@/proxy/admin/charts/models'
|
||||||
import CreatableSelect from 'react-select/creatable'
|
import CreatableSelect from 'react-select/creatable'
|
||||||
|
|
||||||
const schema = object().shape({
|
const schema = object().shape({
|
||||||
|
|
@ -134,6 +134,7 @@ function JsonRowOpDialogSeries({
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={
|
initialValues={
|
||||||
data.chartSeriesValues ?? {
|
data.chartSeriesValues ?? {
|
||||||
|
index: -1,
|
||||||
argumentField: '',
|
argumentField: '',
|
||||||
axis: '',
|
axis: '',
|
||||||
barOverlapGroup: '',
|
barOverlapGroup: '',
|
||||||
|
|
@ -204,7 +205,7 @@ function JsonRowOpDialogSeries({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Visible"
|
label="Visible"
|
||||||
invalid={errors.visible && touched.visible}
|
invalid={errors.visible && touched.visible}
|
||||||
|
|
@ -266,7 +267,6 @@ function JsonRowOpDialogSeries({
|
||||||
<Field type="text" name="argumentField">
|
<Field type="text" name="argumentField">
|
||||||
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
<Select
|
<Select
|
||||||
componentAs={CreatableSelect}
|
|
||||||
field={field}
|
field={field}
|
||||||
form={form}
|
form={form}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
|
|
@ -290,7 +290,6 @@ function JsonRowOpDialogSeries({
|
||||||
<Field type="text" name="valueField">
|
<Field type="text" name="valueField">
|
||||||
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
<Select
|
<Select
|
||||||
componentAs={CreatableSelect}
|
|
||||||
field={field}
|
field={field}
|
||||||
form={form}
|
form={form}
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
|
|
@ -306,10 +305,7 @@ function JsonRowOpDialogSeries({
|
||||||
|
|
||||||
<FormItem
|
<FormItem
|
||||||
label={translate('::ListForms.ListFormFieldEdit.PivotSettingSummaryType')}
|
label={translate('::ListForms.ListFormFieldEdit.PivotSettingSummaryType')}
|
||||||
invalid={
|
invalid={errors.summaryType && touched.summaryType}
|
||||||
errors.summaryType &&
|
|
||||||
touched.summaryType
|
|
||||||
}
|
|
||||||
errorMessage={errors.summaryType}
|
errorMessage={errors.summaryType}
|
||||||
>
|
>
|
||||||
<Field
|
<Field
|
||||||
|
|
@ -327,8 +323,7 @@ function JsonRowOpDialogSeries({
|
||||||
isClearable={true}
|
isClearable={true}
|
||||||
options={columnSummaryTypeListOptions}
|
options={columnSummaryTypeListOptions}
|
||||||
value={columnSummaryTypeListOptions.filter(
|
value={columnSummaryTypeListOptions.filter(
|
||||||
(option: any) =>
|
(option: any) => option.value === values.summaryType,
|
||||||
option.value === values.summaryType,
|
|
||||||
)}
|
)}
|
||||||
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
onChange={(option) => form.setFieldValue(field.name, option?.value)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ function JsonRowOpDialogSubForm({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-96 overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Tab Title"
|
label="Tab Title"
|
||||||
invalid={errors.tabTitle && touched.tabTitle}
|
invalid={errors.tabTitle && touched.tabTitle}
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ function JsonRowOpDialogWidget({
|
||||||
{({ touched, errors, values, isSubmitting }) => (
|
{({ touched, errors, values, isSubmitting }) => (
|
||||||
<Form>
|
<Form>
|
||||||
<FormContainer size="sm">
|
<FormContainer size="sm">
|
||||||
<div className="max-h-full overflow-y-auto p-2">
|
<div className="h-full overflow-y-auto p-2">
|
||||||
<FormItem
|
<FormItem
|
||||||
label="Column Gap (Sütun Boşluğu)"
|
label="Column Gap (Sütun Boşluğu)"
|
||||||
invalid={errors.colGap && touched.colGap}
|
invalid={errors.colGap && touched.colGap}
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,27 @@ 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 { usePermission } from '@/utils/hooks/usePermission'
|
||||||
import { Button, FormContainer, FormItem, Input, toast, Notification, Dialog } from '@/components/ui'
|
import { Button, toast, Notification } from '@/components/ui'
|
||||||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||||||
import { usePWA } from '@/utils/hooks/usePWA'
|
import { usePWA } from '@/utils/hooks/usePWA'
|
||||||
import { FaCog, FaCrosshairs, FaMinus, FaPlus, FaSearch, FaSyncAlt } from 'react-icons/fa'
|
import { FaCog, FaCrosshairs, FaMinus, FaPlus, FaSearch, FaSyncAlt } from 'react-icons/fa'
|
||||||
import { buildSeriesDto } from './Utils'
|
import { buildSeriesDto } from './Utils'
|
||||||
import { ChartSeriesDto } from '@/proxy/admin/charts/models'
|
import { ChartSeriesDto } from '@/proxy/admin/charts/models'
|
||||||
import { Formik, Form, Field, FieldArray, useFormikContext } from 'formik' // sadece buradan Form
|
import { SelectBoxOption } from '@/shared/types'
|
||||||
import { object, string, array } from 'yup'
|
import { useStoreState } from '@/store/store'
|
||||||
|
import ChartSeriesDialog from './ChartSeriesDialog'
|
||||||
|
import { getListFormFields } from '@/services/admin/list-form-field.service'
|
||||||
|
import { groupBy } from 'lodash'
|
||||||
|
import { ListFormJsonRowDto } from '@/proxy/admin/list-form/models'
|
||||||
|
import { ListFormEditTabs } from '@/proxy/admin/list-form/options'
|
||||||
|
import {
|
||||||
|
deleteListFormJsonRow,
|
||||||
|
postListFormJsonRow,
|
||||||
|
putListFormJsonRow,
|
||||||
|
} from '@/services/admin/list-form.service'
|
||||||
|
|
||||||
interface ChartProps extends CommonProps, Meta {
|
interface ChartProps extends CommonProps, Meta {
|
||||||
|
id: string
|
||||||
listFormCode: string
|
listFormCode: string
|
||||||
filter?: string
|
filter?: string
|
||||||
isSubForm?: boolean
|
isSubForm?: boolean
|
||||||
|
|
@ -30,11 +41,12 @@ interface ChartProps extends CommonProps, Meta {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Chart = (props: ChartProps) => {
|
const Chart = (props: ChartProps) => {
|
||||||
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 { translate } = useLocalization()
|
||||||
const { checkPermission } = usePermission()
|
const { checkPermission } = usePermission()
|
||||||
const isPwaMode = usePWA()
|
const isPwaMode = usePWA()
|
||||||
const [series, setSeries] = useState<ChartSeriesDto[]>([])
|
|
||||||
const initialized = useRef(false)
|
const initialized = useRef(false)
|
||||||
|
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
|
|
@ -44,38 +56,45 @@ const Chart = (props: ChartProps) => {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
|
const _listFormCode = props?.listFormCode ?? params?.listFormCode ?? ''
|
||||||
|
|
||||||
|
const [openDialog, setOpenDialog] = useState(false)
|
||||||
|
const [fieldList, setFieldList] = useState<SelectBoxOption[]>([])
|
||||||
|
|
||||||
const [searchText, setSearchText] = useState('')
|
const [searchText, setSearchText] = useState('')
|
||||||
const [prevValue, setPrevValue] = useState('')
|
const [prevValue, setPrevValue] = useState('')
|
||||||
const [urlSearchParams, setUrlSearchParams] = useState<URLSearchParams>(
|
const [urlSearchParams, setUrlSearchParams] = useState<URLSearchParams>(
|
||||||
searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(),
|
searchParams ? new URLSearchParams(searchParams) : new URLSearchParams(),
|
||||||
)
|
)
|
||||||
|
|
||||||
const schema = object().shape({
|
const [allSeries, setAllSeries] = useState<ChartSeriesDto[]>([])
|
||||||
series: array().of(
|
|
||||||
object().shape({
|
const [userSeries, setUserSeries] = useState<ChartSeriesDto[]>([])
|
||||||
name: string().required('Name Required'),
|
const [oldSeries, setOldSeries] = useState<ChartSeriesDto[]>([])
|
||||||
argumentField: string().required('Argument Field Required'),
|
|
||||||
valueField: string().required('Value Field Required'),
|
useEffect(() => {
|
||||||
summaryType: string().required('Summary Type Required'),
|
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(() => {
|
useEffect(() => {
|
||||||
if (!gridDto) return
|
if (!gridDto) return
|
||||||
|
if (!allSeries) return
|
||||||
|
if (!initialized.current) return
|
||||||
|
|
||||||
|
const seriesDto = userSeries.length > 0 ? userSeries : allSeries.length > 0 ? allSeries : []
|
||||||
|
|
||||||
const gridOptions = {
|
const gridOptions = {
|
||||||
...gridDto.gridOptions,
|
...gridDto.gridOptions,
|
||||||
seriesDto: series ?? gridDto.gridOptions.seriesDto,
|
seriesDto,
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataSource = createSelectDataSource(
|
const dataSource = createSelectDataSource(gridOptions, listFormCode, urlSearchParams, [], true)
|
||||||
gridOptions,
|
|
||||||
listFormCode,
|
|
||||||
urlSearchParams,
|
|
||||||
[],
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
dataSource: dataSource,
|
dataSource: dataSource,
|
||||||
|
|
@ -106,7 +125,7 @@ const Chart = (props: ChartProps) => {
|
||||||
valueAxis: gridDto.gridOptions.valueAxisDto,
|
valueAxis: gridDto.gridOptions.valueAxisDto,
|
||||||
tooltip: gridDto.gridOptions.tooltipDto,
|
tooltip: gridDto.gridOptions.tooltipDto,
|
||||||
|
|
||||||
series: buildSeriesDto(series ?? gridDto.gridOptions.seriesDto),
|
series: buildSeriesDto(seriesDto),
|
||||||
|
|
||||||
panes: gridDto.gridOptions.panesDto?.length > 0 ? gridDto.gridOptions.panesDto : undefined,
|
panes: gridDto.gridOptions.panesDto?.length > 0 ? gridDto.gridOptions.panesDto : undefined,
|
||||||
commonSeriesSettings: gridDto.gridOptions.commonSeriesSettingsDto,
|
commonSeriesSettings: gridDto.gridOptions.commonSeriesSettingsDto,
|
||||||
|
|
@ -121,7 +140,7 @@ const Chart = (props: ChartProps) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
setChartOptions(options)
|
setChartOptions(options)
|
||||||
}, [gridDto, series, searchParams, urlSearchParams])
|
}, [gridDto, allSeries, initialized.current, searchParams, urlSearchParams])
|
||||||
|
|
||||||
const onFilter = useCallback(
|
const onFilter = useCallback(
|
||||||
(value?: string) => {
|
(value?: string) => {
|
||||||
|
|
@ -169,50 +188,64 @@ const Chart = (props: ChartProps) => {
|
||||||
[gridDto, urlSearchParams, searchText],
|
[gridDto, urlSearchParams, searchText],
|
||||||
)
|
)
|
||||||
|
|
||||||
const newSeriesValue = () => {
|
const getFields = async () => {
|
||||||
return {
|
if (!props.listFormCode) return
|
||||||
argumentField: '',
|
try {
|
||||||
axis: '',
|
const resp = await getListFormFields({
|
||||||
barOverlapGroup: '',
|
listFormCode: props.listFormCode,
|
||||||
barPadding: 0,
|
sorting: 'ListOrderNo',
|
||||||
barWidth: 0,
|
maxResultCount: 1000,
|
||||||
color: '',
|
})
|
||||||
cornerRadius: 0,
|
if (resp.data?.items) {
|
||||||
dashStyle: 'solid',
|
const fieldNames = groupBy(resp?.data?.items, 'fieldName')
|
||||||
ignoreEmptyPoints: false,
|
setFieldList(Object.keys(fieldNames).map((a) => ({ value: a, label: a })))
|
||||||
name: '',
|
}
|
||||||
pane: '',
|
} catch (error: any) {
|
||||||
rangeValue1Field: '',
|
toast.push(
|
||||||
rangeValue2Field: '',
|
<Notification type="danger" duration={2000}>
|
||||||
selectionMode: 'none',
|
Alanlar getirilemedi {error.toString()}
|
||||||
showInLegend: true,
|
</Notification>,
|
||||||
type: 'line',
|
{ placement: 'top-end' },
|
||||||
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,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (gridDto && !initialized.current) {
|
if (props.listFormCode) getFields()
|
||||||
setSeries(gridDto.gridOptions.seriesDto)
|
}, [props.listFormCode])
|
||||||
initialized.current = true
|
|
||||||
}
|
|
||||||
}, [gridDto])
|
|
||||||
|
|
||||||
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 (
|
return (
|
||||||
<Container className={DX_CLASSNAMES}>
|
<Container className={DX_CLASSNAMES}>
|
||||||
|
|
@ -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"
|
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"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
variant={'default'}
|
variant={'default'}
|
||||||
className="text-sm"
|
className="text-sm"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setSeries(gridDto?.gridOptions?.seriesDto ?? [])
|
initialized.current = false
|
||||||
await props.refreshGridDto()
|
await refreshGridDto()
|
||||||
}}
|
}}
|
||||||
title="Refresh Data"
|
title="Refresh Data"
|
||||||
>
|
>
|
||||||
<FaSyncAlt className="w-3 h-3" />
|
<FaSyncAlt className="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
variant="default"
|
variant="default"
|
||||||
className="text-sm"
|
className="text-sm"
|
||||||
onClick={() => setOpenDialog(true)}
|
onClick={() => setOpenDialog(true)}
|
||||||
title="Edit Series"
|
title="Series Özelleştir"
|
||||||
>
|
>
|
||||||
<FaCrosshairs className="w-3 h-3" />
|
<FaCrosshairs className="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -299,109 +330,13 @@ const Chart = (props: ChartProps) => {
|
||||||
</div>
|
</div>
|
||||||
<DxChart key={'DxChart' + _listFormCode} {...chartOptions}></DxChart>
|
<DxChart key={'DxChart' + _listFormCode} {...chartOptions}></DxChart>
|
||||||
|
|
||||||
<Dialog isOpen={openDialog} onClose={() => setOpenDialog(false)} width={600}>
|
<ChartSeriesDialog
|
||||||
<Formik
|
open={openDialog}
|
||||||
enableReinitialize
|
onClose={() => setOpenDialog(false)}
|
||||||
initialValues={{
|
initialSeries={allSeries.filter((s) => s.userId === userName)}
|
||||||
series: series && series.length > 0 ? series : [newSeriesValue()],
|
fieldList={fieldList}
|
||||||
}}
|
onSave={onSave}
|
||||||
validationSchema={schema}
|
/>
|
||||||
onSubmit={(values, { setSubmitting }) => {
|
|
||||||
setSeries(values.series)
|
|
||||||
|
|
||||||
setSubmitting(true)
|
|
||||||
try {
|
|
||||||
toast.push(<Notification type="success">{'Chart güncellendi'}</Notification>, {
|
|
||||||
placement: 'top-end',
|
|
||||||
})
|
|
||||||
setOpenDialog(false) // kaydettikten sonra dialogu kapat
|
|
||||||
} catch (error: any) {
|
|
||||||
toast.push(
|
|
||||||
<Notification type="danger">
|
|
||||||
Hata
|
|
||||||
<code>{error}</code>
|
|
||||||
</Notification>,
|
|
||||||
{ placement: 'top-end' },
|
|
||||||
)
|
|
||||||
} finally {
|
|
||||||
setSubmitting(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{({ setFieldValue, values, isSubmitting }) => (
|
|
||||||
<Form className="flex flex-col h-full">
|
|
||||||
<FormContainer size="sm" className="flex flex-col h-full">
|
|
||||||
{/* Kaydırılabilir içerik */}
|
|
||||||
<div className="flex-1 overflow-y-auto p-2">
|
|
||||||
<FieldArray name="series">
|
|
||||||
{({ remove }) => (
|
|
||||||
<div>
|
|
||||||
{values.series.map((_, index) => (
|
|
||||||
<div key={index} className="mb-2 border-b pb-2">
|
|
||||||
<FormItem label="Name">
|
|
||||||
<Field
|
|
||||||
name={`series[${index}].name`}
|
|
||||||
type="text"
|
|
||||||
component={Input}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Argument Field">
|
|
||||||
<Field
|
|
||||||
name={`series[${index}].argumentField`}
|
|
||||||
type="text"
|
|
||||||
component={Input}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Value Field">
|
|
||||||
<Field
|
|
||||||
name={`series[${index}].valueField`}
|
|
||||||
type="text"
|
|
||||||
component={Input}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
<FormItem label="Summary Type">
|
|
||||||
<Field
|
|
||||||
name={`series[${index}].summaryType`}
|
|
||||||
type="text"
|
|
||||||
component={Input}
|
|
||||||
/>
|
|
||||||
</FormItem>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
shape="circle"
|
|
||||||
type="button"
|
|
||||||
className="mt-2"
|
|
||||||
size="xs"
|
|
||||||
icon={<FaMinus />}
|
|
||||||
onClick={() => remove(index)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</FieldArray>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Footer */}
|
|
||||||
<div className="flex gap-2 mt-auto pt-2 border-t text-right">
|
|
||||||
<Button
|
|
||||||
variant="default"
|
|
||||||
type="button"
|
|
||||||
onClick={() =>
|
|
||||||
setFieldValue('series', [...values.series, newSeriesValue()])
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FaPlus />
|
|
||||||
</Button>
|
|
||||||
<Button block variant="solid" loading={isSubmitting} type="submit">
|
|
||||||
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</FormContainer>
|
|
||||||
</Form>
|
|
||||||
)}
|
|
||||||
</Formik>
|
|
||||||
</Dialog>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
||||||
279
ui/src/views/list/ChartSeriesDialog.tsx
Normal file
279
ui/src/views/list/ChartSeriesDialog.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<Dialog isOpen={open} onClose={onClose} width={1200}>
|
||||||
|
<div className="flex flex-col bg-white p-4 h-[600px]">
|
||||||
|
<Formik
|
||||||
|
enableReinitialize
|
||||||
|
initialValues={{
|
||||||
|
series: initialSeries && initialSeries.length > 0 ? initialSeries : [newSeriesValue()],
|
||||||
|
}}
|
||||||
|
validationSchema={schema}
|
||||||
|
onSubmit={(values, { setSubmitting }) => {
|
||||||
|
try {
|
||||||
|
onSave(values.series)
|
||||||
|
toast.push(<Notification type="success">{'Chart güncellendi'}</Notification>, {
|
||||||
|
placement: 'top-end',
|
||||||
|
})
|
||||||
|
onClose()
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.push(
|
||||||
|
<Notification type="danger">
|
||||||
|
Hata
|
||||||
|
<code>{error}</code>
|
||||||
|
</Notification>,
|
||||||
|
{ placement: 'top-end' },
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ setFieldValue, values, isSubmitting }) => (
|
||||||
|
<Form className="flex flex-col h-full">
|
||||||
|
<FormContainer size="sm" className="flex flex-col h-full">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-2 pb-2 border-b flex items-center justify-between">
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
shape="circle"
|
||||||
|
type="button"
|
||||||
|
size="xs"
|
||||||
|
onClick={() => setFieldValue('series', [...values.series, newSeriesValue()])}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<FaPlus /> Seri Ekle
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{/* Kaydırılabilir içerik */}
|
||||||
|
<div className="flex-1 overflow-y-auto p-1">
|
||||||
|
<FieldArray name="series">
|
||||||
|
{({ remove }) => (
|
||||||
|
<div>
|
||||||
|
<div className="grid grid-cols-12 gap-2 font-semibold text-xs py-2">
|
||||||
|
<div className="text-center col-span-1">#</div>
|
||||||
|
<div className="text-center col-span-2">Type</div>
|
||||||
|
<div className="text-center col-span-2">Name</div>
|
||||||
|
<div className="text-center col-span-2">Argument Field</div>
|
||||||
|
<div className="text-center col-span-2">Value Field</div>
|
||||||
|
<div className="text-center col-span-2">Summary Type</div>
|
||||||
|
<div className="text-center col-span-1">#</div>
|
||||||
|
</div>
|
||||||
|
{values.series.map((_, index) => (
|
||||||
|
<div key={index} className="border-b py-1">
|
||||||
|
<div className="grid grid-cols-12 gap-1 items-center">
|
||||||
|
<div className="text-center text-xs col-span-1">
|
||||||
|
{values.series[index].index}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field name={`series[${index}].type`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
options={chartSeriesTypeOptions}
|
||||||
|
isClearable
|
||||||
|
value={chartSeriesTypeOptions.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field
|
||||||
|
size="sm"
|
||||||
|
name={`series[${index}].name`}
|
||||||
|
type="text"
|
||||||
|
component={Input}
|
||||||
|
className="text-xs px-1 py-0 grid-cols-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field type="text" name={`series[${index}].argumentField`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={fieldList}
|
||||||
|
value={fieldList?.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
menuPlacement="auto"
|
||||||
|
maxMenuHeight={150}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field type="text" name={`series[${index}].valueField`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={fieldList}
|
||||||
|
value={fieldList?.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
menuPlacement="auto"
|
||||||
|
maxMenuHeight={150}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field type="text" name={`series[${index}].summaryType`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={columnSummaryTypeListOptions}
|
||||||
|
value={columnSummaryTypeListOptions.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-center gap-1 col-span-1">
|
||||||
|
<Button
|
||||||
|
shape="circle"
|
||||||
|
type="button"
|
||||||
|
size="xs"
|
||||||
|
icon={<FaMinus />}
|
||||||
|
className="bg-slate-100 hover:bg-red-100"
|
||||||
|
onClick={() => remove(index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</FieldArray>
|
||||||
|
</div>
|
||||||
|
{/* Footer */}
|
||||||
|
<div className="flex gap-2 mt-auto pt-2 border-t text-right justify-end">
|
||||||
|
<Button
|
||||||
|
variant="solid"
|
||||||
|
loading={isSubmitting}
|
||||||
|
type="submit"
|
||||||
|
className="ml-auto px-4 py-1 text-sm rounded"
|
||||||
|
>
|
||||||
|
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</FormContainer>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChartSeriesDialog
|
||||||
278
ui/src/views/list/ChartSeriesDialog1.tsx
Normal file
278
ui/src/views/list/ChartSeriesDialog1.tsx
Normal file
|
|
@ -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 (
|
||||||
|
<Dialog isOpen={open} onClose={onClose} width={1200}>
|
||||||
|
<div className="flex flex-col bg-white p-4 h-[600px]">
|
||||||
|
<Formik
|
||||||
|
enableReinitialize
|
||||||
|
initialValues={{
|
||||||
|
series: initialSeries && initialSeries.length > 0 ? initialSeries : [newSeriesValue()],
|
||||||
|
}}
|
||||||
|
validationSchema={schema}
|
||||||
|
onSubmit={(values, { setSubmitting }) => {
|
||||||
|
try {
|
||||||
|
onSave(values.series)
|
||||||
|
toast.push(<Notification type="success">{'Chart güncellendi'}</Notification>, {
|
||||||
|
placement: 'top-end',
|
||||||
|
})
|
||||||
|
onClose()
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.push(
|
||||||
|
<Notification type="danger">
|
||||||
|
Hata
|
||||||
|
<code>{error}</code>
|
||||||
|
</Notification>,
|
||||||
|
{ placement: 'top-end' },
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
setSubmitting(false)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ setFieldValue, values, isSubmitting }) => (
|
||||||
|
<Form className="flex flex-col h-full">
|
||||||
|
<FormContainer size="sm" className="flex flex-col h-full">
|
||||||
|
{/* Header */}
|
||||||
|
<div className="mb-2 pb-2 border-b flex items-center justify-between">
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
shape="circle"
|
||||||
|
type="button"
|
||||||
|
size="xs"
|
||||||
|
onClick={() => setFieldValue('series', [...values.series, newSeriesValue()])}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<FaPlus /> Seri Ekle
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
{/* Kaydırılabilir içerik */}
|
||||||
|
<div className="flex-1 overflow-y-auto p-1">
|
||||||
|
<FieldArray name="series">
|
||||||
|
{({ remove }) => (
|
||||||
|
<div>
|
||||||
|
<div className="grid grid-cols-12 gap-2 font-semibold text-xs py-2">
|
||||||
|
<div className="text-center col-span-1">#</div>
|
||||||
|
<div className="text-center col-span-2">Type</div>
|
||||||
|
<div className="text-center col-span-2">Name</div>
|
||||||
|
<div className="text-center col-span-2">Argument Field</div>
|
||||||
|
<div className="text-center col-span-2">Value Field</div>
|
||||||
|
<div className="text-center col-span-2">Summary Type</div>
|
||||||
|
<div className="text-center col-span-1">#</div>
|
||||||
|
</div>
|
||||||
|
{values.series.map((_, index) => (
|
||||||
|
<div key={index} className="border-b py-1">
|
||||||
|
<div className="grid grid-cols-12 gap-1 items-center">
|
||||||
|
<div className="text-center text-xs col-span-1">
|
||||||
|
{values.series[index].index}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field name={`series[${index}].type`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
options={chartSeriesTypeOptions}
|
||||||
|
isClearable
|
||||||
|
value={chartSeriesTypeOptions.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field
|
||||||
|
size="sm"
|
||||||
|
name={`series[${index}].name`}
|
||||||
|
type="text"
|
||||||
|
component={Input}
|
||||||
|
className="text-xs px-1 py-0 grid-cols-2"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field type="text" name={`series[${index}].argumentField`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={fieldList}
|
||||||
|
value={fieldList?.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
menuPlacement="auto"
|
||||||
|
maxMenuHeight={150}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field type="text" name={`series[${index}].valueField`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={fieldList}
|
||||||
|
value={fieldList?.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
menuPlacement="auto"
|
||||||
|
maxMenuHeight={150}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-xs col-span-2">
|
||||||
|
<Field type="text" name={`series[${index}].summaryType`}>
|
||||||
|
{({ field, form }: FieldProps<SelectBoxOption>) => (
|
||||||
|
<Select
|
||||||
|
field={field}
|
||||||
|
form={form}
|
||||||
|
isClearable={true}
|
||||||
|
options={columnSummaryTypeListOptions}
|
||||||
|
value={columnSummaryTypeListOptions.find(
|
||||||
|
(option) => option.value === field.value,
|
||||||
|
)}
|
||||||
|
onChange={(option) =>
|
||||||
|
form.setFieldValue(field.name, option?.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-center gap-1 col-span-1">
|
||||||
|
<Button
|
||||||
|
shape="circle"
|
||||||
|
type="button"
|
||||||
|
size="xs"
|
||||||
|
icon={<FaMinus />}
|
||||||
|
className="bg-slate-100 hover:bg-red-100"
|
||||||
|
onClick={() => remove(index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</FieldArray>
|
||||||
|
</div>
|
||||||
|
{/* Footer */}
|
||||||
|
<div className="flex gap-2 mt-auto pt-2 border-t text-right justify-end">
|
||||||
|
<Button
|
||||||
|
variant="solid"
|
||||||
|
loading={isSubmitting}
|
||||||
|
type="submit"
|
||||||
|
className="ml-auto px-4 py-1 text-sm rounded"
|
||||||
|
>
|
||||||
|
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</FormContainer>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ChartSeriesDialog1
|
||||||
|
|
@ -168,6 +168,7 @@ const List = () => {
|
||||||
/>
|
/>
|
||||||
) : viewMode === 'chart' ? (
|
) : viewMode === 'chart' ? (
|
||||||
<Chart
|
<Chart
|
||||||
|
id={gridDto?.gridOptions.id!}
|
||||||
listFormCode={listFormCode}
|
listFormCode={listFormCode}
|
||||||
filter={searchParams.toString()}
|
filter={searchParams.toString()}
|
||||||
isSubForm={true}
|
isSubForm={true}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue