Grid, Tree, Chart, Pivot Toolbar style

This commit is contained in:
Sedat ÖZTÜRK 2026-06-18 17:03:22 +03:00
parent 866d9f1e85
commit 76621b24d8
8 changed files with 349 additions and 206 deletions

View file

@ -113,6 +113,140 @@ div.dialog-after-open > div.dialog-content.maximized {
padding: 0 0 !important; padding: 0 0 !important;
} }
.dx-datagrid-header-panel.pivot-toolbar-panel {
min-height: 37px;
background-color: transparent !important;
}
.dark .dx-datagrid-header-panel.pivot-toolbar-panel {
background-color: #202020 !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel .button,
.dx-datagrid-header-panel.pivot-toolbar-panel .dx-button,
.dx-datagrid-header-panel.pivot-toolbar-panel button {
background-color: transparent !important;
border-color: transparent !important;
border-radius: 0 !important;
padding: 0 !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel .relative.flex {
gap: 4px !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar {
width: 100% !important;
background-color: transparent !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar .dx-toolbar-items-container {
min-height: 28px !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar .dx-toolbar-before {
width: auto !important;
max-width: none !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar .dx-toolbar-after {
width: auto !important;
max-width: none !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar .dx-toolbar-after .dx-toolbar-item {
padding-inline: 2px !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar .dx-button-content {
padding-block: 4px !important;
padding-inline: 6px !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel .chart-toolbar-search {
width: 160px;
height: 32px;
padding: 6px 12px 6px 34px;
border: 0 !important;
border-bottom: 1px solid #d1d5db !important;
border-radius: 0 !important;
background-color: #fff;
}
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .chart-toolbar-search {
background-color: #2d2d2d !important;
border-bottom-color: #6b7280 !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel > .dx-toolbar .dx-toolbar-menu-container .dx-button {
border-radius: 50% !important;
}
.dark
.dx-datagrid-header-panel.pivot-toolbar-panel
> .dx-toolbar
.dx-toolbar-menu-container
.dx-button {
background-color: #343440 !important;
border-color: #343440 !important;
}
.dark
.dx-datagrid-header-panel.pivot-toolbar-panel
> .dx-toolbar
.dx-toolbar-menu-container
.dx-button:hover {
background-color: #424250 !important;
border-color: #424250 !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel
> .dx-toolbar
.dx-toolbar-menu-container
.dx-button-content {
padding: 4px !important;
}
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .button,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .dx-button,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel button {
background-color: transparent !important;
border-color: transparent !important;
color: #fff !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel .dx-button-text {
text-transform: none !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel .button:hover,
.dx-datagrid-header-panel.pivot-toolbar-panel .dx-button:hover,
.dx-datagrid-header-panel.pivot-toolbar-panel button:hover {
background-color: #dedede !important;
}
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .button:hover,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .dx-button:hover,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel button:hover {
background-color: #2d2d2d !important;
}
.dx-datagrid-header-panel.pivot-toolbar-panel,
.dx-datagrid-header-panel.pivot-toolbar-panel .dx-button,
.dx-datagrid-header-panel.pivot-toolbar-panel .dx-button-text,
.dx-datagrid-header-panel.pivot-toolbar-panel svg {
color: #000 !important;
}
.dark .dx-datagrid-header-panel.pivot-toolbar-panel,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .button,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .dx-button,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel .dx-button-text,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel button,
.dark .dx-datagrid-header-panel.pivot-toolbar-panel svg {
color: #fff !important;
}
.dx-datagrid-header-panel > .dx-toolbar .dx-toolbar-before, .dx-datagrid-header-panel > .dx-toolbar .dx-toolbar-before,
.dx-treelist-header-panel > .dx-toolbar .dx-toolbar-before { .dx-treelist-header-panel > .dx-toolbar .dx-toolbar-before {
width: 50% !important; width: 50% !important;

View file

@ -9,10 +9,10 @@ import { Helmet } from 'react-helmet'
import { useParams, useSearchParams } from 'react-router-dom' import { useParams, useSearchParams } from 'react-router-dom'
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, toast, Notification } from '@/components/ui' import { 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, FaSearch, FaSyncAlt } from 'react-icons/fa' import { FaSearch } 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 { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'
@ -29,6 +29,7 @@ import {
} from '@/services/admin/list-form.service' } from '@/services/admin/list-form.service'
import { layoutTypes } from '../admin/listForm/edit/types' import { layoutTypes } from '../admin/listForm/edit/types'
import { useListFormCustomDataSource } from './useListFormCustomDataSource' import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import Toolbar, { Item } from 'devextreme-react/toolbar'
interface ChartProps extends CommonProps, Meta { interface ChartProps extends CommonProps, Meta {
id: string id: string
@ -327,10 +328,15 @@ const Chart = (props: ChartProps) => {
></Helmet> ></Helmet>
)} )}
{_listFormCode && chartOptions && ( {_listFormCode && chartOptions && (
<div className="p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 h-full relative"> <div className="p-1">
<div className="flex justify-end items-center h-full"> <div className="dx-datagrid-header-panel pivot-toolbar-panel text-black dark:text-white">
<div className="relative pb-1 flex gap-1 border-b-1"> <Toolbar width="100%">
<FaSearch className="absolute left-2 top-1/2 -translate-y-1/2 text-gray-400 text-sm" /> <Item
location="before"
locateInMenu="never"
render={() => (
<div className="relative flex items-center">
<FaSearch className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm" />
<input <input
type="text" type="text"
placeholder={translate('::App.Search')} placeholder={translate('::App.Search')}
@ -353,39 +359,50 @@ const Chart = (props: ChartProps) => {
onFilter(newValue) onFilter(newValue)
setPrevValue(newValue) setPrevValue(newValue)
}} }}
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="chart-toolbar-search outline-none text-xs text-gray-700 placeholder-gray-400 dark:text-gray-200 dark:placeholder-gray-400"
/> />
<Button </div>
size="sm" )}
variant={'default'} />
icon={<FaSyncAlt className="w-3 h-3" />} <Item
className="text-sm flex items-center gap-1" location="after"
onClick={async () => { widget="dxButton"
locateInMenu="auto"
showText="always"
options={{
icon: 'refresh',
text: translate('::App.Platform.Refresh'),
hint: translate('::App.Platform.Refresh'),
onClick: async () => {
setInitialized(false) setInitialized(false)
await refreshGridDto?.() await refreshGridDto?.()
},
}} }}
title={translate('::App.Platform.Refresh')} />
> <Item
{translate('::App.Platform.Refresh')} location="after"
</Button> widget="dxButton"
<Button locateInMenu="auto"
size="sm" showText="always"
icon={<FaCrosshairs className="w-3 h-3" />} options={{
variant="default" icon: 'chart',
className="text-sm flex items-center gap-1" text: translate('::ListForms.ListFormEdit.TabChartSeries'),
onClick={() => setOpenDrawer(true)} hint: translate('::ListForms.ListFormEdit.TabChartSeries'),
title={translate('::ListForms.ListFormEdit.TabChartSeries')} onClick: () => setOpenDrawer(true),
> }}
{translate('::ListForms.ListFormEdit.TabChartSeries')} />
</Button>
{checkPermission(gridDto?.gridOptions.permissionDto.u) && ( {checkPermission(gridDto?.gridOptions.permissionDto.u) && (
<Button <Item
size="sm" location="after"
icon={<FaCog className="w-3 h-3" />} widget="dxButton"
variant={'default'} locateInMenu="auto"
className="text-sm" showText="always"
onClick={() => { options={{
icon: 'preferences',
text: translate('::ListForms.ListForm.Manage'),
hint: translate('::ListForms.ListForm.Manage'),
onClick: () => {
window.open( window.open(
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace( ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(
':listFormCode', ':listFormCode',
@ -393,16 +410,13 @@ const Chart = (props: ChartProps) => {
), ),
isPwaMode ? '_self' : '_blank', isPwaMode ? '_self' : '_blank',
) )
},
}} }}
title={translate('::ListForms.ListForm.Manage')} />
></Button>
)} )}
</Toolbar>
</div> </div>
</div> <div className="border border-gray-200 dark:border-gray-600">
<div
className={`transition-all duration-300 ${openDrawer ? 'mr-[500px]' : 'mr-0'}`}
style={{ width: openDrawer ? 'calc(100% - 500px)' : '100%' }}
>
<DxChart key={'DxChart' + _listFormCode} {...chartOptions}></DxChart> <DxChart key={'DxChart' + _listFormCode} {...chartOptions}></DxChart>
</div> </div>

View file

@ -90,7 +90,7 @@ const ChartDrawer = ({
<> <>
{/* Drawer */} {/* Drawer */}
<div <div
className={`fixed right-0 top-0 h-full w-[500px] bg-white shadow-2xl z-50 transform transition-transform duration-300 border-l-2 border-gray-300 ${ className={`fixed right-0 top-0 h-full w-[500px] bg-white text-gray-900 shadow-2xl z-50 transform transition-transform duration-300 border-l-2 border-gray-300 dark:bg-gray-900 dark:text-gray-100 dark:border-gray-700 ${
open ? 'translate-x-0' : 'translate-x-full' open ? 'translate-x-0' : 'translate-x-full'
}`} }`}
> >
@ -139,8 +139,8 @@ const ChartDrawer = ({
return ( return (
<Form className="flex flex-col h-full"> <Form className="flex flex-col h-full">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between p-4 border-b bg-gray-50"> <div className="flex items-center justify-between p-4 border-b border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800">
<h2 className="text-lg font-semibold flex items-center gap-2"> <h2 className="text-lg font-semibold flex items-center gap-2 text-gray-900 dark:text-gray-100">
<span>📊</span> <span>📊</span>
{translate('::App.Platform.ChartDrawer.ChartSeries')} {translate('::App.Platform.ChartDrawer.ChartSeries')}
</h2> </h2>
@ -155,7 +155,7 @@ const ChartDrawer = ({
<FormContainer size="sm" className="flex flex-col flex-1 overflow-hidden"> <FormContainer size="sm" className="flex flex-col flex-1 overflow-hidden">
{/* Add Series Button */} {/* Add Series Button */}
<div className="p-3 border-b"> <div className="p-3 border-b border-gray-200 dark:border-gray-700">
<Button <Button
size="sm" size="sm"
block block
@ -180,11 +180,11 @@ const ChartDrawer = ({
{values.series.map((series, index) => ( {values.series.map((series, index) => (
<div <div
key={index} key={index}
className="border rounded-lg p-3 bg-gray-50 hover:bg-gray-100 transition-colors" className="border border-gray-200 rounded-lg p-3 bg-gray-50 hover:bg-gray-100 transition-colors dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700"
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<span className="font-semibold text-sm"> <span className="font-semibold text-sm text-gray-900 dark:text-gray-100">
{translate('::App.Platform.ChartDrawer.Series')} #{index + 1} {translate('::App.Platform.ChartDrawer.Series')} #{index + 1}
</span> </span>
<Button <Button
@ -192,7 +192,7 @@ const ChartDrawer = ({
size="xs" size="xs"
variant="plain" variant="plain"
icon={<FaMinus />} icon={<FaMinus />}
className="border-0 text-red-500 hover:bg-red-100" className="border-0 text-red-500 hover:bg-red-100 dark:text-red-400 dark:hover:bg-red-900/30"
onClick={() => { onClick={() => {
remove(index) remove(index)
}} }}
@ -201,7 +201,7 @@ const ChartDrawer = ({
{/* Chart Type Selector */} {/* Chart Type Selector */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block"> <label className="text-xs font-medium mb-1 block text-gray-700 dark:text-gray-300">
{translate('::App.Platform.ChartDrawer.ChartType')} {translate('::App.Platform.ChartDrawer.ChartType')}
</label> </label>
<Field name={`series[${index}].type`}> <Field name={`series[${index}].type`}>
@ -214,7 +214,7 @@ const ChartDrawer = ({
selectedSeriesIndex === index ? -1 : index, selectedSeriesIndex === index ? -1 : index,
) )
} }
className="w-full px-3 py-2 text-left border rounded hover:bg-white flex items-center gap-2 transition-colors" className="w-full px-3 py-2 text-left border border-gray-300 rounded bg-white hover:bg-gray-50 flex items-center gap-2 transition-colors dark:border-gray-600 dark:bg-gray-900 dark:hover:bg-gray-800"
> >
<span className="text-xl"> <span className="text-xl">
{chartSeriesTypeOptions.find( {chartSeriesTypeOptions.find(
@ -228,7 +228,7 @@ const ChartDrawer = ({
</span> </span>
</Button> </Button>
{selectedSeriesIndex === index && ( {selectedSeriesIndex === index && (
<div className="absolute z-50 mt-1 w-full bg-white border rounded-lg shadow-xl p-2"> <div className="absolute z-50 mt-1 w-full bg-white border border-gray-200 rounded-lg shadow-xl p-2 dark:bg-gray-900 dark:border-gray-700">
<div className="grid grid-cols-2 gap-2"> <div className="grid grid-cols-2 gap-2">
{chartSeriesTypeOptions.map((chartType) => ( {chartSeriesTypeOptions.map((chartType) => (
<Button <Button
@ -238,10 +238,10 @@ const ChartDrawer = ({
form.setFieldValue(field.name, chartType.label) form.setFieldValue(field.name, chartType.label)
setSelectedSeriesIndex(-1) setSelectedSeriesIndex(-1)
}} }}
className={`p-2 rounded-lg hover:bg-blue-50 flex items-center gap-2 transition-all ${ className={`p-2 rounded-lg hover:bg-blue-50 flex items-center gap-2 transition-all dark:hover:bg-blue-900/30 ${
field.value === chartType.label field.value === chartType.label
? 'bg-blue-100 ring-2 ring-blue-400' ? 'bg-blue-100 ring-2 ring-blue-400 dark:bg-blue-900/40 dark:ring-blue-500'
: 'bg-gray-50' : 'bg-gray-50 dark:bg-gray-800'
}`} }`}
> >
<span className="text-xl">{chartType.icon}</span> <span className="text-xl">{chartType.icon}</span>
@ -260,7 +260,7 @@ const ChartDrawer = ({
{/* Name */} {/* Name */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block"> <label className="text-xs font-medium mb-1 block text-gray-700 dark:text-gray-300">
{translate('::App.Listform.ListformField.Name')} {translate('::App.Listform.ListformField.Name')}
</label> </label>
<Field <Field
@ -274,7 +274,7 @@ const ChartDrawer = ({
{/* Argument Field */} {/* Argument Field */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block"> <label className="text-xs font-medium mb-1 block text-gray-700 dark:text-gray-300">
{translate('::App.Platform.ChartDrawer.ArgumentField')} {translate('::App.Platform.ChartDrawer.ArgumentField')}
</label> </label>
<Field name={`series[${index}].argumentField`}> <Field name={`series[${index}].argumentField`}>
@ -300,7 +300,7 @@ const ChartDrawer = ({
{/* Value Field */} {/* Value Field */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block"> <label className="text-xs font-medium mb-1 block text-gray-700 dark:text-gray-300">
{translate('::App.Platform.ChartDrawer.ValueField')} {translate('::App.Platform.ChartDrawer.ValueField')}
</label> </label>
<Field name={`series[${index}].valueField`}> <Field name={`series[${index}].valueField`}>
@ -326,7 +326,7 @@ const ChartDrawer = ({
{/* Summary Type */} {/* Summary Type */}
<div className="mb-3"> <div className="mb-3">
<label className="text-xs font-medium mb-1 block"> <label className="text-xs font-medium mb-1 block text-gray-700 dark:text-gray-300">
{translate('::App.Platform.ChartDrawer.SummaryType')} {translate('::App.Platform.ChartDrawer.SummaryType')}
</label> </label>
<Field name={`series[${index}].summaryType`}> <Field name={`series[${index}].summaryType`}>
@ -354,7 +354,7 @@ const ChartDrawer = ({
</div> </div>
{/* Footer */} {/* Footer */}
<div className="p-4 border-t bg-gray-50 flex gap-2"> <div className="p-4 border-t border-gray-200 bg-gray-50 flex gap-2 dark:border-gray-700 dark:bg-gray-800">
<Button type="button" variant="plain" onClick={onClose} className="flex-1"> <Button type="button" variant="plain" onClick={onClose} className="flex-1">
{translate('::Cancel')} {translate('::Cancel')}
</Button> </Button>

View file

@ -187,7 +187,7 @@ const GanttView = (props: GanttViewProps) => {
return ( return (
<> <>
<div ref={widgetGroupRef}> <div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} /> <WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
</div> </div>

View file

@ -1402,7 +1402,7 @@ const Grid = (props: GridProps) => {
return ( return (
<> <>
<div ref={widgetGroupRef} className="mt-2"> <div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} /> <WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
</div> </div>
@ -1556,9 +1556,7 @@ const Grid = (props: GridProps) => {
popup={{ popup={{
deferRendering: true, deferRendering: true,
animation: {}, animation: {},
wrapperAttr: useMobileEditPopup wrapperAttr: useMobileEditPopup ? { class: 'mobile-edit-popup' } : undefined,
? { class: 'mobile-edit-popup' }
: undefined,
title: title:
(mode === 'new' ? '✚ ' : '🖊️ ') + (mode === 'new' ? '✚ ' : '🖊️ ') +
translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title), translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title),
@ -1568,7 +1566,8 @@ const Grid = (props: GridProps) => {
width: useMobileEditPopup width: useMobileEditPopup
? '100%' ? '100%'
: gridDto.gridOptions.editingOptionDto?.popup?.width, : gridDto.gridOptions.editingOptionDto?.popup?.width,
height: useMobileEditPopup && isPopupFullScreen height:
useMobileEditPopup && isPopupFullScreen
? '100%' ? '100%'
: gridDto.gridOptions.editingOptionDto?.popup?.height, : gridDto.gridOptions.editingOptionDto?.popup?.height,
position: useMobileEditPopup position: useMobileEditPopup

View file

@ -32,8 +32,7 @@ import {
} from './Utils' } from './Utils'
import { useFilters } from './useFilters' import { useFilters } from './useFilters'
import WidgetGroup from '@/components/common/WidgetGroup' import WidgetGroup from '@/components/common/WidgetGroup'
import { Button, Dropdown, Notification, toast } from '@/components/ui' import { Notification, toast } from '@/components/ui'
import { FaCaretDown, FaCog, FaSave, FaTimes, FaUndo } from 'react-icons/fa'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'
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'
@ -42,6 +41,7 @@ import { useListFormCustomDataSource } from './useListFormCustomDataSource'
import { useListFormColumns } from './useListFormColumns' import { useListFormColumns } from './useListFormColumns'
import { useStoreState } from '@/store' import { useStoreState } from '@/store'
import Checkbox from '@/components/ui/Checkbox' import Checkbox from '@/components/ui/Checkbox'
import Toolbar, { Item } from 'devextreme-react/toolbar'
interface PivotProps { interface PivotProps {
listFormCode: string listFormCode: string
@ -263,6 +263,44 @@ const Pivot = (props: PivotProps) => {
}) })
}, [listFormCode, storageKey]) }, [listFormCode, storageKey])
const savePivotGridState = useCallback(() => {
const instance = gridRef.current?.instance()
if (!instance) {
return
}
const ds = instance.getDataSource()
if (!ds || typeof ds.state !== 'function') {
return
}
const currentState = ds.state()
customSaveState(currentState)
.then(() => {
toast.push(
<Notification type="success" duration={2000}>
{translate('::ListForms.ListForm.GridStateSaved')}
</Notification>,
{ placement: 'top-end' },
)
})
.catch(() => {
toast.push(
<Notification type="danger" duration={2500}>
{translate('::ListForms.ListForm.GridStateSaveError')}
</Notification>,
{ placement: 'top-end' },
)
})
}, [customSaveState, translate])
const openFormManager = useCallback(() => {
window.open(
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(':listFormCode', listFormCode),
isPwaMode ? '_self' : '_blank',
)
}, [isPwaMode, listFormCode])
useEffect(() => { useEffect(() => {
refListFormCode.current = listFormCode refListFormCode.current = listFormCode
}, [listFormCode]) }, [listFormCode])
@ -420,112 +458,72 @@ const Pivot = (props: PivotProps) => {
></Helmet> ></Helmet>
)} )}
{gridDto && columnData && ( {gridDto && columnData && (
<div className="p-1 bg-white dark:bg-neutral-800 dark:border-neutral-700 "> <div className="p-1">
<div className="flex justify-end items-center text-black"> <div className="dx-datagrid-header-panel pivot-toolbar-panel text-black">
<div className="relative flex gap-1"> <Toolbar width="100%">
<label className="flex items-center gap-1 text-xs cursor-pointer dark:text-white"> <Item
<span>{translate('::ListForms.ListFormEdit.ShowChart')}</span> location="before"
locateInMenu="never"
render={() => (
<label className="flex items-center gap-1 text-xs cursor-pointer">
<span className="font-medium">
{translate('::ListForms.ListFormEdit.ShowChart')}
</span>
<Checkbox checked={showChart} onChange={(checked) => setShowChart(checked)} /> <Checkbox checked={showChart} onChange={(checked) => setShowChart(checked)} />
</label> </label>
<div className="dx-menu">
<Dropdown
placement="bottom-end"
renderTitle={
<Button
size="sm"
variant={'plain'}
icon={<FaCaretDown className="ml-2 w-2 h-3" />}
className="text-sm flex items-center gap-1 border-0"
title="Menu"
>
<i className="dx-icon dx-icon-overflow" style={{ fontSize: '17px' }}></i>
<span className="text-black dark:text-white" style={{ fontSize: '13px' }}>
{translate('::ListForms.ListForm.GridMenu')}
</span>
</Button>
}
>
<Dropdown.Item
eventKey="removeFilter"
onClick={clearPivotFilters}
className="px-2"
>
<span className="flex items-center gap-2">
<FaTimes className="w-3 h-3" />
<span>{translate('::ListForms.ListForm.RemoveFilter')}</span>
</span>
</Dropdown.Item>
<Dropdown.Item
eventKey="saveGridState"
onClick={() => {
const instance = gridRef.current?.instance()
if (instance) {
const ds = instance.getDataSource()
if (ds && typeof ds.state === 'function') {
const currentState = ds.state()
customSaveState(currentState)
.then(() => {
toast.push(
<Notification type="success" duration={2000}>
{translate('::ListForms.ListForm.GridStateSaved')}
</Notification>,
{ placement: 'top-end' },
)
})
.catch(() => {
toast.push(
<Notification type="danger" duration={2500}>
{translate('::ListForms.ListForm.GridStateSaveError')}
</Notification>,
{ placement: 'top-end' },
)
})
}
}
}}
className="px-2"
>
<span className="flex items-center gap-2">
<FaSave className="w-3 h-3" />
<span>{translate('::ListForms.ListForm.SaveGridState')}</span>
</span>
</Dropdown.Item>
<Dropdown.Item
eventKey="resetGridState"
onClick={resetPivotGridState}
className="px-2"
>
<span className="flex items-center gap-2">
<FaUndo className="w-3 h-3" />
<span>{translate('::ListForms.ListForm.ResetGridState')}</span>
</span>
</Dropdown.Item>
{checkPermission(gridDto?.gridOptions.permissionDto.u) && (
<Dropdown.Item
eventKey="formManager"
onClick={() => {
window.open(
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(
':listFormCode',
listFormCode,
),
isPwaMode ? '_self' : '_blank',
)
}}
className="px-2"
>
<span className="flex items-center gap-2">
<FaCog className="w-3 h-3" />
<span>{translate('::ListForms.ListForm.Manage')}</span>
</span>
</Dropdown.Item>
)} )}
</Dropdown> />
</div> <Item
</div> location="after"
widget="dxButton"
locateInMenu="auto"
showText="always"
options={{
icon: 'clear',
text: translate('::ListForms.ListForm.RemoveFilter'),
hint: translate('::ListForms.ListForm.RemoveFilter'),
onClick: clearPivotFilters,
}}
/>
<Item
location="after"
widget="dxButton"
locateInMenu="auto"
showText="always"
options={{
icon: 'save',
text: translate('::ListForms.ListForm.SaveGridState'),
hint: translate('::ListForms.ListForm.SaveGridState'),
onClick: savePivotGridState,
}}
/>
<Item
location="after"
widget="dxButton"
locateInMenu="auto"
showText="always"
options={{
icon: 'undo',
text: translate('::ListForms.ListForm.ResetGridState'),
hint: translate('::ListForms.ListForm.ResetGridState'),
onClick: resetPivotGridState,
}}
/>
{checkPermission(gridDto?.gridOptions.permissionDto.u) && (
<Item
location="after"
widget="dxButton"
locateInMenu="auto"
showText="always"
options={{
icon: 'preferences',
text: translate('::ListForms.ListForm.Manage'),
hint: translate('::ListForms.ListForm.Manage'),
onClick: openFormManager,
}}
/>
)}
</Toolbar>
</div> </div>
{showChart && ( {showChart && (
<Chart ref={chartRef as any}> <Chart ref={chartRef as any}>
@ -537,8 +535,6 @@ const Pivot = (props: PivotProps) => {
</Chart> </Chart>
)} )}
<div className="dx-datagrid-header-panel h-1"></div>
<PivotGrid <PivotGrid
ref={gridRef as any} ref={gridRef as any}
id={'Pivot-' + listFormCode} id={'Pivot-' + listFormCode}

View file

@ -523,7 +523,7 @@ const SchedulerView = (props: SchedulerViewProps) => {
return ( return (
<> <>
<div ref={widgetGroupRef}> <div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} /> <WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
</div> </div>

View file

@ -1060,7 +1060,7 @@ const Tree = (props: TreeProps) => {
return ( return (
<> <>
<div ref={widgetGroupRef}> <div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} /> <WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
</div> </div>