677 lines
24 KiB
TypeScript
677 lines
24 KiB
TypeScript
import Container from '@/components/shared/Container'
|
||
import '@/utils/registerDevExtremeEditors'
|
||
import { APP_NAME, DX_CLASSNAMES } from '@/constants/app.constant'
|
||
import {
|
||
DbTypeEnum,
|
||
GridDto,
|
||
PlatformEditorTypes,
|
||
UiLookupDataSourceTypeEnum,
|
||
EditingFormItemDto
|
||
} from '@/proxy/form/models'
|
||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||
import Scheduler, {
|
||
Editing,
|
||
Item,
|
||
Resource,
|
||
type SchedulerRef,
|
||
Toolbar,
|
||
View,
|
||
} from 'devextreme-react/scheduler'
|
||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||
import { Helmet } from 'react-helmet'
|
||
import { getList } from '@/services/form.service'
|
||
import { useListFormCustomDataSource } from './useListFormCustomDataSource'
|
||
import { addCss, addJs, autoNumber } from './Utils'
|
||
import { layoutTypes } from '../admin/listForm/edit/types'
|
||
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
|
||
import { ROUTES_ENUM } from '@/routes/route.constant'
|
||
import { usePWA } from '@/utils/hooks/usePWA'
|
||
import CustomStore from 'devextreme/data/custom_store'
|
||
import { Loading } from '@/components/shared'
|
||
import { usePermission } from '@/utils/hooks/usePermission'
|
||
import { RowMode, SimpleItemWithColData } from '../form/types'
|
||
import { captionize } from 'devextreme/core/utils/inflector'
|
||
import type { AppointmentFormOpeningEvent } from 'devextreme/ui/scheduler'
|
||
|
||
interface SchedulerViewProps {
|
||
listFormCode: string
|
||
searchParams?: URLSearchParams
|
||
isSubForm?: boolean
|
||
level?: number
|
||
refreshData?: () => Promise<void>
|
||
gridDto?: GridDto
|
||
}
|
||
|
||
const SchedulerView = (props: SchedulerViewProps) => {
|
||
const { listFormCode, searchParams, isSubForm, level, gridDto: extGridDto } = props
|
||
const { translate } = useLocalization()
|
||
const isPwaMode = usePWA()
|
||
const [mode, setMode] = useState<RowMode>('view')
|
||
|
||
const schedulerRef = useRef<SchedulerRef>()
|
||
const refListFormCode = useRef('')
|
||
const widgetGroupRef = useRef<HTMLDivElement>(null)
|
||
const { checkPermission } = usePermission()
|
||
|
||
const [schedulerDataSource, setSchedulerDataSource] = useState<CustomStore<any, any>>()
|
||
const [gridDto, setGridDto] = useState<GridDto>()
|
||
const [widgetGroupHeight, setWidgetGroupHeight] = useState(0)
|
||
const [currentView, setCurrentView] = useState<string>('week')
|
||
const [isPopupFullScreen, setIsPopupFullScreen] = useState(false)
|
||
const layout = layoutTypes.scheduler || 'scheduler'
|
||
|
||
useEffect(() => {
|
||
const initializeScheduler = async () => {
|
||
const response = await getList({ listFormCode })
|
||
setGridDto(response.data)
|
||
}
|
||
|
||
if (extGridDto === undefined) {
|
||
initializeScheduler()
|
||
} else {
|
||
setGridDto(extGridDto)
|
||
}
|
||
|
||
setCurrentView(extGridDto?.gridOptions.schedulerOptionDto?.defaultView || 'week')
|
||
}, [listFormCode, extGridDto])
|
||
|
||
useEffect(() => {
|
||
if (schedulerRef?.current) {
|
||
const instance = schedulerRef?.current?.instance()
|
||
if (instance) {
|
||
instance.option('dataSource', undefined)
|
||
}
|
||
}
|
||
|
||
if (refListFormCode.current !== listFormCode) {
|
||
// Reset state if needed
|
||
}
|
||
}, [listFormCode])
|
||
|
||
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef: schedulerRef })
|
||
|
||
useEffect(() => {
|
||
if (!gridDto) {
|
||
return
|
||
}
|
||
|
||
// Set js and css
|
||
const grdOpt = gridDto.gridOptions
|
||
if (grdOpt.customJsSources.length) {
|
||
for (const js of grdOpt.customJsSources) {
|
||
addJs(js)
|
||
}
|
||
}
|
||
if (grdOpt.customStyleSources.length) {
|
||
for (const css of grdOpt.customStyleSources) {
|
||
addCss(css)
|
||
}
|
||
}
|
||
}, [gridDto])
|
||
|
||
useEffect(() => {
|
||
if (!gridDto) return
|
||
|
||
const dataSource = createSelectDataSource(
|
||
gridDto.gridOptions,
|
||
listFormCode,
|
||
searchParams,
|
||
layout,
|
||
undefined,
|
||
)
|
||
|
||
setSchedulerDataSource(dataSource)
|
||
}, [gridDto, searchParams, createSelectDataSource])
|
||
|
||
useEffect(() => {
|
||
refListFormCode.current = listFormCode
|
||
}, [listFormCode])
|
||
|
||
// WidgetGroup yüksekliğini hesapla
|
||
useEffect(() => {
|
||
const calculateWidgetHeight = () => {
|
||
if (widgetGroupRef.current) {
|
||
const height = widgetGroupRef.current.offsetHeight
|
||
setWidgetGroupHeight(height)
|
||
}
|
||
}
|
||
|
||
calculateWidgetHeight()
|
||
|
||
const resizeObserver = new ResizeObserver(calculateWidgetHeight)
|
||
if (widgetGroupRef.current) {
|
||
resizeObserver.observe(widgetGroupRef.current)
|
||
}
|
||
|
||
return () => {
|
||
resizeObserver.disconnect()
|
||
}
|
||
}, [gridDto?.widgets])
|
||
|
||
const settingButtonClick = useCallback(() => {
|
||
window.open(
|
||
ROUTES_ENUM.protected.saas.listFormManagement.edit.replace(':listFormCode', listFormCode),
|
||
isPwaMode ? '_self' : '_blank',
|
||
)
|
||
}, [listFormCode, isPwaMode])
|
||
|
||
const handleRefresh = useCallback(() => {
|
||
const instance = schedulerRef.current?.instance()
|
||
if (instance) {
|
||
const dataSource = instance.getDataSource()
|
||
if (dataSource) {
|
||
dataSource.reload()
|
||
}
|
||
}
|
||
}, [])
|
||
|
||
const onCurrentViewChange = useCallback((value: string) => {
|
||
setCurrentView(value)
|
||
}, [])
|
||
|
||
const onAppointmentFormOpening = useCallback(
|
||
(e: AppointmentFormOpeningEvent) => {
|
||
if (!gridDto) return
|
||
|
||
// Yeni appointment mı yoksa düzenleme mi kontrol et
|
||
const isNewAppointment =
|
||
!e.appointmentData ||
|
||
(!e.appointmentData.id && !e.appointmentData[gridDto.gridOptions.keyFieldName || 'id'])
|
||
|
||
const currentMode = isNewAppointment ? 'new' : 'edit'
|
||
setMode(currentMode)
|
||
|
||
// Popup ayarlarını her açılışta yeniden yapılandır
|
||
e.popup.option(
|
||
'title',
|
||
(currentMode === 'new' ? '✚ ' : '🖊️ ') +
|
||
translate('::' + gridDto.gridOptions.editingOptionDto?.popup?.title),
|
||
)
|
||
e.popup.option('showTitle', gridDto.gridOptions.editingOptionDto?.popup?.showTitle)
|
||
e.popup.option('width', gridDto.gridOptions.editingOptionDto?.popup?.width)
|
||
e.popup.option('height', gridDto.gridOptions.editingOptionDto?.popup?.height)
|
||
e.popup.option('resizeEnabled', gridDto.gridOptions.editingOptionDto?.popup?.resizeEnabled)
|
||
e.popup.option('fullScreen', isPopupFullScreen)
|
||
|
||
// Toolbar butonlarını ekle
|
||
e.popup.option('toolbarItems', [
|
||
{
|
||
widget: 'dxButton',
|
||
toolbar: 'bottom',
|
||
location: 'after',
|
||
options: {
|
||
text: translate('::Save'),
|
||
type: 'default',
|
||
onClick: async () => {
|
||
const formInstance = e.form
|
||
const validationResult = formInstance.validate()
|
||
|
||
if (validationResult.isValid) {
|
||
// Form verilerini al
|
||
const formData = formInstance.option('formData')
|
||
|
||
try {
|
||
// Scheduler instance'ını al
|
||
const scheduler = schedulerRef.current?.instance()
|
||
|
||
if (e.appointmentData && scheduler) {
|
||
// Yeni appointment mı yoksa güncelleme mi kontrol et
|
||
if (
|
||
e.appointmentData.id ||
|
||
e.appointmentData[gridDto.gridOptions.keyFieldName || 'id']
|
||
) {
|
||
// Güncelleme
|
||
await scheduler.updateAppointment(e.appointmentData, formData)
|
||
} else {
|
||
// Yeni ekleme
|
||
await scheduler.addAppointment(formData)
|
||
}
|
||
|
||
// Popup'ı kapat
|
||
e.popup.hide()
|
||
|
||
// RefreshData varsa çağır
|
||
if (props.refreshData) {
|
||
await props.refreshData()
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Appointment save error:', error)
|
||
}
|
||
}
|
||
},
|
||
},
|
||
},
|
||
{
|
||
widget: 'dxButton',
|
||
toolbar: 'bottom',
|
||
location: 'after',
|
||
options: {
|
||
text: translate('::Cancel'),
|
||
onClick: () => {
|
||
e.cancel = true
|
||
e.popup.hide()
|
||
},
|
||
},
|
||
},
|
||
{
|
||
widget: 'dxButton',
|
||
toolbar: 'top',
|
||
location: 'after',
|
||
options: {
|
||
icon: 'fullscreen',
|
||
hint: translate('::Tam Ekran'),
|
||
stylingMode: 'text',
|
||
onClick: () => {
|
||
// Popup'tan mevcut fullScreen durumunu al
|
||
const currentFullScreen = e.popup.option('fullScreen')
|
||
const newFullScreenState = !currentFullScreen
|
||
|
||
// State'i güncelle
|
||
setIsPopupFullScreen(newFullScreenState)
|
||
|
||
// Popup'ı güncelle
|
||
e.popup.option('fullScreen', newFullScreenState)
|
||
|
||
// Width ve height'i da güncelle
|
||
if (newFullScreenState) {
|
||
e.popup.option('width', '100%')
|
||
e.popup.option('height', '100%')
|
||
} else {
|
||
e.popup.option('width', gridDto.gridOptions.editingOptionDto?.popup?.width || 600)
|
||
e.popup.option(
|
||
'height',
|
||
gridDto.gridOptions.editingOptionDto?.popup?.height || 'auto',
|
||
)
|
||
}
|
||
},
|
||
},
|
||
},
|
||
])
|
||
|
||
// EditingFormDto'dan form items oluştur
|
||
const result: any[] = []
|
||
|
||
if (gridDto.gridOptions.editingFormDto?.length > 0) {
|
||
const sortedFormDto = gridDto.gridOptions.editingFormDto
|
||
.slice()
|
||
.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
|
||
|
||
// Tüm tabbed items'ları topla (Grid'deki gibi)
|
||
const tabbedItems = sortedFormDto.filter((e: any) => e.itemType === 'tabbed')
|
||
|
||
// Ortak item mapper fonksiyonu - hem group hem tab için kullanılır
|
||
const mapFormItem = (i: EditingFormItemDto) => {
|
||
let editorOptions: any = {}
|
||
try {
|
||
if (i.editorOptions) {
|
||
editorOptions = JSON.parse(i.editorOptions)
|
||
}
|
||
} catch {}
|
||
|
||
const fieldName = i.dataField.split(':')[0]
|
||
const listFormField = gridDto.columnFormats.find((x: any) => x.fieldName === fieldName)
|
||
|
||
if (listFormField?.sourceDbType === DbTypeEnum.Date) {
|
||
editorOptions = {
|
||
...{
|
||
type: 'date',
|
||
dateSerializationFormat: 'yyyy-MM-dd',
|
||
displayFormat: 'shortDate',
|
||
},
|
||
...editorOptions,
|
||
}
|
||
} else if (
|
||
listFormField?.sourceDbType === DbTypeEnum.DateTime ||
|
||
listFormField?.sourceDbType === DbTypeEnum.DateTime2 ||
|
||
listFormField?.sourceDbType === DbTypeEnum.DateTimeOffset
|
||
) {
|
||
editorOptions = {
|
||
...{
|
||
type: 'datetime',
|
||
dateSerializationFormat: 'yyyy-MM-ddTHH:mm:ss',
|
||
displayFormat: 'shortDateShortTime',
|
||
},
|
||
...editorOptions,
|
||
}
|
||
}
|
||
|
||
// Set defaultValue for @AUTONUMBER fields
|
||
if (
|
||
typeof listFormField?.defaultValue === 'string' &&
|
||
listFormField?.defaultValue === '@AUTONUMBER' &&
|
||
currentMode === 'new'
|
||
) {
|
||
editorOptions = {
|
||
...editorOptions,
|
||
value: autoNumber(),
|
||
}
|
||
}
|
||
|
||
// EditorType belirleme
|
||
let editorType: any = i.editorType2 || i.editorType
|
||
if (i.editorType2 === PlatformEditorTypes.dxGridBox) {
|
||
editorType = 'dxDropDownBox'
|
||
} else if (i.editorType2) {
|
||
editorType = i.editorType2
|
||
}
|
||
|
||
// Lookup DataSource oluştur
|
||
if (listFormField?.lookupDto) {
|
||
const lookup = listFormField.lookupDto
|
||
|
||
if (lookup.dataSourceType === UiLookupDataSourceTypeEnum.Query) {
|
||
editorOptions.dataSource = new CustomStore({
|
||
key: 'key',
|
||
loadMode: 'raw',
|
||
load: async () => {
|
||
try {
|
||
const { dynamicFetch } = await import('@/services/form.service')
|
||
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
|
||
listFormCode,
|
||
listFormFieldName: fieldName,
|
||
filters: [],
|
||
})
|
||
return (response.data ?? []).map((a: any) => ({
|
||
key: a.Key,
|
||
name: a.Name,
|
||
group: a.Group,
|
||
}))
|
||
} catch (error) {
|
||
console.error('Lookup load error:', error)
|
||
return []
|
||
}
|
||
},
|
||
})
|
||
|
||
editorOptions.valueExpr = 'key'
|
||
editorOptions.displayExpr = 'name'
|
||
} else if (lookup.dataSourceType === UiLookupDataSourceTypeEnum.StaticData) {
|
||
if (lookup.lookupQuery) {
|
||
try {
|
||
const staticData = JSON.parse(lookup.lookupQuery)
|
||
editorOptions.dataSource = staticData
|
||
editorOptions.valueExpr = lookup.valueExpr || 'key'
|
||
editorOptions.displayExpr = lookup.displayExpr || 'name'
|
||
} catch (error) {
|
||
console.error('Static data parse error:', error)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
const item: SimpleItemWithColData = {
|
||
canRead: listFormField?.canRead ?? false,
|
||
canUpdate: listFormField?.canUpdate ?? false,
|
||
canCreate: listFormField?.canCreate ?? false,
|
||
canExport: listFormField?.canExport ?? false,
|
||
allowEditing: listFormField?.allowEditing ?? true,
|
||
allowAdding: listFormField?.allowAdding ?? true,
|
||
dataField: i.dataField,
|
||
name: i.dataField,
|
||
editorType2: i.editorType2,
|
||
editorType:
|
||
i.editorType2 == PlatformEditorTypes.dxGridBox
|
||
? 'dxDropDownBox'
|
||
: i.editorType2 == PlatformEditorTypes.dxImageUpload ||
|
||
i.editorType2 == PlatformEditorTypes.dxImageViewer
|
||
? undefined
|
||
: i.editorType2,
|
||
colSpan: i.colSpan,
|
||
editorOptions,
|
||
editorScript: i.editorScript,
|
||
}
|
||
|
||
if (i.dataField.indexOf(':') >= 0) {
|
||
item.label = { text: captionize(i.dataField.split(':')[1]) }
|
||
}
|
||
|
||
if (
|
||
(currentMode == 'edit' && !item.canUpdate) ||
|
||
(currentMode == 'new' && !item.canCreate)
|
||
) {
|
||
item.editorOptions = {
|
||
...item.editorOptions,
|
||
readOnly: true,
|
||
}
|
||
}
|
||
|
||
return item
|
||
}
|
||
|
||
sortedFormDto.forEach((e: any) => {
|
||
// Items'ları da order'a göre sırala
|
||
const sortedItems = (e.items || [])
|
||
.slice()
|
||
.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
|
||
|
||
const groupItems = sortedItems.map(mapFormItem)
|
||
|
||
if (e.itemType !== 'tabbed') {
|
||
// Grup kullanmadan direkt items'ları ekle - form'un colCount'u geçerli olsun
|
||
result.push(...groupItems)
|
||
} else if (e.itemType === 'tabbed' && tabbedItems.length > 0 && e === tabbedItems[0]) {
|
||
// Tabbed için caption OLMAMALI - sadece tabs array içinde title kullan
|
||
result.push({
|
||
itemType: 'tabbed',
|
||
// colCount tabbed item için OLMAMALI - sadece colSpan
|
||
colSpan: 1,
|
||
// caption kullanma! Tabs içindeki title'lar yeterli
|
||
tabs: tabbedItems.map((tabbedItem: any) => {
|
||
// Backend'den gelen colCount ve colSpan değerlerini kullan
|
||
const effectiveColCount = tabbedItem.colCount || 2
|
||
|
||
return {
|
||
title: tabbedItem.caption, // Her tab'ın title'ı
|
||
colCount: effectiveColCount,
|
||
items: tabbedItem.items
|
||
?.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1))
|
||
.map(mapFormItem)
|
||
.filter((a: any) => {
|
||
if (currentMode === 'new') {
|
||
return a.canCreate || a.canRead
|
||
} else if (currentMode === 'edit') {
|
||
return a.canUpdate || a.canRead
|
||
}
|
||
return false
|
||
}),
|
||
}
|
||
}),
|
||
})
|
||
}
|
||
})
|
||
}
|
||
|
||
// Form'u tamamen yeniden yapılandır
|
||
const hasTabbedItems = result.some((item: any) => item.itemType === 'tabbed')
|
||
|
||
// Form'u tamamen yeniden baştan yapılandır
|
||
e.form.option(
|
||
'colCount',
|
||
hasTabbedItems ? 1 : gridDto.gridOptions.editingFormDto?.[0]?.colCount || 2,
|
||
)
|
||
e.form.option(
|
||
'colCount',
|
||
hasTabbedItems ? 1 : gridDto.gridOptions.editingFormDto?.[0]?.colCount || 2,
|
||
)
|
||
e.form.option('showValidationSummary', false)
|
||
e.form.option('items', result)
|
||
|
||
// Yeni versiyonlarda bu şekilde Style değiştirme işlemi yapmak zorunda olmayabiliriz.
|
||
// Yani geçici olarak eklenmiştir.
|
||
// Tabbed varsa belirli class'lara sahip elementi bul ve flex-direction'ı değiştir
|
||
if (hasTabbedItems) {
|
||
setTimeout(() => {
|
||
const targetElement = document.querySelector(
|
||
'.dx-item-content.dx-box-item-content.dx-box-flex.dx-box.dx-widget.dx-collection',
|
||
)
|
||
if (targetElement) {
|
||
const htmlElement = targetElement as HTMLElement
|
||
|
||
// Mevcut style'ı al ve flex-direction: row'u column'a çevir
|
||
const currentStyle = htmlElement.getAttribute('style') || ''
|
||
const updatedStyle = currentStyle.replace(
|
||
/flex-direction:\s*row/gi,
|
||
'flex-direction: column',
|
||
)
|
||
htmlElement.setAttribute('style', updatedStyle)
|
||
}
|
||
}, 100)
|
||
}
|
||
},
|
||
[gridDto, translate, isPopupFullScreen, listFormCode],
|
||
)
|
||
|
||
return (
|
||
<>
|
||
<div ref={widgetGroupRef} className={(gridDto?.widgets?.length ?? 0) > 0 ? 'mt-2' : ''}>
|
||
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
|
||
</div>
|
||
|
||
<Container className={DX_CLASSNAMES}>
|
||
{!isSubForm && (
|
||
<Helmet
|
||
titleTemplate={`%s | ${APP_NAME}`}
|
||
title={translate('::' + gridDto?.gridOptions.title)}
|
||
defaultTitle={APP_NAME}
|
||
></Helmet>
|
||
)}
|
||
{!gridDto && (
|
||
<div className="p-4">
|
||
<Loading loading>Loading scheduler configuration...</Loading>
|
||
</div>
|
||
)}
|
||
{gridDto && !schedulerDataSource && (
|
||
<div className="p-4">
|
||
<Loading loading>Loading data source...</Loading>
|
||
</div>
|
||
)}
|
||
{gridDto && schedulerDataSource && (
|
||
<>
|
||
<div className="p-1">
|
||
<Scheduler
|
||
ref={schedulerRef as any}
|
||
key={`Scheduler-${listFormCode}-${schedulerDataSource ? 'loaded' : 'loading'}`}
|
||
id={'Scheduler-' + listFormCode}
|
||
dataSource={schedulerDataSource}
|
||
dateSerializationFormat="yyyy-MM-ddTHH:mm:ss"
|
||
textExpr={gridDto.gridOptions.schedulerOptionDto?.textExpr || 'text'}
|
||
startDateExpr={gridDto.gridOptions.schedulerOptionDto?.startDateExpr || 'startDate'}
|
||
endDateExpr={gridDto.gridOptions.schedulerOptionDto?.endDateExpr || 'endDate'}
|
||
allDayExpr={gridDto.gridOptions.schedulerOptionDto?.allDayExpr}
|
||
recurrenceRuleExpr={gridDto.gridOptions.schedulerOptionDto?.recurrenceRuleExpr}
|
||
recurrenceExceptionExpr={
|
||
gridDto.gridOptions.schedulerOptionDto?.recurrenceExceptionExpr
|
||
}
|
||
startDayHour={gridDto.gridOptions.schedulerOptionDto?.startDayHour || 8}
|
||
endDayHour={gridDto.gridOptions.schedulerOptionDto?.endDayHour || 18}
|
||
currentView={currentView}
|
||
onCurrentViewChange={onCurrentViewChange}
|
||
onAppointmentFormOpening={onAppointmentFormOpening}
|
||
onAppointmentAdding={() => {
|
||
props.refreshData?.()
|
||
}}
|
||
onAppointmentUpdating={() => {
|
||
props.refreshData?.()
|
||
}}
|
||
onAppointmentDeleting={() => {
|
||
props.refreshData?.()
|
||
}}
|
||
height={
|
||
gridDto.gridOptions.height > 0
|
||
? gridDto.gridOptions.height
|
||
: gridDto.gridOptions.fullHeight
|
||
? `calc(100vh - ${170 + widgetGroupHeight}px)`
|
||
: undefined
|
||
}
|
||
showAllDayPanel={gridDto.gridOptions.schedulerOptionDto?.showAllDayPanel ?? true}
|
||
crossScrollingEnabled={
|
||
gridDto.gridOptions.schedulerOptionDto?.crossScrollingEnabled ?? false
|
||
}
|
||
cellDuration={gridDto.gridOptions.schedulerOptionDto?.cellDuration || 30}
|
||
firstDayOfWeek={
|
||
(gridDto.gridOptions.schedulerOptionDto?.firstDayOfWeek as
|
||
| 0
|
||
| 1
|
||
| 2
|
||
| 3
|
||
| 4
|
||
| 5
|
||
| 6) || 1
|
||
}
|
||
adaptivityEnabled={true}
|
||
>
|
||
<Toolbar>
|
||
<Item name="dateNavigator" />
|
||
<Item name="today" />
|
||
<Item name="viewSwitcher" />
|
||
<Item
|
||
location="after"
|
||
widget="dxButton"
|
||
options={{
|
||
icon: 'refresh',
|
||
hint: translate('::ListForms.ListForm.Refresh'),
|
||
onClick: handleRefresh,
|
||
}}
|
||
/>
|
||
{checkPermission('App.Listforms.Listform.Update') && (
|
||
<Item
|
||
location="after"
|
||
widget="dxButton"
|
||
options={{
|
||
icon: 'preferences',
|
||
hint: 'Settings',
|
||
onClick: settingButtonClick,
|
||
}}
|
||
/>
|
||
)}
|
||
</Toolbar>
|
||
|
||
<Editing
|
||
allowAdding={gridDto.gridOptions.schedulerOptionDto?.allowAdding ?? false}
|
||
allowUpdating={gridDto.gridOptions.schedulerOptionDto?.allowEditing ?? false}
|
||
allowDeleting={gridDto.gridOptions.schedulerOptionDto?.allowDeleting ?? false}
|
||
allowResizing={gridDto.gridOptions.schedulerOptionDto?.allowResizing ?? false}
|
||
allowDragging={gridDto.gridOptions.schedulerOptionDto?.allowDragging ?? false}
|
||
/>
|
||
|
||
<View type="day" name={translate('::App.Listform.ListformField.Day')} />
|
||
<View type="week" name={translate('::ListForms.SchedulerOptions.Week')} />
|
||
<View type="workWeek" name={translate('::ListForms.SchedulerOptions.WorkWeek')} />
|
||
<View type="month" name={translate('::ListForms.SchedulerOptions.Month')} />
|
||
<View
|
||
type="timelineDay"
|
||
name={translate('::ListForms.SchedulerOptions.TimelineDay')}
|
||
maxAppointmentsPerCell="unlimited"
|
||
/>
|
||
<View
|
||
type="timelineWeek"
|
||
name={translate('::ListForms.SchedulerOptions.TimelineWeek')}
|
||
maxAppointmentsPerCell="unlimited"
|
||
/>
|
||
<View
|
||
type="timelineMonth"
|
||
name={translate('::ListForms.SchedulerOptions.TimelineMonth')}
|
||
maxAppointmentsPerCell="unlimited"
|
||
/>
|
||
<View type="agenda" name={translate('::ListForms.SchedulerOptions.Agenda')} />
|
||
|
||
{gridDto.gridOptions.schedulerOptionDto?.resources?.map((resource, index) => (
|
||
<Resource
|
||
key={index}
|
||
fieldExpr={resource.fieldExpr}
|
||
dataSource={resource.dataSource}
|
||
label={resource.label}
|
||
useColorAsDefault={resource.useColorAsDefault}
|
||
/>
|
||
))}
|
||
</Scheduler>
|
||
</div>
|
||
</>
|
||
)}
|
||
</Container>
|
||
</>
|
||
)
|
||
}
|
||
|
||
export default SchedulerView
|