From c60e06754d24dc01a1e72b5f8ade601476b4b024 Mon Sep 17 00:00:00 2001 From: enkhtuvshinD <87625210+enkhtuvshinD@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:28:36 +0800 Subject: [PATCH 01/19] change calendar to fullcalendar --- .../src/models/Meetings.ts | 3 +- packages/plugin-meetings-ui/package.json | 5 + .../src/components/List.tsx | 13 +- .../src/components/myCalendar/MyCalendar.tsx | 19 +- .../myCalendar/meeting/Calendar.tsx | 171 +- .../components/myCalendar/meeting/Detail.tsx | 3 +- .../components/myCalendar/meeting/Form.tsx | 16 +- .../src/containers/myCalendar/MyCalendar.tsx | 27 +- .../myCalendar/meeting/Calendar.tsx | 46 + .../containers/myCalendar/meeting/Detail.tsx | 21 +- .../containers/myCalendar/meeting/Form.tsx | 1 + packages/plugin-meetings-ui/src/types.ts | 8 - yarn.lock | 7066 +++++++++-------- 13 files changed, 3775 insertions(+), 3624 deletions(-) create mode 100644 packages/plugin-meetings-ui/src/containers/myCalendar/meeting/Calendar.tsx diff --git a/packages/plugin-meetings-api/src/models/Meetings.ts b/packages/plugin-meetings-api/src/models/Meetings.ts index df0f0f7939..63fc1f0099 100644 --- a/packages/plugin-meetings-api/src/models/Meetings.ts +++ b/packages/plugin-meetings-api/src/models/Meetings.ts @@ -53,7 +53,8 @@ export const loadMeetingClass = (model: IModels) => { } const result = await model.Meetings.findOne({ _id: doc._id, - createdBy: user._id + createdBy: user._id, + status: { $ne: 'completed' } }); if (result) { await model.Meetings.updateOne( diff --git a/packages/plugin-meetings-ui/package.json b/packages/plugin-meetings-ui/package.json index fa27061148..dcb17b90fa 100644 --- a/packages/plugin-meetings-ui/package.json +++ b/packages/plugin-meetings-ui/package.json @@ -7,6 +7,11 @@ "build": "cd .erxes && yarn build" }, "dependencies": { + "@fullcalendar/core": "^6.1.8", + "@fullcalendar/daygrid": "^6.1.8", + "@fullcalendar/interaction": "^6.1.8", + "@fullcalendar/react": "^6.1.8", + "@fullcalendar/timegrid": "^6.1.8", "moment": "^2.29.4", "react": "^18.2.0", "react-big-calendar": "^1.8.1", diff --git a/packages/plugin-meetings-ui/src/components/List.tsx b/packages/plugin-meetings-ui/src/components/List.tsx index 0058c0930d..c35dd0cbfa 100755 --- a/packages/plugin-meetings-ui/src/components/List.tsx +++ b/packages/plugin-meetings-ui/src/components/List.tsx @@ -64,12 +64,15 @@ function List(props: Props) { /> ); break; - // case 'agendaTemplate': - // setComponent(
1
); - // setSideBar(
sidebar 1
); - // break; default: - setComponent(); + setComponent( + + ); setSideBar( { @@ -20,7 +23,8 @@ export const MyCalendarList = (props: Props) => { title: meeting.title, start: new Date(meeting.startDate), // Year, Month (0-11), Day, Hour, Minute end: new Date(meeting.endDate), - bgColor: generateColorCode(meeting.createdBy) + id: meeting._id, + color: generateColorCode(meeting.createdBy) })) || []; const companyId = @@ -36,7 +40,12 @@ export const MyCalendarList = (props: Props) => { // Add more events as needed return !meetingId ? ( - + ) : ( <> diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Calendar.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Calendar.tsx index 46f15fe744..9676e9a948 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Calendar.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Calendar.tsx @@ -1,55 +1,136 @@ -import React from 'react'; -import { Calendar, momentLocalizer } from 'react-big-calendar'; -import 'react-big-calendar/lib/css/react-big-calendar.css'; -import moment from 'moment'; +import React, { useEffect, useState } from 'react'; +import { EventClickArg, formatDate } from '@fullcalendar/core'; +import FullCalendar from '@fullcalendar/react'; +import dayGridPlugin from '@fullcalendar/daygrid'; +import timeGridPlugin from '@fullcalendar/timegrid'; +import interactionPlugin from '@fullcalendar/interaction'; +import { router } from '@erxes/ui/src/utils/core'; +import { useHistory } from 'react-router-dom'; +import MeetingFormContainer from '../../../containers/myCalendar/meeting/Form'; +import { Modal } from 'react-bootstrap'; +import { IMeeting } from '../../../types'; +import { IUser } from '@erxes/ui/src/auth/types'; type Props = { - events: any[]; + meetings?: IMeeting[]; + queryParams: any; + currentUser: IUser; + events: any; + changeDateMeeting: ( + _id: string, + start: string, + end: string, + callback: () => void + ) => void; }; -const localizer = momentLocalizer(moment); - -export const CalendarComponent = ({ events }: Props) => { - const MyCustomEvent = ({ event }: any) => { - return ( -
{ + setShowModal(false); + }, [meetings]); + + const handleDateSelect = selectInfo => { + let calendarApi = selectInfo.view.calendar; + + calendarApi.unselect(); // clear date selection + setStartDate(selectInfo.startStr); + setEndDate(selectInfo.endStr); + setShowModal(true); + }; + + const handleEventClick = ({ event }: EventClickArg) => { + router.setParams(history, { meetingId: event.id }); + }; + + const changeEvent = e => { + const { event, revert } = e; + const { id, _instance } = event; + const { range = {} } = _instance; + const { end, start } = range; + + if (end && start) { + changeDateMeeting(id, start, end, revert); + } + }; + + const renderEventContent = ({ event }: EventClickArg) => ( +
+ + {event.title} + + - {event.title} - - {moment(event.start).format('LT') + - '-' + - moment(event.end).format('LT')} - -
- ); + {formatDate(event.startStr!, { + hour: '2-digit', + minute: '2-digit' + })} + +
+ ); + + const object = { + startDate, + endDate }; return ( -
- + ({ - style: { - backgroundColor: event.bgColor, - margin: '1px 2px', - width: 'calc(100% - 2px)', - borderRadius: '6px', - padding: '2px 8px' - } - })} + initialView="dayGridMonth" + editable={true} + selectMirror={true} + selectable={true} + dayMaxEvents={true} + initialEvents={events} + select={handleDateSelect} + eventContent={renderEventContent} + eventClick={handleEventClick} + eventChange={changeEvent} /> -
+ setShowModal(false)} size="lg"> + + Create Meeting + + + setShowModal(false)} + calendarDate={object} + /> + + + ); -}; +} + +export default CalendarComponent; diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx index 2ba2f563ab..a217c8cb33 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx @@ -74,7 +74,6 @@ export const MeetingDetail = (props: Props) => { meetingId={meetingDetail._id} participantUserIds={meetingDetail.participantUser?.map(user => user._id)} meetingStatus={meetingDetail.status} - // closeModal={() => setShowTopicModal(false)} /> ); @@ -153,7 +152,7 @@ export const MeetingDetail = (props: Props) => { }} icon="times-circle" > - Cancel + Cancel meeting + ); + + const updatedProps = { + meetings, + refetch: ['meetings'] + }; + + const content = props =>
; + + return ( + + ); + }; + + return ( + + {renderContent()} + + ); +}; + +export default meetingDealList; diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx index 497d854888..79e84c6951 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx @@ -3,7 +3,6 @@ import React, { useState } from 'react'; import Detail from '../../containers/myCalendar/meeting/Detail'; import PreviousDetail from '../../containers/myCalendar/meeting/PreviousDetail'; import { IMeeting, MeetingsQueryResponse } from '../../types'; -import { generateColorCode } from '../../utils'; import { IUser } from '@erxes/ui/src/auth/types'; import { CalendarContainer } from '../../containers/myCalendar/meeting/Calendar'; @@ -18,30 +17,28 @@ export const MyCalendarList = (props: Props) => { const { meetings, queryParams } = props; const { meetingId } = queryParams; const [currentTab, setCurrentTab] = useState('This session'); - const events = - meetings?.map((meeting: IMeeting) => ({ - title: meeting.title, - start: new Date(meeting.startDate), // Year, Month (0-11), Day, Hour, Minute - end: new Date(meeting.endDate), - id: meeting._id, - color: generateColorCode(meeting.createdBy) - })) || []; const companyId = (meetings?.find(meeting => meeting._id === meetingId) ?.companyId as string) || ''; + const dealIds = meetings?.find(meeting => meeting._id === meetingId) + ?.dealIds as string[]; const renderTabContent = () => { if (currentTab === 'Previous session') { return ; } - return ; + return ( + + ); }; - // Add more events as needed return !meetingId ? ( { setShowModal(false); - }, [meetings]); + setMeetings(meetings); + }, [meetings, meetings.length]); + + const events = + updatedMeetings?.map((meeting: IMeeting) => ({ + title: meeting.title, + start: new Date(meeting.startDate), // Year, Month (0-11), Day, Hour, Minute + end: new Date(meeting.endDate), + id: meeting._id, + color: generateColorCode(meeting.createdBy) + })) || []; const handleDateSelect = selectInfo => { let calendarApi = selectInfo.view.calendar; @@ -102,7 +107,7 @@ function CalendarComponent(props: Props) { selectMirror={true} selectable={true} dayMaxEvents={true} - initialEvents={events} + events={events} select={handleDateSelect} eventContent={renderEventContent} eventClick={handleEventClick} diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx index a217c8cb33..9f3badc37d 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx @@ -20,9 +20,10 @@ import Button from '@erxes/ui/src/components/Button'; type Props = { meetingDetail: IMeeting; changeStatus: (status: string, meetingId: string) => void; + deals: { _id: string; name: string }[]; }; export const MeetingDetail = (props: Props) => { - const { meetingDetail, changeStatus } = props; + const { meetingDetail, changeStatus, deals } = props; const { topics } = meetingDetail; const { participantUser } = meetingDetail || {}; @@ -126,6 +127,14 @@ export const MeetingDetail = (props: Props) => { })} + + + Deals:{' '} + {deals?.map(deal => { + return <>{deal.name}, ; + })} + +

{meetingDetail.description}

diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx index d4a1436e72..99576bf3dc 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx @@ -14,6 +14,8 @@ import DateControl from '@erxes/ui/src/components/form/DateControl'; import SelectTeamMembers from '@erxes/ui/src/team/containers/SelectTeamMembers'; import { IUser } from '@erxes/ui/src/auth/types'; import { CompaniesQueryResponse } from '@erxes/ui-contacts/src/companies/types'; +import SelectCompanies from '@erxes/ui-contacts/src/companies/containers/SelectCompanies'; +import { DealsQueryResponse } from '@erxes/ui-cards/src/deals/types'; type Props = { renderButton: (props: IButtonMutateProps) => JSX.Element; @@ -21,16 +23,26 @@ type Props = { queryParams: any; currentUser: IUser; companiesQuery: CompaniesQueryResponse; + dealsQuery: DealsQueryResponse; calendarDate?: { startDate: string; endDate: string }; } & ICommonFormProps; export const MeetingForm = (props: Props) => { - const { companiesQuery, meeting, queryParams, calendarDate } = props; + const { + companiesQuery, + meeting, + queryParams, + calendarDate, + dealsQuery + } = props; const { companies } = companiesQuery || {}; + const { deals } = dealsQuery || {}; + const [userIds, setUserIds] = useState([props.currentUser._id] || []); const [companyId, setCompanyId] = useState(''); const [title, setTitle] = useState(''); const [selectedMethod, setSelectedMethod] = useState(''); + const [dealId, setDealId] = useState(''); const [startDate, setStartDate] = useState( calendarDate?.startDate || new Date() @@ -52,6 +64,7 @@ export const MeetingForm = (props: Props) => { endDate: string | Date; companyId: string; method: string; + dealIds: string[]; }) => { const finalValues = values; @@ -74,6 +87,9 @@ export const MeetingForm = (props: Props) => { if (selectedMethod) { finalValues.method = selectedMethod; } + if (dealId) { + finalValues.dealIds = [dealId]; + } return { ...finalValues @@ -123,8 +139,12 @@ export const MeetingForm = (props: Props) => { setUserIds(users); }; - const onCompanySelect = e => { - setCompanyId((e.target as HTMLInputElement).value); + const onDealSelect = e => { + setDealId(e.target.value); + }; + + const onCompanySelect = companyId => { + setCompanyId(companyId); }; const onMethodSelect = e => { @@ -136,14 +156,14 @@ export const MeetingForm = (props: Props) => { const { values, isSubmitted } = formProps; const object = meeting || ({} as IMeeting); - const companyOptions = - (companies && - companies.map((company: any) => ({ - value: company._id, - label: company.primaryName || '', - avatar: company.avatar + let dealOptions = + (deals && + deals.map((deal: any) => ({ + value: deal._id, + label: deal.name || '' }))) || []; + dealOptions = [{ value: '', label: '' }, ...dealOptions]; return ( <> @@ -151,16 +171,12 @@ export const MeetingForm = (props: Props) => {

{object?.title || title}

- Choose Company - Choose Company + @@ -225,6 +241,19 @@ export const MeetingForm = (props: Props) => { /> + + Select Deal + + + + ); + + const updatedProps = { + meetings, + refetch: ['meetings'] + }; + + const content = props => ; + + return ( + + ); + }; + + return ( + + {renderContent()} + + ); +}; + +export default meetingDealList; diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx index 497d854888..79e84c6951 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/MyCalendar.tsx @@ -3,7 +3,6 @@ import React, { useState } from 'react'; import Detail from '../../containers/myCalendar/meeting/Detail'; import PreviousDetail from '../../containers/myCalendar/meeting/PreviousDetail'; import { IMeeting, MeetingsQueryResponse } from '../../types'; -import { generateColorCode } from '../../utils'; import { IUser } from '@erxes/ui/src/auth/types'; import { CalendarContainer } from '../../containers/myCalendar/meeting/Calendar'; @@ -18,30 +17,28 @@ export const MyCalendarList = (props: Props) => { const { meetings, queryParams } = props; const { meetingId } = queryParams; const [currentTab, setCurrentTab] = useState('This session'); - const events = - meetings?.map((meeting: IMeeting) => ({ - title: meeting.title, - start: new Date(meeting.startDate), // Year, Month (0-11), Day, Hour, Minute - end: new Date(meeting.endDate), - id: meeting._id, - color: generateColorCode(meeting.createdBy) - })) || []; const companyId = (meetings?.find(meeting => meeting._id === meetingId) ?.companyId as string) || ''; + const dealIds = meetings?.find(meeting => meeting._id === meetingId) + ?.dealIds as string[]; const renderTabContent = () => { if (currentTab === 'Previous session') { return ; } - return ; + return ( + + ); }; - // Add more events as needed return !meetingId ? ( { setShowModal(false); - }, [meetings]); + setMeetings(meetings); + }, [meetings, meetings.length]); + + const events = + updatedMeetings?.map((meeting: IMeeting) => ({ + title: meeting.title, + start: new Date(meeting.startDate), // Year, Month (0-11), Day, Hour, Minute + end: new Date(meeting.endDate), + id: meeting._id, + color: generateColorCode(meeting.createdBy) + })) || []; const handleDateSelect = selectInfo => { let calendarApi = selectInfo.view.calendar; @@ -102,7 +107,7 @@ function CalendarComponent(props: Props) { selectMirror={true} selectable={true} dayMaxEvents={true} - initialEvents={events} + events={events} select={handleDateSelect} eventContent={renderEventContent} eventClick={handleEventClick} diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx index a217c8cb33..9f3badc37d 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Detail.tsx @@ -20,9 +20,10 @@ import Button from '@erxes/ui/src/components/Button'; type Props = { meetingDetail: IMeeting; changeStatus: (status: string, meetingId: string) => void; + deals: { _id: string; name: string }[]; }; export const MeetingDetail = (props: Props) => { - const { meetingDetail, changeStatus } = props; + const { meetingDetail, changeStatus, deals } = props; const { topics } = meetingDetail; const { participantUser } = meetingDetail || {}; @@ -126,6 +127,14 @@ export const MeetingDetail = (props: Props) => { })}
+ + + Deals:{' '} + {deals?.map(deal => { + return <>{deal.name}, ; + })} + +

{meetingDetail.description}

diff --git a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx index d4a1436e72..99576bf3dc 100644 --- a/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx +++ b/packages/plugin-meetings-ui/src/components/myCalendar/meeting/Form.tsx @@ -14,6 +14,8 @@ import DateControl from '@erxes/ui/src/components/form/DateControl'; import SelectTeamMembers from '@erxes/ui/src/team/containers/SelectTeamMembers'; import { IUser } from '@erxes/ui/src/auth/types'; import { CompaniesQueryResponse } from '@erxes/ui-contacts/src/companies/types'; +import SelectCompanies from '@erxes/ui-contacts/src/companies/containers/SelectCompanies'; +import { DealsQueryResponse } from '@erxes/ui-cards/src/deals/types'; type Props = { renderButton: (props: IButtonMutateProps) => JSX.Element; @@ -21,16 +23,26 @@ type Props = { queryParams: any; currentUser: IUser; companiesQuery: CompaniesQueryResponse; + dealsQuery: DealsQueryResponse; calendarDate?: { startDate: string; endDate: string }; } & ICommonFormProps; export const MeetingForm = (props: Props) => { - const { companiesQuery, meeting, queryParams, calendarDate } = props; + const { + companiesQuery, + meeting, + queryParams, + calendarDate, + dealsQuery + } = props; const { companies } = companiesQuery || {}; + const { deals } = dealsQuery || {}; + const [userIds, setUserIds] = useState([props.currentUser._id] || []); const [companyId, setCompanyId] = useState(''); const [title, setTitle] = useState(''); const [selectedMethod, setSelectedMethod] = useState(''); + const [dealId, setDealId] = useState(''); const [startDate, setStartDate] = useState( calendarDate?.startDate || new Date() @@ -52,6 +64,7 @@ export const MeetingForm = (props: Props) => { endDate: string | Date; companyId: string; method: string; + dealIds: string[]; }) => { const finalValues = values; @@ -74,6 +87,9 @@ export const MeetingForm = (props: Props) => { if (selectedMethod) { finalValues.method = selectedMethod; } + if (dealId) { + finalValues.dealIds = [dealId]; + } return { ...finalValues @@ -123,8 +139,12 @@ export const MeetingForm = (props: Props) => { setUserIds(users); }; - const onCompanySelect = e => { - setCompanyId((e.target as HTMLInputElement).value); + const onDealSelect = e => { + setDealId(e.target.value); + }; + + const onCompanySelect = companyId => { + setCompanyId(companyId); }; const onMethodSelect = e => { @@ -136,14 +156,14 @@ export const MeetingForm = (props: Props) => { const { values, isSubmitted } = formProps; const object = meeting || ({} as IMeeting); - const companyOptions = - (companies && - companies.map((company: any) => ({ - value: company._id, - label: company.primaryName || '', - avatar: company.avatar + let dealOptions = + (deals && + deals.map((deal: any) => ({ + value: deal._id, + label: deal.name || '' }))) || []; + dealOptions = [{ value: '', label: '' }, ...dealOptions]; return ( <> @@ -151,16 +171,12 @@ export const MeetingForm = (props: Props) => {

{object?.title || title}

- Choose Company - Choose Company + @@ -225,6 +241,19 @@ export const MeetingForm = (props: Props) => { /> + + Select Deal + + + - + ) : ( - } + header={} actionBar={actionBar} content={ void; + count: number; }; export const ListComponent = (props: Props) => { - const { meetings, remove } = props; + const { meetings, remove, count } = props; + return ( <> @@ -26,11 +28,18 @@ export const ListComponent = (props: Props) => { - {meetings?.map((meeting: IMeeting) => { - return remove(meeting._id)} />; + {meetings?.map((meeting: IMeeting, index: number) => { + return ( + remove(meeting._id)} + /> + ); })}
+ ); }; diff --git a/packages/plugin-meetings-ui/src/components/myMeetings/Row.tsx b/packages/plugin-meetings-ui/src/components/myMeetings/Row.tsx index c6f220422c..4d6367877e 100644 --- a/packages/plugin-meetings-ui/src/components/myMeetings/Row.tsx +++ b/packages/plugin-meetings-ui/src/components/myMeetings/Row.tsx @@ -6,13 +6,14 @@ import { IMeeting } from '../../types'; '@erxes/ui/src/components/MemberAvatars'; import ActionButtons from '@erxes/ui/src/components/ActionButtons'; import Form from '../../containers/myCalendar/meeting/Form'; - +import { useHistory } from 'react-router-dom'; type Props = { meeting: IMeeting; remove: () => void; }; export const Row = (props: Props) => { const { meeting, remove } = props; + const history = useHistory(); const editTrigger = (