import * as React from 'react'; import './CalendarManager.scss'; import { observer } from "mobx-react"; import { action, computed, observable, runInAction } from 'mobx'; import { Doc, DocListCast } from '../../fields/Doc'; import { DocumentView } from '../views/nodes/DocumentView'; import { DictationOverlay } from '../views/DictationOverlay'; import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; import { MainViewModal } from '../views/MainViewModal'; import { TextField } from '@material-ui/core'; import Select from 'react-select'; import { SettingsManager } from './SettingsManager'; import { DocCast, StrCast } from '../../fields/Types'; import { SelectionManager } from './SelectionManager'; import { DocumentManager } from './DocumentManager'; import { DocData } from '../../fields/DocSymbols'; // import { DateRange, Range, RangeKeyDict } from 'react-date-range'; import { Button } from 'browndash-components'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import {DateRangePicker} from '@adobe/react-spectrum'; import { IconLookup, faPlus } from '@fortawesome/free-solid-svg-icons'; import { Docs } from '../documents/Documents'; // import 'react-date-range/dist/styles.css'; // import 'react-date-range/dist/theme/default.css'; type CreationType = 'new-calendar' | 'existing-calendar' | 'manage-calendars'; interface CalendarSelectOptions { label: string, value: string } const formatDateToString = (date: Date) => { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } // TODO: If doc is already part of a calendar, display that // TODO: For a doc already in a calendar: give option to edit date range, delete from calendar @observer export class CalendarManager extends React.Component<{}> { public static Instance: CalendarManager; @observable private isOpen = false; @observable private targetDoc: Doc | undefined; // the target document @observable private targetDocView: DocumentView | undefined; // the DocumentView of the target doc @observable private dialogueBoxOpacity = 1; // for the modal @observable private overlayOpacity = 0.4; // for the modal @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used @observable private creationType: CreationType = 'new-calendar'; @observable private existingCalendars: Doc[] = DocListCast(Doc.MyCalendars.data); @computed get selectOptions() { return this.existingCalendars.map(calendar => ({ label: StrCast(calendar.title), value: StrCast(calendar.title) })); } @observable selectedExistingCalendarOption: CalendarSelectOptions | null = null; @observable calendarName: string = ""; @observable calendarDescription: string = ""; @observable errorMessage: string = ""; @action setInterationType = (type: CreationType) => { this.errorMessage = ""; this.calendarName = ""; this.creationType = type; } public open = (target?: DocumentView, target_doc?: Doc) => { console.log('hi'); runInAction(() => { this.targetDoc = target_doc || target?.props.Document; this.targetDocView = target; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = this.targetDoc !== undefined; }) }; public close = action(() => { this.isOpen = false; TaskCompletionBox.taskCompleted = false; setTimeout( action(() => { DictationOverlay.Instance.hasActiveModal = false; this.targetDoc = undefined; }), 500 ); this.layoutDocAcls = false; }); constructor(props: {}) { super(props); CalendarManager.Instance = this; } componentDidMount(): void { } @action handleSelectChange = (option: any) => { let selectOpt = option as CalendarSelectOptions; this.selectedExistingCalendarOption = selectOpt; this.calendarName = selectOpt.value; // or label } @action handleTextFieldChange = (event: React.ChangeEvent) => { this.calendarName = event.target.value; } // TODO: Make undoable private addToCalendar = () => { let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.rootDoc); const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; // doc to add to calendar if (targetDoc) { let calendar: Doc; if (this.creationType === 'new-calendar'){ if (!this.existingCalendars.find(doc => StrCast(doc.title) === this.calendarName)){ calendar = Docs.Create.CalendarDocument({ title: this.calendarName, description: this.calendarDescription }, []); } else { this.errorMessage = "Calendar with this name already exists" return; } } else { // find existing calendar based on selected name (should technically always find one) const existingCalendar = this.existingCalendars.find(calendar => StrCast(calendar.title) === this.calendarName); if (existingCalendar) calendar = existingCalendar; else { this.errorMessage = "Must select an existing calendar"; return; } } // Get start and end date strings const startDateStr = formatDateToString(this.selectedDateRange.start); const endDateStr = formatDateToString(this.selectedDateRange.end); const subDocEmbedding = Doc.MakeEmbedding(targetDoc); // embedding subDocEmbedding.embedContainer = calendar; // set embed container subDocEmbedding.date_range = `${startDateStr}-${endDateStr}`; // set subDoc date range Doc.AddDocToList(calendar, 'data', subDocEmbedding); // add embedded subDoc to calendar if (this.creationType === 'new-calendar'){ Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add to new calendar to dashboard calendars } } } private focusOn = (contents: string) => { const title = this.targetDoc ? StrCast(this.targetDoc.title) : ''; const docs = SelectionManager.Views().length > 1 ? SelectionManager.Views().map(docView => docView.props.Document) : [this.targetDoc]; return ( { if (this.targetDoc && this.targetDocView && docs.length === 1) { DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true }); } }} onPointerEnter={action(() => { if (docs.length) { docs.forEach(doc => doc && Doc.BrushDoc(doc)); this.dialogueBoxOpacity = 0.1; this.overlayOpacity = 0.1; } })} onPointerLeave={action(() => { if (docs.length) { docs.forEach(doc => doc && Doc.UnBrushDoc(doc)); this.dialogueBoxOpacity = 1; this.overlayOpacity = 0.4; } })}> {contents} ); }; @observable selectedDateRange: any = [{ start: new Date(), end: new Date(), }] @action setSelectedDateRange = (range: any) => { this.selectedDateRange = range; } @computed get createButtonActive() { if (this.calendarName.length === 0 || this.errorMessage.length > 0) return false // disabled if no calendar name let startDate: Date | undefined; let endDate: Date | undefined; try { startDate = this.selectedDateRange[0].startDate; endDate = this.selectedDateRange[0].endDate; } catch (e: any){ return false; // disabled } if (!startDate || !endDate) return false; // disabled if any is undefined return true; } @computed get calendarInterface(){ let docs = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.rootDoc); const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; const currentDate = new Date(); return (

{this.focusOn(docs.length < 2 ? StrCast(targetDoc?.title, 'this document') : '-multiple-')}

this.setInterationType('new-calendar')} > Add to New Calendar
this.setInterationType('existing-calendar')} > Add to Existing calendar
{this.creationType === 'new-calendar' ? : }
this.setSelectedDateRange(v))} label="Date range" />
) } render() { return ( ) } }