import * as React from 'react'; import './CalendarManager.scss'; import { observer } from 'mobx-react'; import { action, computed, observable, runInAction, makeObservable } 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 '@mui/material'; import Select from 'react-select'; import { SettingsManager } from './SettingsManager'; import { DateCast, 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 { Provider, defaultTheme } from '@adobe/react-spectrum'; import { DateValue } from '@internationalized/date'; import { DateRangePicker, SpectrumDateRangePickerProps } from '@adobe/react-spectrum'; import { IconLookup, faPlus } from '@fortawesome/free-solid-svg-icons'; import { Docs } from '../documents/Documents'; import { ObservableReactComponent } from '../views/ObservableReactComponent'; // 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 formatCalendarDateToString = (calendarDate: any) => { console.log('Formatting the following date: ', calendarDate); const date = new Date(calendarDate.year, calendarDate.month - 1, calendarDate.day); console.log(typeof 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 ObservableReactComponent<{}> { 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?.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; makeObservable(this); } componentDidMount(): void {} @action handleSelectChange = (option: any) => { if (option) { let selectOpt = option as CalendarSelectOptions; this.selectedExistingCalendarOption = selectOpt; this.calendarName = selectOpt.value; // or label } }; @action handleCalendarTitleChange = (event: React.ChangeEvent) => { console.log('Existing calendars: ', this.existingCalendars); this.calendarName = event.target.value; }; @action handleCalendarDescriptionChange = (event: React.ChangeEvent) => { this.calendarDescription = event.target.value; }; // TODO: Make undoable private addToCalendar = () => { let docs = SelectionManager.Views.length < 2 ? [this.targetDoc] : SelectionManager.Views.map(docView => docView.Document); const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; // doc to add to calendar console.log(targetDoc); if (targetDoc) { let calendar: Doc; if (this.creationType === 'new-calendar') { if (!this.existingCalendars.find(doc => StrCast(doc.title) === this.calendarName)) { console.log('creating...'); calendar = Docs.Create.CalendarDocument( { title: this.calendarName, description: this.calendarDescription, }, [] ); console.log('successful calendar creation'); } 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 = formatCalendarDateToString(this.selectedDateRange.start); const endDateStr = formatCalendarDateToString(this.selectedDateRange.end); console.log('start date: ', startDateStr); console.log('end date: ', endDateStr); const subDocEmbedding = Doc.MakeEmbedding(targetDoc); // embedding console.log('subdoc embedding', subDocEmbedding); 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 console.log('my calendars: ', Doc.MyCalendars); 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.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) => { console.log('Range: ', range); 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.start; endDate = this.selectedDateRange.end; console.log(startDate); console.log(endDate); } catch (e: any) { console.log(e); 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.Document); 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' ? ( ) : ( )}
Select a date range:
this.setSelectedDateRange(v)} />
{this.createButtonActive && (
)}
); } render() { return ; } }