forked from ChurchCRM/CRM
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
React/calendar react (ChurchCRM#4716)
* Add React Enviornment * Convert Calendar to React * comments * don't bother nuking host-side node_modules at provision * make the webpack build work (and on windows) * cleanup react code. * two spaces = tab indentation * add pinned calendars using react-select * tell webpack to use development output mode * add handler for pinned calendars (not quite saving the state yet though) * move files * cleanup react code for event editor * split editor and viewer to separate files. link things up. * cleanup and now populate pinned calendars dropdown * rename Calendar interface; loading calendars over AJAX for dropdown list * updates to pinnedcalendar ui now properly updates state.event * Fix Schema.xml, and add PinnedCalednars to event object array render * working display and partially working udpate of pinned calendars * update CRMEvent interface from Schema.xml * begin trying to get new event creation working * working display and edit for pinned calendars and event type * fix merge versions * update package-lock * add react-datepicker; ensure copied from node_modules to skin/external * Added event handler for start and end time * update the API backend to accept event properties as defined in the TS interface file * add react-moment to render formatted start and end dates * add interface definitions for the javascript window object's i18next for TypeScript * use i18next, and cleanup wording * add build-react step to travis file * fix conflicts with master package.json * update gruntfile from master * update package-lock, composer, upgrade * add a window object to reference whether FullCalendarJS is finished loading * add test for new react event creation form * add missing inputId for the react-select elements * update react-datepicker; drop react-moment * add accessor to the global momentjs inside typescript * cleanup display formatting of DatePicker * use TypeScript Date native toString method * Ensure state.event is properly initialized to the interface definition with Date() objects * Use a stringify replacer to ensure Date objects are submitted in ISO8601 combined format example: 2007-04-05T12:30-02:00 * minor syntax cleanup * Ensure CRMEvent interface uses Date not string * remove dead code * cleanup console.log entries before mergning to master * remove weird vagrant node_modules sync stuff * undo change to vagrant bootstrap - leave the node_modules directory un-sync'd as it was
- Loading branch information
1 parent
0cce932
commit 9c97c2a
Showing
24 changed files
with
13,545 additions
and
5,304 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,3 +49,4 @@ src/logs/*.log | |
error.log | ||
|
||
nbproject/* | ||
/src/skin/js-react/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import * as React from 'react'; | ||
import * as ReactDOM from 'react-dom'; | ||
import CRMEvent from './interfaces/CRMEvent'; | ||
import ExistingEvent from './components/ExistingEvent'; | ||
declare global { | ||
interface Window { | ||
// Since TypeScript requires a definition for all methods, let's tell it how to handle the javascript objects already in the page | ||
showEventForm(object): void, | ||
showNewEventForm(start: string,end: string): void, | ||
CRM: { | ||
// we need to access this method of CRMJSOM, so let's tell TypeScript how to use it | ||
refreshAllFullCalendarSources(): void | ||
}, | ||
// React does have it's own i18next implementation, but for now, lets use the one that's already being loaded | ||
i18next: { | ||
t(string): string | ||
}, | ||
// instead of loading the whole react-moment class, we can just use the one that's already on window. | ||
moment: any | ||
} | ||
} | ||
|
||
window.showEventForm = function(event) { | ||
const unmount = function() { | ||
ReactDOM.unmountComponentAtNode( document.getElementById('calendar-event-react-app')); | ||
window.CRM.refreshAllFullCalendarSources() | ||
} | ||
unmount(); | ||
ReactDOM.render(<ExistingEvent onClose={unmount} eventId={event.id}/>, document.getElementById('calendar-event-react-app')); | ||
} | ||
|
||
window.showNewEventForm = function(start,end) { | ||
const unmount = function() { | ||
ReactDOM.unmountComponentAtNode( document.getElementById('calendar-event-react-app')); | ||
window.CRM.refreshAllFullCalendarSources() | ||
} | ||
unmount(); | ||
ReactDOM.render(<ExistingEvent onClose={unmount} eventId={0} />, document.getElementById('calendar-event-react-app')); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import * as React from 'react'; | ||
import CRMEvent from '../interfaces/CRMEvent'; | ||
import Calendar from '../interfaces/Calendar'; | ||
import EventType from '../interfaces/EventType'; | ||
import { Modal, FormControl } from 'react-bootstrap'; | ||
import Select from 'react-select'; | ||
import DatePicker from 'react-datepicker'; | ||
|
||
|
||
const EventPropertiesEditor: React.FunctionComponent<{ event: CRMEvent, calendars: Array<Calendar>, eventTypes: Array<EventType>, changeHandler: (event:React.ChangeEvent)=>void, handleStartDateChange: (date: any)=>void, handleEndDateChange: (date: any)=>void, pinnedCalendarChanged: (event: Array<Object>) => void, eventTypeChanged: (event: Array<Object>) => void }> = ({ event, calendars, eventTypes, changeHandler, handleStartDateChange, handleEndDateChange, pinnedCalendarChanged, eventTypeChanged }) => { | ||
//map the Calendar data type (returned from CRM API) into something that react-select can present as dropdown choices | ||
var calendarOptions=calendars.map((Pcal:Calendar) => ({value: Pcal.Id, label: Pcal.Name}) ); | ||
var EventTypeOptions=eventTypes.map((eventType:EventType) => ({value: eventType.Id, label: eventType.Name}) ); | ||
var initialPinnedCalendarValue=calendars.map((Pcal:Calendar) => {if (event.PinnedCalendars.includes(Pcal.Id) ) { return {value: Pcal.Id, label: Pcal.Name}} } ); | ||
var initialEventTypeValue= eventTypes.map( (eventType:EventType) => { if (event.Type == eventType.Id) { return { value: eventType.Id, label: eventType.Name } } } ); | ||
return ( | ||
<table className="table modal-table"> | ||
<tbody> | ||
<tr> | ||
<td className="LabelColumn"> | ||
{window.i18next.t('Event Type')} | ||
</td> | ||
<td className="TextColumn"> | ||
<Select name="EventType" inputId="EventType" options={EventTypeOptions} value={initialEventTypeValue} onChange={eventTypeChanged} /> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td className="LabelColumn"> | ||
{window.i18next.t('Description')} | ||
</td> | ||
<td className="TextColumn"> | ||
<textarea name="Desc" value={event.Desc} onChange={changeHandler} /> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td className="LabelColumn"> | ||
{window.i18next.t('Start Date')} | ||
</td> | ||
<td className="TextColumn"> | ||
<DatePicker | ||
name="Start" | ||
selected={event.Start} | ||
onChange={handleStartDateChange} | ||
showTimeSelect | ||
timeFormat="h:mm" | ||
timeIntervals={15} | ||
dateFormat="MMMM d, yyyy h:mm aa" | ||
timeCaption="time" /> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td className="LabelColumn"> | ||
{window.i18next.t('End Date')} | ||
</td> | ||
<td className="TextColumn"> | ||
<DatePicker | ||
name="End" | ||
minDate={event.Start} | ||
selected={event.End} | ||
onChange={handleEndDateChange} | ||
showTimeSelect | ||
timeFormat="h:mm" | ||
timeIntervals={15} | ||
dateFormat="MMMM d, yyyy h:mm aa" | ||
timeCaption="time" /> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td className="LabelColumn"> | ||
{window.i18next.t('Pinned Calendars')} | ||
</td> | ||
<td className="TextColumn"> | ||
<Select name="PinnedCalendars" inputId="PinnedCalendars" options={calendarOptions} value={initialPinnedCalendarValue} onChange={pinnedCalendarChanged} isMulti="true" /> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td className="LabelColumn"> | ||
{window.i18next.t('Text')} | ||
</td> | ||
<td className="TextColumn"> | ||
<textarea name="Text" value={event.Text} onChange={changeHandler} /> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
)} | ||
|
||
|
||
export default EventPropertiesEditor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import * as React from 'react'; | ||
import CRMEvent from '../interfaces/CRMEvent'; | ||
import Calendar from '../interfaces/Calendar'; | ||
import EventType from '../interfaces/EventType'; | ||
|
||
const EventPropertiesViewer: React.FunctionComponent<{ event: CRMEvent, calendars: Array<Calendar>, eventTypes: Array<EventType> }> = ({ event, calendars, eventTypes }) => { | ||
return ( | ||
<table className="table modal-table"> | ||
<tbody> | ||
<tr> | ||
<td> | ||
{window.i18next.t('Type')} | ||
</td> | ||
<td> | ||
{ | ||
eventTypes.map( | ||
(eventType: EventType)=> { | ||
if (event.Type != null && event.Type == eventType.Id) { | ||
return (<p>{eventType.Name}</p>) | ||
} | ||
} | ||
) | ||
} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
{window.i18next.t('Event Description')} | ||
</td> | ||
<td> | ||
{event.Desc} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
{window.i18next.t('Start Date')} | ||
</td> | ||
<td> | ||
{event.Start.toString()} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
{window.i18next.t('End Date')} | ||
</td> | ||
<td> | ||
{event.End.toString()} | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
{window.i18next.t('Pinned Calendars')} | ||
</td> | ||
<td> | ||
<ul> | ||
{ | ||
calendars.map( | ||
(calendar: Calendar)=> { | ||
if (event.PinnedCalendars != null && event.PinnedCalendars.includes(calendar.Id)) { | ||
return (<li>{calendar.Name}</li>) | ||
} | ||
} | ||
) | ||
} | ||
</ul> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
{window.i18next.t('Text')} | ||
</td> | ||
<td> | ||
{event.Text} | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
)} | ||
export default EventPropertiesViewer; |
Oops, something went wrong.