aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/CalendarManager.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util/CalendarManager.tsx')
-rw-r--r--src/client/util/CalendarManager.tsx153
1 files changed, 130 insertions, 23 deletions
diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx
index 39ba41652..e471db7c6 100644
--- a/src/client/util/CalendarManager.tsx
+++ b/src/client/util/CalendarManager.tsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import './CalendarManager.scss';
import { observer } from "mobx-react";
import { action, computed, observable, runInAction } from 'mobx';
-import { Doc } from '../../fields/Doc';
+import { Doc, DocListCast } from '../../fields/Doc';
import { DocumentView } from '../views/nodes/DocumentView';
import { DictationOverlay } from '../views/DictationOverlay';
import { TaskCompletionBox } from '../views/nodes/TaskCompletedBox';
@@ -10,19 +10,38 @@ import { MainViewModal } from '../views/MainViewModal';
import { TextField } from '@material-ui/core';
import Select from 'react-select';
import { SettingsManager } from './SettingsManager';
-import { StrCast } from '../../fields/Types';
+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 { 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 'react-date-range/dist/styles.css';
-import 'react-date-range/dist/theme/default.css';
+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;
@@ -36,11 +55,28 @@ export class CalendarManager extends React.Component<{}> {
@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;
}
@@ -76,6 +112,60 @@ export class CalendarManager extends React.Component<{}> {
}
+ @action
+ handleSelectChange = (option: any) => {
+ let selectOpt = option as CalendarSelectOptions;
+ this.selectedExistingCalendarOption = selectOpt;
+ this.calendarName = selectOpt.value; // or label
+ }
+
+ @action
+ handleTextFieldChange = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
+ 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
+
+ Doc.AddDocToList(Doc.MyCalendars, 'data', calendar); // add 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];
@@ -108,20 +198,19 @@ export class CalendarManager extends React.Component<{}> {
};
@observable
- selectedDateRange: Range[] = [{
- startDate: new Date(),
- endDate: undefined,
- key: 'selection'
+ selectedDateRange: any = [{
+ start: new Date(),
+ end: new Date(),
}]
@action
- setSelectedDateRange = (range: Range[]) => {
+ setSelectedDateRange = (range: any) => {
this.selectedDateRange = range;
}
@computed
get createButtonActive() {
- if (this.calendarName.length === 0) return false // disabled if no calendar name
+ 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 {
@@ -170,6 +259,7 @@ export class CalendarManager extends React.Component<{}> {
{this.creationType === 'new-calendar' ?
<TextField
fullWidth
+ onChange={this.handleTextFieldChange}
placeholder='Enter calendar name...'
variant='filled'
style={{
@@ -178,38 +268,55 @@ export class CalendarManager extends React.Component<{}> {
borderRadius: '5px'
}}
-
/>
:
<Select
className='existing-calendar-search'
placeholder='Search for existing calendar...'
- isMulti
+ isClearable
isSearchable
+ options={this.selectOptions}
+ value={this.selectedExistingCalendarOption}
+ onChange={this.handleSelectChange}
+ styles={{
+ control: () => ({
+ display: 'inline-flex',
+ width: '100%',
+ }),
+ indicatorSeparator: () => ({
+ display: 'inline-flex',
+ visibility: 'hidden',
+ }),
+ indicatorsContainer: () => ({
+ display: 'inline-flex',
+ textDecorationColor: 'black',
+ }),
+ valueContainer: () => ({
+ display: 'inline-flex',
+ fontStyle: StrCast(Doc.UserDoc().userColor),
+ color: StrCast(Doc.UserDoc().userColor),
+ width: '100%',
+ }),
+ }}
>
-
</Select>
}
</div>
<div className='date-range-picker-container'>
- <DateRange
- className='react-date-range'
- editableDateInputs={true}
- // ranges={[selectionRange]}
- onChange={item => this.setSelectedDateRange([item.selection])}
- ranges={this.selectedDateRange}
- // onChange={this.handleSelect}
- />
+ <DateRangePicker
+ value={this.selectedDateRange}
+ onChange={(v => this.setSelectedDateRange(v))}
+ label="Date range" />
</div>
<div className='create-button-container'>
<Button
active={this.createButtonActive}
+ onClick={() => {}}
text="Add to Calendar"
iconPlacement='right'
icon={<FontAwesomeIcon icon={faPlus as IconLookup}/>}
/>
</div>
-
</div>
)
}