tachybase_todo/packages/client/src/schema-component/antd/calendar-v2/Calendar.tsx
chenos 74779a0d46
feat: block provider (#261)
* feat: block schema

* feat: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* feat: styling for kanban

* feat: improve code

* feat: improve code

* fix(client): auto collapse menu items when overflow

* feat: improve code

* fix: fieldNames prop for calendar

* fix: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* feat: improve code

* fix: list the sub-table data source

* fix: useFilterByTk

* feat: improve code

* feat: improve code

* feat: improve code
2022-04-04 00:30:40 +08:00

157 lines
4.6 KiB
TypeScript

import { LeftOutlined, RightOutlined } from '@ant-design/icons';
import { createForm } from '@formily/core';
import { observer, RecursionField, Schema, useFieldSchema } from '@formily/react';
import get from 'lodash/get';
import moment from 'moment';
import React, { useMemo, useState } from 'react';
import { Calendar as BigCalendar, momentLocalizer } from 'react-big-calendar';
import * as dates from 'react-big-calendar/lib/utils/dates';
import { useTranslation } from 'react-i18next';
import { RecordProvider } from '../../../';
import { i18n } from '../../../i18n';
import { useProps } from '../../hooks/useProps';
import { ActionContext } from '../action';
import { CalendarToolbarContext } from './context';
import './style.less';
import type { ToolbarProps } from './types';
const localizer = momentLocalizer(moment);
function Toolbar(props: ToolbarProps) {
const fieldSchema = useFieldSchema();
const toolBarSchema: Schema = useMemo(
() =>
fieldSchema.reduceProperties((buf, current) => {
if (current['x-component'].endsWith('.ActionBar')) {
return current;
}
return buf;
}, null),
[],
);
return (
<CalendarToolbarContext.Provider value={props}>
<RecursionField name={toolBarSchema.name} schema={toolBarSchema} />
</CalendarToolbarContext.Provider>
);
}
const messages: any = {
allDay: '',
previous: (
<div>
<LeftOutlined />
</div>
),
next: (
<div>
<RightOutlined />
</div>
),
today: i18n.t('Today'),
month: i18n.t('Month'),
week: i18n.t('Week'),
work_week: i18n.t('Work week'),
day: i18n.t('Day'),
agenda: i18n.t('Agenda'),
date: i18n.t('Date'),
time: i18n.t('Time'),
event: i18n.t('Event'),
noEventsInRange: i18n.t('None'),
showMore: (count) => i18n.t('{{count}} more items', { count }),
};
const useEvents = (dataSource: any, fieldNames: any) => {
const { t } = useTranslation();
return useMemo(
() =>
Array.isArray(dataSource)
? dataSource?.map((item) => {
return {
id: get(item, fieldNames.id || 'id'),
title: get(item, fieldNames.title) || t('Untitle'),
start: new Date(get(item, fieldNames.start)),
end: new Date(get(item, fieldNames.end || fieldNames.start)),
};
})
: [],
[dataSource, fieldNames],
);
};
const CalendarRecordViewer = (props) => {
const { visible, setVisible, record } = props;
const form = useMemo(() => createForm(), [record]);
const fieldSchema = useFieldSchema();
const eventSchema: Schema = useMemo(
() =>
fieldSchema.reduceProperties((buf, current) => {
if (current['x-component'].endsWith('.Event')) {
return current;
}
return buf;
}, null),
[],
);
return (
eventSchema && (
<ActionContext.Provider value={{ visible, setVisible }}>
<RecordProvider record={record}>
<RecursionField schema={eventSchema} name={eventSchema.name} />
</RecordProvider>
</ActionContext.Provider>
)
);
};
export const Calendar: any = observer((props: any) => {
const { dataSource, fieldNames } = useProps(props);
const events = useEvents(dataSource, fieldNames);
const [visible, setVisible] = useState(false);
const [record, setRecord] = useState<any>({});
return (
<div {...props} style={{ height: 700 }}>
<CalendarRecordViewer visible={visible} setVisible={setVisible} record={record} />
<BigCalendar
popup
selectable
events={events}
views={['month', 'week', 'day']}
step={60}
showMultiDayTimes
messages={messages}
onSelectSlot={(slotInfo) => {
console.log('onSelectSlot', slotInfo);
}}
onDoubleClickEvent={(event) => {
console.log('onDoubleClickEvent');
}}
onSelectEvent={(event) => {
const record = dataSource?.find((item) => item[fieldNames.id] === event.id);
if (!record) {
return;
}
setRecord(record);
setVisible(true);
}}
formats={{
monthHeaderFormat: 'Y-M',
agendaDateFormat: 'M-DD',
dayHeaderFormat: 'Y-M-DD',
dayRangeHeaderFormat: ({ start, end }, culture, local) => {
if (dates.eq(start, end, 'month')) {
return local.format(start, 'Y-M', culture);
}
return `${local.format(start, 'Y-M', culture)} - ${local.format(end, 'Y-M', culture)}`;
},
}}
defaultDate={new Date()}
components={{
toolbar: Toolbar,
}}
localizer={localizer}
/>
</div>
);
});