import { DateRangePicker, Provider, defaultTheme } from '@adobe/react-spectrum'; import { IconLookup, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { TextField } from '@mui/material'; import { Button } from '@dash/components'; import { action, computed, makeObservable, observable, runInAction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import Select from 'react-select'; import { Doc, DocListCast } from '../../fields/Doc'; import { DocData } from '../../fields/DocSymbols'; import { StrCast } from '../../fields/Types'; import { Docs } from '../documents/Documents'; import { MainViewModal } from '../views/MainViewModal'; import { ObservableReactComponent } from '../views/ObservableReactComponent'; import { DocumentView } from '../views/nodes/DocumentView'; import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox'; import './CalendarManager.scss'; import { SnappingManager } from './SnappingManager'; import { CalendarDate, DateValue } from '@internationalized/date'; // 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: DateValue) => { 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 { // eslint-disable-next-line no-use-before-define public static Instance: CalendarManager; @observable private isOpen = false; @observable private targetDoc: Doc | undefined = undefined; // the target document @observable private targetDocView: DocumentView | undefined = undefined; // the DocumentView of the target doc @observable private dialogueBoxOpacity = 1; // 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, targetDoc?: Doc) => { runInAction(() => { this.targetDoc = targetDoc || target?.Document; this.targetDocView = target; this.isOpen = this.targetDoc !== undefined; }); }; public close = action(() => { this.isOpen = false; TaskCompletionBox.taskCompleted = false; setTimeout( action(() => { this.targetDoc = undefined; }), 500 ); this.layoutDocAcls = false; }); constructor(props: object) { super(props); CalendarManager.Instance = this; makeObservable(this); } componentDidMount(): void {} @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 = () => { const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().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(findCal => StrCast(findCal.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 = DocumentView.Selected().length > 1 ? DocumentView.Selected().map(docView => docView.Document) : [this.targetDoc]; return ( { if (this.targetDoc && this.targetDocView && docs.length === 1) { DocumentView.showDocument(this.targetDoc, { willZoomCentered: true }); } }} onPointerEnter={action(() => { if (docs.length) { docs.forEach(doc => doc && Doc.BrushDoc(doc)); this.dialogueBoxOpacity = 0.1; } })} onPointerLeave={action(() => { if (docs.length) { docs.forEach(doc => doc && Doc.UnBrushDoc(doc)); this.dialogueBoxOpacity = 1; } })}> {contents} ); }; @observable selectedDateRange: { start: DateValue; end: DateValue } = { start: new CalendarDate(2024, 1, 1), end: new CalendarDate(2024, 1, 1), }; @action setSelectedDateRange = (range: { start: DateValue; end: DateValue }) => { 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: DateValue | undefined; let endDate: DateValue | undefined; try { startDate = this.selectedDateRange.start; endDate = this.selectedDateRange.end; console.log(startDate); console.log(endDate); } catch (e) { console.log(e); return false; // disabled } if (!startDate || !endDate) return false; // disabled if any is undefined return true; } @computed get calendarInterface() { const docs = DocumentView.Selected().length < 2 ? [this.targetDoc] : DocumentView.Selected().map(docView => docView.Document); const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DocData]; 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' ? ( ) : (