Widget düzenlemesi

This commit is contained in:
Sedat Öztürk 2025-11-09 00:07:00 +03:00
parent 4d9ae1563d
commit f65ae119c0
9 changed files with 97 additions and 37 deletions

View file

@ -13,4 +13,5 @@ public class WidgetEditDto
public string SubTitle { get; set; }
public string OnClick { get; set; }
public string ClassName { get; set; }
public bool IsActive { get; set; }
}

View file

@ -6,6 +6,7 @@ public class WidgetDto
public int ColSpan { get; set; }
public string ClassName { get; set; }
public List<WidgetItemDto> Items { get; set; }
public bool IsActive { get; set; }
}
public class WidgetItemDto

View file

@ -231,7 +231,7 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe
if (!listForm.WidgetsJson.IsNullOrWhiteSpace())
{
var widgetList = JsonSerializer.Deserialize<WidgetEditDto[]>(listForm.WidgetsJson) ?? [];
foreach (var widget in widgetList)
foreach (var widget in widgetList.Where(w => w.IsActive))
{
if (!string.IsNullOrWhiteSpace(widget.SqlQuery))
{

View file

@ -4957,6 +4957,12 @@
"en": "Value Class Name",
"tr": "Değer Sütun Sınıf Adı"
},
{
"resourceName": "Platform",
"key": "ListForms.ListFormEdit.WidgetStatus",
"en": "Status",
"tr": "Durum"
},
{
"resourceName": "Platform",
"key": "ListForms.ListFormEdit.WidgetColor",

View file

@ -16,6 +16,7 @@ public class Widget : ValueObject
public string SubTitle { get; set; }
public string OnClick { get; set; }
public string ClassName { get; set; }
public bool IsActive { get; set; }
protected override IEnumerable<object> GetAtomicValues()
{
@ -30,5 +31,6 @@ public class Widget : ValueObject
yield return SubTitle;
yield return OnClick;
yield return ClassName;
yield return IsActive;
}
}

View file

@ -792,6 +792,7 @@ export interface WidgetGroupDto {
colSpan?: number
className?: string
items: WidgetEditDto[]
isActive: boolean
}
export interface WidgetEditDto {
@ -806,6 +807,7 @@ export interface WidgetEditDto {
icon: string
subTitle: string
onClick: string
isActive: boolean
}
export interface LayoutDto {

View file

@ -59,6 +59,7 @@ function FormTabWidgets(props: { listFormCode: string }) {
<Th>{translate('::ListForms.ListFormEdit.WidgetSqlQuery')}</Th>
<Th>{translate('::ListForms.ListFormEdit.WidgetClassName')}</Th>
<Th>{translate('::ListForms.ListFormEdit.WidgetValueClassName')}</Th>
<Th>{translate('::ListForms.ListFormEdit.WidgetStatus')}</Th>
</Tr>
</THead>
<TBody>
@ -108,6 +109,7 @@ function FormTabWidgets(props: { listFormCode: string }) {
<Td>{row.sqlQuery}</Td>
<Td>{row.className}</Td>
<Td>{row.valueClassName}</Td>
<Td>{row.isActive ? 'Active' : 'Inactive'}</Td>
</Tr>
))}
</TBody>

View file

@ -1,5 +1,6 @@
import {
Button,
Checkbox,
Dialog,
FormContainer,
FormItem,
@ -97,6 +98,7 @@ function JsonRowOpDialogWidget({
icon: 'Icon',
subTitle: 'SubTitle',
onClick: '',
isActive: false,
}
}
validationSchema={schema}
@ -137,40 +139,55 @@ function JsonRowOpDialogWidget({
<Form>
<FormContainer size="sm">
<div className="h-full overflow-y-auto p-2">
<FormItem
label="Column Gap (Sütun Boşluğu)"
invalid={errors.colGap && touched.colGap}
errorMessage={errors.colGap}
>
<Field
type="number"
autoComplete="off"
name="colGap"
placeholder="Column Gap"
component={Input}
/>
</FormItem>
<div className="grid grid-cols-3 gap-4">
<FormItem
label="Column Gap (Sütun Boşluğu)"
invalid={errors.colGap && touched.colGap}
errorMessage={errors.colGap}
>
<Field
type="number"
autoComplete="off"
name="colGap"
placeholder="Column Gap"
component={Input}
/>
</FormItem>
<FormItem
label="Column Span (Sütun Genişliği)"
invalid={errors.colSpan && touched.colSpan}
errorMessage={errors.colSpan}
>
<Field type="text" autoComplete="off" name="colSpan" placeholder="colSpan">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
isClearable={true}
options={colSpanOptions}
value={colSpanOptions?.filter(
(option: any) => option.value === values.colSpan,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="Column Span (Sütun Genişliği)"
invalid={errors.colSpan && touched.colSpan}
errorMessage={errors.colSpan}
>
<Field type="text" autoComplete="off" name="colSpan" placeholder="colSpan">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
isClearable={true}
options={colSpanOptions}
value={colSpanOptions?.filter(
(option: any) => option.value === values.colSpan,
)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label="IsActive"
invalid={errors.isActive && touched.isActive}
errorMessage={errors.isActive}
>
<Field
autoComplete="off"
name="isActive"
placeholder="IsActive"
component={Checkbox}
/>
</FormItem>
</div>
<FormItem
label="Sql Query"
@ -183,7 +200,6 @@ function JsonRowOpDialogWidget({
name="sqlQuery"
placeholder="Sql Query"
component={Input}
rows={6}
textArea={true}
/>
</FormItem>

View file

@ -87,6 +87,7 @@ const Grid = (props: GridProps) => {
const gridRef = useRef<DataGrid>()
const refListFormCode = useRef('')
const widgetGroupRef = useRef<HTMLDivElement>(null)
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
const [columnData, setColumnData] = useState<GridColumnData[]>()
@ -95,6 +96,7 @@ const Grid = (props: GridProps) => {
const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])
const [gridDto, setGridDto] = useState<GridDto>()
const [isPopupFullScreen, setIsPopupFullScreen] = useState(false)
const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
const preloadExportLibs = () => {
import('exceljs')
@ -593,6 +595,29 @@ const Grid = (props: GridProps) => {
gridRef.current.instance.option('stateStoring', stateStoring)
}, [columnData])
// WidgetGroup yüksekliğini hesapla
useEffect(() => {
const calculateWidgetHeight = () => {
if (widgetGroupRef.current) {
const height = widgetGroupRef.current.offsetHeight
setWidgetGroupHeight(height)
}
}
// İlk render'da hesapla
calculateWidgetHeight()
// Resize durumunda tekrar hesapla
const resizeObserver = new ResizeObserver(calculateWidgetHeight)
if (widgetGroupRef.current) {
resizeObserver.observe(widgetGroupRef.current)
}
return () => {
resizeObserver.disconnect()
}
}, [gridDto?.widgets])
const onExporting = async (e: DataGridTypes.ExportingEvent) => {
// DevExtremein varsayılan export davranışını iptal ediyoruz; kendi akışımızı çalıştıracağız
e.cancel = true
@ -663,7 +688,9 @@ const Grid = (props: GridProps) => {
return (
<>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
<div ref={widgetGroupRef}>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
</div>
<Container className={DX_CLASSNAMES}>
{!isSubForm && (
@ -682,7 +709,10 @@ const Grid = (props: GridProps) => {
//dataSource={gridDataSource}
//remoteOperations={{ groupPaging: true }}
//remoteOperations={false}
height={gridDto.gridOptions.height || 'calc(100vh - 150px)'}
height={
gridDto.gridOptions.height ||
`calc(100vh - ${170 + widgetGroupHeight}px)`
}
width={gridDto.gridOptions.width || '100%'}
allowColumnResizing={gridDto.gridOptions.columnOptionDto?.allowColumnResizing}
allowColumnReordering={gridDto.gridOptions.columnOptionDto?.allowColumnReordering}