diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/client/documents/Documents.ts | 9 | ||||
| -rw-r--r-- | src/client/util/CurrentUserUtils.ts | 3 | ||||
| -rw-r--r-- | src/client/util/DragManager.ts | 12 | ||||
| -rw-r--r-- | src/client/views/DocumentDecorations.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/StyleProvider.tsx | 8 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionNoteTakingView.tsx | 91 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionNoteTakingViewColumn.tsx | 358 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionNoteTakingViewDivider.tsx | 112 | ||||
| -rw-r--r-- | src/client/views/collections/CollectionStackingView.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 30 | ||||
| -rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 6 | 
11 files changed, 332 insertions, 303 deletions
| diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 32d7152fd..9d00664ad 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1036,7 +1036,14 @@ export namespace Docs {          }          export function NoteTakingDocument(documents: Array<Doc>, options: DocumentOptions, id?: string, protoId?: string) { -            return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.NoteTaking }, id, undefined, protoId); +            return InstanceFromProto( +                Prototypes.get(DocumentType.COL), +                new List(documents), +                { columnHeaders: new List<SchemaHeaderField>([new SchemaHeaderField('Untitled')]), ...options, _viewType: CollectionViewType.NoteTaking }, +                id, +                undefined, +                protoId +            );          }          export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) { diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 28dc44c25..7856c913b 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -135,7 +135,6 @@ export class CurrentUserUtils {          return DocUtils.AssignOpts(tempClicks, reqdOpts, reqdClickList) ?? (doc[field] = Docs.Create.TreeDocument(reqdClickList, reqdOpts));      } -      /// Initializes templates that can be applied to notes      static setupNoteTemplates(doc: Doc, field="template-notes") {          const tempNotes = DocCast(doc[field]); @@ -255,6 +254,7 @@ export class CurrentUserUtils {                            creator:(opts:DocumentOptions)=> any // how to create the empty thing if it doesn't exist                }[] = [              {key: "Note",       creator: opts => Docs.Create.TextDocument("", opts),        opts: { _width: 200, _autoHeight: true }}, +            {key: "Noteboard",  creator: opts => Docs.Create.NoteTakingDocument([], opts),  opts: { _width: 250, _height: 200 }},              {key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts),    opts: { _width: 150, _height: 100 }},              {key: "Equation",   creator: opts => Docs.Create.EquationDocument(opts),        opts: { _width: 300, _height: 35, _fitWidth:false, _backgroundGridShow: true, }},              {key: "Webpage",    creator: opts => Docs.Create.WebDocument("",opts),          opts: { _width: 400, _height: 512, _nativeWidth: 850, useCors: true, }}, @@ -280,6 +280,7 @@ export class CurrentUserUtils {          return [              { toolTip: "Tap or drag to create a note",            title: "Note", icon: "sticky-note",   dragFactory: doc.emptyNote as Doc, }, +            { toolTip: "Tap or drag to create a note board",      title: "Notes", icon: "folder",       dragFactory: doc.emptyNoteboard as Doc, },              { toolTip: "Tap or drag to create a collection",      title: "Col", icon: "folder",         dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab),  scripts: { onClick: 'openOnRight(copyDragFactory(this.clickFactory))', onDragStart: '{ return copyDragFactory(this.dragFactory);}'}, },              { toolTip: "Tap or drag to create an equation",       title: "Math", icon: "calculator",    dragFactory: doc.emptyEquation as Doc, },              { toolTip: "Tap or drag to create a webpage",         title: "Web", icon: "globe-asia",     dragFactory: doc.emptyWebpage as Doc, }, diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 3a1bb1673..f4987cf34 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,4 +1,4 @@ -import { action } from 'mobx'; +import { action, observable, runInAction } from 'mobx';  import { DateField } from '../../fields/DateField';  import { Doc, Field, Opt } from '../../fields/Doc';  import { List } from '../../fields/List'; @@ -320,7 +320,7 @@ export namespace DragManager {              y: snapVal([yFromTop, yFromBottom], e.pageY, SnappingManager.horizSnapLines()),          };      } -    export let docsBeingDragged: Doc[] = []; +    export let docsBeingDragged: Doc[] = observable([] as Doc[]);      export let CanEmbed = false;      export let DocDragData: DocumentDragData | undefined;      export function StartDrag(eles: HTMLElement[], dragData: { [id: string]: any }, downX: number, downY: number, options?: DragOptions, finishDrag?: (dropData: DragCompleteEvent) => void) { @@ -349,13 +349,13 @@ export namespace DragManager {              xs: number[] = [],              ys: number[] = []; -        docsBeingDragged = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];          const elesCont = {              left: Number.MAX_SAFE_INTEGER,              right: Number.MIN_SAFE_INTEGER,              top: Number.MAX_SAFE_INTEGER,              bottom: Number.MIN_SAFE_INTEGER,          }; +        const docsToDrag = dragData instanceof DocumentDragData ? dragData.draggedDocuments : dragData instanceof AnchorAnnoDragData ? [dragData.dragDocument] : [];          const dragElements = eles.map(ele => {              if (!ele.parentNode) dragDiv.appendChild(ele);              const dragElement = ele.parentNode === dragDiv ? ele : (ele.cloneNode(true) as HTMLElement); @@ -405,7 +405,7 @@ export namespace DragManager {              });              dragLabel.style.transform = `translate(${rect.left + (options?.offsetX || 0)}px, ${rect.top + (options?.offsetY || 0) - 20}px)`; -            if (docsBeingDragged.length) { +            if (docsToDrag.length) {                  const pdfBox = dragElement.getElementsByTagName('canvas');                  const pdfBoxSrc = ele.getElementsByTagName('canvas');                  Array.from(pdfBox) @@ -429,6 +429,8 @@ export namespace DragManager {              return dragElement;          }); +        runInAction(() => docsBeingDragged.push(...docsToDrag)); +          const hideDragShowOriginalElements = (hide: boolean) => {              dragLabel.style.display = hide ? '' : 'none';              !hide && dragElements.map(dragElement => dragElement.parentNode === dragDiv && dragDiv.removeChild(dragElement)); @@ -456,7 +458,7 @@ export namespace DragManager {              SnappingManager.SetIsDragging(false);              SnappingManager.clearSnapLines();              batch.end(); -            docsBeingDragged = []; +            docsBeingDragged.length = 0;          });          var startWindowDragTimer: any;          const moveHandler = (e: PointerEvent) => { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index c53e61699..0db9eab69 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -351,7 +351,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P      @action      onPointerDown = (e: React.PointerEvent): void => { -        DragManager.docsBeingDragged = SelectionManager.Views().map(dv => dv.rootDoc); +        DragManager.docsBeingDragged.push(...SelectionManager.Views().map(dv => dv.rootDoc));          this._inkDragDocs = DragManager.docsBeingDragged              .filter(doc => doc.type === DocumentType.INK)              .map(doc => { diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 692f7b98e..a83163eb0 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -110,8 +110,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps              return undefined;          case StyleProp.WidgetColor:              return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? 'lightgrey' : 'dimgrey'; -            // return doc = dragManager.dragDocument ? props.dragEffects.opacity??CastofOpacityonline94 : Cast()) -            // same idea for background Color +        // return doc = dragManager.dragDocument ? props.dragEffects.opacity??CastofOpacityonline94 : Cast()) +        // same idea for background Color          case StyleProp.Opacity:              return Cast(doc?._opacity, 'number', Cast(doc?.opacity, 'number', null));          case StyleProp.HideLinkButton: @@ -156,7 +156,9 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps          case StyleProp.JitterRotation:              return comicStyle() ? random(-1, 1, NumCast(doc?.x), NumCast(doc?.y)) * ((props?.PanelWidth() || 0) > (props?.PanelHeight() || 0) ? 5 : 10) : 0;          case StyleProp.HeaderMargin: -            return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) || (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) || doc?.type === DocumentType.LABEL) && +            return ([CollectionViewType.Stacking, CollectionViewType.NoteTaking, CollectionViewType.Masonry, CollectionViewType.Tree].includes(doc?._viewType as any) || +                (doc?.type === DocumentType.RTF && !showTitle()?.includes('noMargin')) || +                doc?.type === DocumentType.LABEL) &&                  showTitle() &&                  !StrCast(doc?.showTitle).includes(':hover')                  ? 15 diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx index f442559fb..1854a4213 100644 --- a/src/client/views/collections/CollectionNoteTakingView.tsx +++ b/src/client/views/collections/CollectionNoteTakingView.tsx @@ -1,6 +1,6 @@  import React = require('react');  import { CursorProperty } from 'csstype'; -import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';  import { observer } from 'mobx-react';  import { DataSym, Doc, HeightSym, Opt, WidthSym } from '../../../fields/Doc';  import { Id } from '../../../fields/FieldSymbols'; @@ -21,10 +21,12 @@ import { ContextMenuProps } from '../ContextMenuItem';  import { LightboxView } from '../LightboxView';  import { CollectionFreeFormDocumentView } from '../nodes/CollectionFreeFormDocumentView';  import { DocFocusOptions, DocumentView, DocumentViewProps, ViewAdjustment } from '../nodes/DocumentView'; +import { FieldViewProps } from '../nodes/FieldView'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';  import { StyleProp } from '../StyleProvider';  import './CollectionNoteTakingView.scss';  import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn'; -import CollectionNoteTakingViewDivider from './CollectionNoteTakingViewDivider'; +import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';  import { CollectionSubView } from './CollectionSubView';  const _global = (window /* browser */ || global) /* node */ as any; @@ -40,7 +42,6 @@ export type collectionNoteTakingViewProps = {  @observer  export class CollectionNoteTakingView extends CollectionSubView<Partial<collectionNoteTakingViewProps>>() { -    _pivotFieldDisposer?: IReactionDisposer;      _autoHeightDisposer?: IReactionDisposer;      _masonryGridRef: HTMLDivElement | null = null;      _draggerRef = React.createRef<HTMLDivElement>(); @@ -54,10 +55,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti          return this.props.chromeHidden || BoolCast(this.layoutDoc.chromeHidden);      }      @computed get columnHeaders() { -        return Cast(this.layoutDoc._columnHeaders, listSpec(SchemaHeaderField), null); +        return Cast(this.dataDoc.columnHeaders, listSpec(SchemaHeaderField), null);      } -    @computed get pivotField() { -        return 'Col'; +    @computed get notetakingCategoryField() { +        return 'noteTakingCategory';      }      @computed get filteredChildren() {          return this.childLayoutPairs.filter(pair => pair.layout instanceof Doc && !pair.layout.hidden).map(pair => pair.layout); @@ -90,7 +91,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti      constructor(props: any) {          super(props);          if (this.columnHeaders === undefined) { -            this.layoutDoc._columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]); +            this.dataDoc.columnHeaders = new List<SchemaHeaderField>([new SchemaHeaderField('New Column')]);              this.columnStartXCoords = [0];              // add all of the docs that have not been added to a column to this new column          } else { @@ -126,18 +127,16 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti          // filter out the currently dragged docs from the child docs, since we will insert them later          if (rowCol.length && DragManager.docsBeingDragged.length) {              const docIdsToRemove = new Set(); -            DragManager.docsBeingDragged.forEach(d => { -                docIdsToRemove.add(d[Id]); -            }); +            DragManager.docsBeingDragged.forEach(d => docIdsToRemove.add(d[Id]));              docs = docs.filter(d => !docIdsToRemove.has(d[Id]));          }          // this will sort the docs into the correct columns (minus the ones you're currently dragging)          docs.map(d => { -            if (!d[this.pivotField]) { -                d[this.pivotField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column`; +            if (!d[this.notetakingCategoryField]) { +                d[this.notetakingCategoryField] = columnHeaders.length > 0 ? columnHeaders[0].heading : `New Column`;              } -            const sectionValue = d[this.pivotField] as object; +            const sectionValue = d[this.notetakingCategoryField] as object;              // look for if header exists already              const existingHeader = columnHeaders.find(sh => sh.heading === sectionValue.toString()); @@ -156,14 +155,15 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti          return sections;      } +    removeDocDragHighlight = () => { +        setTimeout( +            action(() => (this.docsDraggedRowCol.length = 0)), +            100 +        ); +    };      componentDidMount() {          super.componentDidMount?.(); -        // reset section headers when a new filter is inputted -        this._pivotFieldDisposer = reaction( -            () => this.pivotField, -            () => (this.layoutDoc._columnHeaders = new List()) -        ); - +        document.addEventListener('pointerup', this.removeDocDragHighlight, true);          this._autoHeightDisposer = reaction(              () => this.layoutDoc._autoHeight,              autoHeight => autoHeight && this.props.setHeight?.(Math.min(NumCast(this.layoutDoc._maxHeight, Number.MAX_SAFE_INTEGER), this.headerMargin + Math.max(...this.refList.map(r => Number(getComputedStyle(r).height.replace('px', '')))))) @@ -171,8 +171,8 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti      }      componentWillUnmount() { +        document.removeEventListener('pointerup', this.removeDocDragHighlight, true);          super.componentWillUnmount(); -        this._pivotFieldDisposer?.();          this._autoHeightDisposer?.();      } @@ -227,6 +227,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti      };      styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => { +        if (property === StyleProp.BoxShadow && doc && DragManager.docsBeingDragged.includes(doc)) { +            return `#9c9396  ${StrCast(doc?.boxShadow, '10px 10px 0.9vw')}`; +        }          if (property === StyleProp.Opacity && doc) {              if (this.props.childOpacity) {                  return this.props.childOpacity(); @@ -258,9 +261,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti                  docViewPath={this.props.docViewPath}                  fitWidth={this.props.childFitWidth}                  isContentActive={emptyFunction} -                originalBackgroundColor={StrCast(doc.backgroundColor)} +                onKey={this.onKeyDown}                  //TODO: change this from a prop to a parameter passed into a function -                isNoteTakingView={true} +                dontHideOnDrag={true}                  isDocumentActive={this.isContentActive}                  LayoutTemplate={this.props.childLayoutTemplate}                  LayoutTemplateString={this.props.childLayoutString} @@ -307,7 +310,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti      // how to get the width of a document. Currently returns the width of the column (minus margins)      // if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)      getDocWidth(d: Doc) { -        const heading = d[this.pivotField] as object; +        const heading = d[this.notetakingCategoryField] as object;          const castedSectionValue = heading.toString();          const existingHeader = this.columnHeaders.find(sh => sh.heading === castedSectionValue);          const colStartXCoords = this.columnStartXCoords; @@ -364,20 +367,14 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti          if (DragManager.docsBeingDragged.length && this.childDocList) {              // get the current docs for the column based on the mouse's x coordinate              // will use again later, which is why we're saving as local -            const xCoord = e.clientX - 2 * this.gridGap; +            const xCoord = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[0] - 2 * this.gridGap;              const colDocs = this.getDocsFromXCoord(xCoord);              // get the index for where you need to insert the doc you are currently dragging -            const clientY = e.clientY; +            const clientY = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY)[1];              let dropInd = -1; -            // unsure whether we still want this dropAfter field -            // let dropAfter = 0; -            // manually set to 140, because not sure how to get exact value -            let pos0 = 140; +            let pos0 = (this.refList.lastElement() as HTMLDivElement).children[0].getBoundingClientRect().height + this.yMargin * 2;              colDocs.forEach((doc, i) => { -                const noteTakingDocTransform = () => this.getDocTransform(doc); -                let pos1 = noteTakingDocTransform() -                    .inverse() -                    .transformPoint(0, this.getDocHeight(doc) + 2 * this.gridGap)[1]; +                let pos1 = this.getDocHeight(doc) + 2 * this.gridGap;                  pos1 += pos0;                  // updating drop position based on y coordinates                  const yCoordInBetween = clientY > pos0 && (clientY < pos1 || i == colDocs.length - 1); @@ -393,10 +390,10 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti              // we alter the pivot fields of the docs in case they are moved to a new column.              const colIndex = this.getColumnFromXCoord(xCoord);              const colHeader = StrCast(this.columnHeaders[colIndex].heading); -            DragManager.docsBeingDragged.forEach(d => (d[this.pivotField] = colHeader)); +            DragManager.docsBeingDragged.forEach(d => (d[this.notetakingCategoryField] = colHeader));              // used to notify sections to re-render -            // console.log([dropInd, this.getColumnFromXCoord(xCoord)]) -            this.docsDraggedRowCol = [dropInd, this.getColumnFromXCoord(xCoord)]; +            this.docsDraggedRowCol.length = 0; +            this.docsDraggedRowCol.push(dropInd, this.getColumnFromXCoord(xCoord));          }      }; @@ -425,7 +422,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti          if (docs) {              docs.map(d => {                  if (d instanceof Promise) return; -                const sectionValue = d[this.pivotField] as object; +                const sectionValue = d[this.notetakingCategoryField] as object;                  if (sectionValue.toString() == colHeader) {                      docsMatchingHeader.push(d);                  } @@ -436,11 +433,22 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti      @undoBatch      @action +    onKeyDown = (e: React.KeyboardEvent, fieldProps: FieldViewProps) => { +        const docView = fieldProps.DocumentView?.(); +        if (docView && (e.ctrlKey || docView.rootDoc._singleLine) && ['Enter'].includes(e.key)) { +            e.stopPropagation?.(); +            const newDoc = Doc.MakeCopy(docView.rootDoc, true); +            Doc.GetProto(newDoc).text = undefined; +            FormattedTextBox.SelectOnLoad = newDoc[Id]; +            return this.addDocument?.(newDoc); +        } +    }; + +    @undoBatch +    @action      onInternalDrop = (e: Event, de: DragManager.DropEvent) => {          if (de.complete.docDragData) {              if (super.onInternalDrop(e, de)) { -                DragManager.docsBeingDragged = []; -                // this.docsDraggedRowCol = []                  // filter out the currently dragged docs from the child docs, since we will insert them later                  const rowCol = this.docsDraggedRowCol;                  const droppedDocs = this.childDocs.slice().filter((d: Doc, ind: number) => ind >= this.childDocs.length); // if the drop operation adds something to the end of the list, then use that as the new document (may be different than what was dropped e.g., in the case of a button which is dropped but which creates say, a note). @@ -456,10 +464,9 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti                      if (rowCol[0] <= 0) {                          docs.splice(0, 0, ...newDocs);                      } else { -                        const colDocs = this.getDocsFromXCoord(de.x); +                        const colDocs = this.getDocsFromXCoord(this.props.ScreenToLocalTransform().transformPoint(de.x, de.y)[0]);                          const previousDoc = colDocs[rowCol[0] - 1];                          const previousDocIndex = docs.indexOf(previousDoc); -                        console.log(`docs: ${previousDocIndex}`);                          docs.splice(previousDocIndex + 1, 0, ...newDocs);                      }                  } @@ -561,7 +568,7 @@ export class CollectionNoteTakingView extends CollectionSubView<Partial<collecti                  renderChildren={this.children}                  numGroupColumns={this.numGroupColumns}                  gridGap={this.gridGap} -                pivotField={this.pivotField} +                pivotField={this.notetakingCategoryField}                  columnStartXCoords={this.columnStartXCoords}                  maxColWidth={this.maxColWdith}                  PanelWidth={this.PanelWidth} diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx index bdcb9c399..55d032498 100644 --- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx @@ -1,27 +1,27 @@ -import React = require("react"); -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable } from "mobx"; -import { observer } from "mobx-react"; -import { Doc, DocListCast, Opt } from "../../../fields/Doc"; -import { Id } from "../../../fields/FieldSymbols"; -import { RichTextField } from "../../../fields/RichTextField"; -import { SchemaHeaderField } from "../../../fields/SchemaHeaderField"; -import { ScriptField } from "../../../fields/ScriptField"; -import { ImageField } from "../../../fields/URLField"; -import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, returnEmptyString, setupMoveUpEvents } from "../../../Utils"; -import { Docs, DocUtils } from "../../documents/Documents"; -import { DocumentType } from "../../documents/DocumentTypes"; -import { DragManager } from "../../util/DragManager"; -import { SnappingManager } from "../../util/SnappingManager"; -import { Transform } from "../../util/Transform"; -import { undoBatch } from "../../util/UndoManager"; -import { ContextMenu } from "../ContextMenu"; -import { ContextMenuProps } from "../ContextMenuItem"; -import { EditableView } from "../EditableView"; -import { FormattedTextBox } from "../nodes/formattedText/FormattedTextBox"; -import "./CollectionNoteTakingView.scss"; -const higflyout = require("@hig/flyout"); +import React = require('react'); +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; +import { Id } from '../../../fields/FieldSymbols'; +import { RichTextField } from '../../../fields/RichTextField'; +import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; +import { ScriptField } from '../../../fields/ScriptField'; +import { ImageField } from '../../../fields/URLField'; +import { TraceMobx } from '../../../fields/util'; +import { emptyFunction, returnEmptyString, setupMoveUpEvents } from '../../../Utils'; +import { Docs, DocUtils } from '../../documents/Documents'; +import { DocumentType } from '../../documents/DocumentTypes'; +import { DragManager } from '../../util/DragManager'; +import { SnappingManager } from '../../util/SnappingManager'; +import { Transform } from '../../util/Transform'; +import { undoBatch } from '../../util/UndoManager'; +import { ContextMenu } from '../ContextMenu'; +import { ContextMenuProps } from '../ContextMenuItem'; +import { EditableView } from '../EditableView'; +import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; +import './CollectionNoteTakingView.scss'; +const higflyout = require('@hig/flyout');  export const { anchorPoints } = higflyout;  export const Flyout = higflyout.default; @@ -39,7 +39,7 @@ interface CSVFieldColumnProps {      // columnWidth: number;      numGroupColumns: number;      gridGap: number; -    type: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | undefined; +    type: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | undefined;      headings: () => object[];      renderChildren: (docs: Doc[]) => JSX.Element[];      addDocument: (doc: Doc | Doc[]) => boolean; @@ -48,37 +48,37 @@ interface CSVFieldColumnProps {      observeHeight: (myref: any) => void;      unobserveHeight: (myref: any) => void;      editableViewProps: any; -    resizeColumns: (n: number) => void -    columnStartXCoords: number[] -    PanelWidth: number -    maxColWidth: number +    resizeColumns: (n: number) => void; +    columnStartXCoords: number[]; +    PanelWidth: number; +    maxColWidth: number;      // docsByColumnHeader: Map<string, Doc[]>      // setDocsForColHeader: (key: string, docs: Doc[]) => void  }  @observer  export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColumnProps> { -    @observable private _background = "inherit"; +    @observable private _background = 'inherit';      @computed get columnWidth() { -      // base cases -      if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length == 1) { -        return this.props.maxColWidth -      } -      const i = this.props.columnHeaders.indexOf(this.props.headingObject) -      if (i < 0) { -        return this.props.maxColWidth -      } -      const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i+1] -      // TODO make the math work here. 35 is half of 70, which is the current width of the divider -      return endColValue - this.props.columnStartXCoords[i] - 30 +        // base cases +        if (!this.props.columnHeaders || !this.props.headingObject || this.props.columnHeaders.length == 1) { +            return this.props.maxColWidth; +        } +        const i = this.props.columnHeaders.indexOf(this.props.headingObject); +        if (i < 0) { +            return this.props.maxColWidth; +        } +        const endColValue = i == this.props.numGroupColumns - 1 ? this.props.PanelWidth : this.props.columnStartXCoords[i + 1]; +        // TODO make the math work here. 35 is half of 70, which is the current width of the divider +        return endColValue - this.props.columnStartXCoords[i] - 30;      }      private dropDisposer?: DragManager.DragDropDisposer;      private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();      @observable _heading = this.props.headingObject ? this.props.headingObject.heading : this.props.heading; -    @observable _color = this.props.headingObject ? this.props.headingObject.color : "#f1efeb"; +    @observable _color = this.props.headingObject ? this.props.headingObject.color : '#f1efeb';      _ele: HTMLElement | null = null;      // This is likely similar to what we will be doing. Why do we need to make these refs? @@ -90,7 +90,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu              this.props.observeHeight(ele);              this.dropDisposer = DragManager.MakeDropTarget(ele, this.columnDrop.bind(this));          } -    } +    };      componentWillUnmount() {          this.props.unobserveHeight(this._ele); @@ -105,10 +105,10 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu      getValue = (value: string): any => {          const parsed = parseInt(value);          if (!isNaN(parsed)) return parsed; -        if (value.toLowerCase().indexOf("true") > -1) return true; -        if (value.toLowerCase().indexOf("false") > -1) return false; +        if (value.toLowerCase().indexOf('true') > -1) return true; +        if (value.toLowerCase().indexOf('false') > -1) return false;          return value; -    } +    };      @action      headingChanged = (value: string, shiftDown?: boolean) => { @@ -117,7 +117,7 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu              if (this.props.columnHeaders?.map(i => i.heading).indexOf(castedValue.toString()) !== -1) {                  return false;              } -            this.props.docList.forEach(d => d[this.props.pivotField] = castedValue); +            this.props.docList.forEach(d => (d[this.props.pivotField] = castedValue));              if (this.props.headingObject) {                  this.props.headingObject.setHeading(castedValue.toString());                  this._heading = this.props.headingObject.heading; @@ -125,11 +125,11 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu              return true;          }          return false; -    } +    }; -    @action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = "#b4b4b4"); -    @action pointerLeave = () => this._background = "inherit"; -    textCallback = (char: string) => this.addNewTextDoc("-typed text-", false, true); +    @action pointerEntered = () => SnappingManager.GetIsDragging() && (this._background = '#b4b4b4'); +    @action pointerLeave = () => (this._background = 'inherit'); +    textCallback = (char: string) => this.addNewTextDoc('-typed text-', false, true);      @action      addNewTextDoc = (value: string, shiftDown?: boolean, forceEmptyNote?: boolean) => { @@ -139,46 +139,46 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu          const colValue = this.getValue(this.props.heading);          newDoc[key] = colValue;          FormattedTextBox.SelectOnLoad = newDoc[Id]; -        FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? "" : " "; +        FormattedTextBox.SelectOnLoadChar = forceEmptyNote ? '' : ' ';          return this.props.addDocument?.(newDoc) || false; -    } +    };      @action      deleteColumn = () => {          if (!this.props.columnHeaders) { -          return +            return;          }          if (this.props.headingObject) { -          const index = this.props.columnHeaders.indexOf(this.props.headingObject); -          const newIndex = index == 0 ? 1 : index - 1 -          const newHeader = this.props.columnHeaders[newIndex]; -          this.props.docList.forEach(d => d[this.props.pivotField] = newHeader.heading.toString()) -          this.props.columnHeaders.splice(index, 1); -          this.props.resizeColumns(this.props.columnHeaders.length) +            const index = this.props.columnHeaders.indexOf(this.props.headingObject); +            const newIndex = index == 0 ? 1 : index - 1; +            const newHeader = this.props.columnHeaders[newIndex]; +            this.props.docList.forEach(d => (d[this.props.pivotField] = newHeader.heading.toString())); +            this.props.columnHeaders.splice(index, 1); +            this.props.resizeColumns(this.props.columnHeaders.length);          } -    } +    };      headerDown = (e: React.PointerEvent<HTMLDivElement>) => setupMoveUpEvents(this, e, this.startDrag, emptyFunction, emptyFunction); -    //TODO: I think this is where I'm supposed to edit stuff  +    //TODO: I think this is where I'm supposed to edit stuff      startDrag = (e: PointerEvent, down: number[], delta: number[]) => { -        console.log('in startDrag') +        console.log('in startDrag');          // is MakeAlias a way to make a copy of a doc without rendering it?          const alias = Doc.MakeAlias(this.props.Document);          // alias._width = this.props.columnWidth / (this.props.columnHeaders?.length || 1);          alias._width = this.columnWidth;          alias._pivotField = undefined;          let value = this.getValue(this._heading); -        value = typeof value === "string" ? `"${value}"` : value; +        value = typeof value === 'string' ? `"${value}"` : value;          alias.viewSpecScript = ScriptField.MakeFunction(`doc.${this.props.pivotField} === ${value}`, { doc: Doc.name });          if (alias.viewSpecScript) { -            const options = {hideSource: false} +            const options = { hideSource: false };              DragManager.StartDocumentDrag([this._headerRef.current!], new DragManager.DocumentDragData([alias]), e.clientX, e.clientY, options); -            console.log('in startDrag') +            console.log('in startDrag');              return true;          }          return false; -    } +    };      menuCallback = (x: number, y: number) => {          ContextMenu.Instance.clearItems(); @@ -187,44 +187,62 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu          const dataDoc = this.props.DataDoc || this.props.Document;          const pivotValue = this.getValue(this.props.heading); -        DocUtils.addDocumentCreatorMenuItems((doc) => { -            const key = this.props.pivotField; -            doc[key] = this.getValue(this.props.heading); -            FormattedTextBox.SelectOnLoad = doc[Id]; -            return this.props.addDocument?.(doc); -        }, this.props.addDocument, x, y, true, this.props.pivotField, pivotValue); +        DocUtils.addDocumentCreatorMenuItems( +            doc => { +                const key = this.props.pivotField; +                doc[key] = this.getValue(this.props.heading); +                FormattedTextBox.SelectOnLoad = doc[Id]; +                return this.props.addDocument?.(doc); +            }, +            this.props.addDocument, +            x, +            y, +            true, +            this.props.pivotField, +            pivotValue +        ); -        Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof (dataDoc[fieldKey]) === "string").map(fieldKey => -            docItems.push({ -                description: ":" + fieldKey, event: () => { -                    const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.Document)); -                    if (created) { -                        if (this.props.Document.isTemplateDoc) { -                            Doc.MakeMetadataFieldTemplate(created, this.props.Document); +        Array.from(Object.keys(Doc.GetProto(dataDoc))) +            .filter(fieldKey => dataDoc[fieldKey] instanceof RichTextField || dataDoc[fieldKey] instanceof ImageField || typeof dataDoc[fieldKey] === 'string') +            .map(fieldKey => +                docItems.push({ +                    description: ':' + fieldKey, +                    event: () => { +                        const created = DocUtils.DocumentFromField(dataDoc, fieldKey, Doc.GetProto(this.props.Document)); +                        if (created) { +                            if (this.props.Document.isTemplateDoc) { +                                Doc.MakeMetadataFieldTemplate(created, this.props.Document); +                            } +                            return this.props.addDocument?.(created);                          } -                        return this.props.addDocument?.(created); -                    } -                }, icon: "compress-arrows-alt" -            })); -        Array.from(Object.keys(Doc.GetProto(dataDoc))).filter(fieldKey => DocListCast(dataDoc[fieldKey]).length).map(fieldKey => -            docItems.push({ -                description: ":" + fieldKey, event: () => { -                    const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey }); -                    if (created) { -                        const container = this.props.Document.resolvedDataDoc ? Doc.GetProto(this.props.Document) : this.props.Document; -                        if (container.isTemplateDoc) { -                            Doc.MakeMetadataFieldTemplate(created, container); -                            return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created); +                    }, +                    icon: 'compress-arrows-alt', +                }) +            ); +        Array.from(Object.keys(Doc.GetProto(dataDoc))) +            .filter(fieldKey => DocListCast(dataDoc[fieldKey]).length) +            .map(fieldKey => +                docItems.push({ +                    description: ':' + fieldKey, +                    event: () => { +                        const created = Docs.Create.CarouselDocument([], { _width: 400, _height: 200, title: fieldKey }); +                        if (created) { +                            const container = this.props.Document.resolvedDataDoc ? Doc.GetProto(this.props.Document) : this.props.Document; +                            if (container.isTemplateDoc) { +                                Doc.MakeMetadataFieldTemplate(created, container); +                                return Doc.AddDocToList(container, Doc.LayoutFieldKey(container), created); +                            } +                            return this.props.addDocument?.(created) || false;                          } -                        return this.props.addDocument?.(created) || false; -                    } -                }, icon: "compress-arrows-alt" -            })); -        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Doc Fields ...", subitems: docItems, icon: "eye" }); -        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: "Containers ...", subitems: layoutItems, icon: "eye" }); -        ContextMenu.Instance.setDefaultItem("::", (name: string): void => { -            Doc.GetProto(this.props.Document)[name] = ""; -            const created = Docs.Create.TextDocument("", { title: name, _width: 250, _autoHeight: true }); +                    }, +                    icon: 'compress-arrows-alt', +                }) +            ); +        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: 'Doc Fields ...', subitems: docItems, icon: 'eye' }); +        !Doc.UserDoc().noviceMode && ContextMenu.Instance.addItem({ description: 'Containers ...', subitems: layoutItems, icon: 'eye' }); +        ContextMenu.Instance.setDefaultItem('::', (name: string): void => { +            Doc.GetProto(this.props.Document)[name] = ''; +            const created = Docs.Create.TextDocument('', { title: name, _width: 250, _autoHeight: true });              if (created) {                  if (this.props.Document.isTemplateDoc) {                      Doc.MakeMetadataFieldTemplate(created, this.props.Document); @@ -233,98 +251,100 @@ export class CollectionNoteTakingViewColumn extends React.Component<CSVFieldColu              }          });          ContextMenu.Instance.displayMenu(x, y, undefined, true); -    } +    };      @computed get innards() {          TraceMobx();          const key = this.props.pivotField;          const heading = this._heading;          const columnYMargin = this.props.headingObject ? 0 : this.props.yMargin; -        const evContents = heading ? heading : "25"; -        const headingView = this.props.headingObject ? -            <div key={heading} className="collectionNoteTakingView-sectionHeader" ref={this._headerRef} +        const evContents = heading ? heading : '25'; +        const headingView = this.props.headingObject ? ( +            <div +                key={heading} +                className="collectionNoteTakingView-sectionHeader" +                ref={this._headerRef}                  style={{                      marginTop: 2 * this.props.yMargin,                      // width: (this.props.columnWidth) /                      //     ((uniqueHeadings.length) || 1) -                    width: this.columnWidth - 20 +                    width: this.columnWidth - 20,                  }}> -                <div className="collectionNoteTakingView-sectionHeader-subCont" onPointerDown={this.headerDown} -                    title={evContents === `No Value` ? -                        `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ""} -                    style={{ background: evContents !== `No Value` ? this._color : "inherit" }}> -                    <EditableView -                        GetValue={() => evContents} -                        SetValue={this.headingChanged} -                        contents={evContents} -                        oneLine={true} -                    /> +                <div +                    className="collectionNoteTakingView-sectionHeader-subCont" +                    onPointerDown={this.headerDown} +                    title={evContents === `No Value` ? `Documents that don't have a ${key} value will go here. This column cannot be removed.` : ''} +                    style={{ background: evContents !== `No Value` ? this._color : 'inherit' }}> +                    <EditableView GetValue={() => evContents} SetValue={this.headingChanged} contents={evContents} oneLine={true} />                  </div> -            </div> : (null); +            </div> +        ) : null;          // const templatecols = `${this.props.columnWidth / this.props.numGroupColumns}px `;          const templatecols = `${this.columnWidth}px `;          const type = this.props.Document.type; -        return <> -            {headingView} -            {<div> -              <div key={`${heading}-stack`} className={`collectionNoteTakingView-Nodes`} -                  style={{ -                      padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`, -                      margin: "auto", -                      width: "max-content", //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`, -                      height: 'max-content', -                      position: "relative", -                      gridGap: this.props.gridGap, -                      gridTemplateColumns: templatecols, -                      gridAutoRows: "0px" -                  }}> -                  {this.props.renderChildren(this.props.docList)} -              </div> +        return ( +            <> +                {headingView} +                { +                    <div> +                        <div +                            key={`${heading}-stack`} +                            className={`collectionNoteTakingView-Nodes`} +                            style={{ +                                padding: `${columnYMargin}px ${0}px ${this.props.yMargin}px ${0}px`, +                                margin: 'auto', +                                width: 'max-content', //singleColumn ? undefined : `${cols * (style.columnWidth + style.gridGap) + 2 * style.xMargin - style.gridGap}px`, +                                height: 'max-content', +                                position: 'relative', +                                gridGap: this.props.gridGap, +                                gridTemplateColumns: templatecols, +                                gridAutoRows: '0px', +                            }}> +                            {this.props.renderChildren(this.props.docList)} +                        </div> -              {!this.props.chromeHidden && type !== DocumentType.PRES ? -                  <div className="collectionNoteTakingView-DocumentButtons" -                      // style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10 }}> -                      style={{ width: this.columnWidth - 20, marginBottom: 10 }}> -                      <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton"> -                          <EditableView -                              GetValue={returnEmptyString} -                              SetValue={this.addNewTextDoc} -                              textCallback={this.textCallback} -                              placeholder={"Type ':' for commands"} -                              contents={"+ New Node"} -                              menuCallback={this.menuCallback} -                          /> -                      </div> -                      <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton"> -                          <EditableView {...this.props.editableViewProps} /> -                      </div> -                      {(this.props.columnHeaders?.length && this.props.columnHeaders.length > 1) &&  -                          <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}> -                          <FontAwesomeIcon icon="trash" size="lg" /> -                      </button> -                      } -                  </div> -                  : null} -              </div> -            } -        </>; +                        {!this.props.chromeHidden && type !== DocumentType.PRES ? ( +                            <div +                                className="collectionNoteTakingView-DocumentButtons" +                                // style={{ width: this.props.columnWidth / this.props.numGroupColumns, marginBottom: 10 }}> +                                style={{ width: this.columnWidth - 20, marginBottom: 10 }}> +                                <div key={`${heading}-add-document`} className="collectionNoteTakingView-addDocumentButton"> +                                    <EditableView GetValue={returnEmptyString} SetValue={this.addNewTextDoc} textCallback={this.textCallback} placeholder={"Type ':' for commands"} contents={'+ New Node'} menuCallback={this.menuCallback} /> +                                </div> +                                <div key={`${this.props.Document[Id]}-addGroup`} className="collectionNoteTakingView-addDocumentButton"> +                                    <EditableView {...this.props.editableViewProps} /> +                                </div> +                                {this.props.columnHeaders?.length && this.props.columnHeaders.length > 1 && ( +                                    <button className="collectionNoteTakingView-sectionDelete" onClick={this.deleteColumn}> +                                        <FontAwesomeIcon icon="trash" size="lg" /> +                                    </button> +                                )} +                            </div> +                        ) : null} +                    </div> +                } +            </> +        );      } -      render() {          TraceMobx();          const heading = this._heading;          return ( -            <div className={"collectionNoteTakingViewFieldColumn" + (SnappingManager.GetIsDragging() ? "Dragging" : "")} key={heading} +            <div +                className={'collectionNoteTakingViewFieldColumn' + (SnappingManager.GetIsDragging() ? 'Dragging' : '')} +                key={heading}                  style={{ -                  //TODO: change this so that it's based on the column width  +                    //TODO: change this so that it's based on the column width                      width: this.columnWidth, -                    height: "100%", -                    background: this._background +                    height: '100%', +                    background: this._background,                  }} -                ref={this.createColumnDropRef} onPointerEnter={this.pointerEntered} onPointerLeave={this.pointerLeave}> +                ref={this.createColumnDropRef} +                onPointerEnter={this.pointerEntered} +                onPointerLeave={this.pointerLeave}>                  {this.innards} -            </div > +            </div>          );      } -}
\ No newline at end of file +} diff --git a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx index ed5dc3715..7d31b3193 100644 --- a/src/client/views/collections/CollectionNoteTakingViewDivider.tsx +++ b/src/client/views/collections/CollectionNoteTakingViewDivider.tsx @@ -1,61 +1,63 @@ -import { action, observable } from "mobx"; -import * as React from "react"; +import { action, observable } from 'mobx'; +import * as React from 'react';  interface DividerProps { -  index: number -  xMargin: number -  setColumnStartXCoords: (movementX: number, colIndex: number) => void +    index: number; +    xMargin: number; +    setColumnStartXCoords: (movementX: number, colIndex: number) => void;  } -export default class Divider extends React.Component<DividerProps>{ -  @observable private isHoverActive = false; -  @observable private isResizingActive = false; -   -  @action -  private registerResizing = (e: React.PointerEvent<HTMLDivElement>) => { -      e.stopPropagation(); -      e.preventDefault(); -      window.removeEventListener("pointermove", this.onPointerMove); -      window.removeEventListener("pointerup", this.onPointerUp); -      window.addEventListener("pointermove", this.onPointerMove); -      window.addEventListener("pointerup", this.onPointerUp); -      this.isResizingActive = true; -  } +export class CollectionNoteTakingViewDivider extends React.Component<DividerProps> { +    @observable private isHoverActive = false; +    @observable private isResizingActive = false; -  @action -  private onPointerUp = () => { -      this.isResizingActive = false; -      this.isHoverActive = false; -      window.removeEventListener("pointermove", this.onPointerMove); -      window.removeEventListener("pointerup", this.onPointerUp); -  } +    @action +    private registerResizing = (e: React.PointerEvent<HTMLDivElement>) => { +        e.stopPropagation(); +        e.preventDefault(); +        window.removeEventListener('pointermove', this.onPointerMove); +        window.removeEventListener('pointerup', this.onPointerUp); +        window.addEventListener('pointermove', this.onPointerMove); +        window.addEventListener('pointerup', this.onPointerUp); +        this.isResizingActive = true; +    }; -  @action -  onPointerMove = ({ movementX }: PointerEvent) => { -    this.props.setColumnStartXCoords(movementX, this.props.index) -  } -   -  render() { -    return ( -      <div className="columnResizer" -        style={{ -          display: "flex",  -          alignItems: "center",  -          cursor: "col-resize" -        }} -        onPointerEnter={action(() => this.isHoverActive = true)} -        onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))} -      > -        <div className="columnResizer-handler" onPointerDown={e => this.registerResizing(e)} -          style={{ -            height: "95%", -            width: 12, -            borderRight: "4px solid #282828", -            borderLeft: "4px solid #282828", -            margin: "0px 10px" -          }} -        /> -      </div> -    ) -  } -}
\ No newline at end of file +    @action +    private onPointerUp = () => { +        this.isResizingActive = false; +        this.isHoverActive = false; +        window.removeEventListener('pointermove', this.onPointerMove); +        window.removeEventListener('pointerup', this.onPointerUp); +    }; + +    @action +    onPointerMove = ({ movementX }: PointerEvent) => { +        this.props.setColumnStartXCoords(movementX, this.props.index); +    }; + +    render() { +        return ( +            <div +                className="columnResizer" +                style={{ +                    display: 'flex', +                    alignItems: 'center', +                    cursor: 'col-resize', +                }} +                onPointerEnter={action(() => (this.isHoverActive = true))} +                onPointerLeave={action(() => !this.isResizingActive && (this.isHoverActive = false))}> +                <div +                    className="columnResizer-handler" +                    onPointerDown={e => this.registerResizing(e)} +                    style={{ +                        height: '95%', +                        width: 12, +                        borderRight: '4px solid #282828', +                        borderLeft: '4px solid #282828', +                        margin: '0px 10px', +                    }} +                /> +            </div> +        ); +    } +} diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 1927db51e..ef68cadd7 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -447,8 +447,6 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection                  const newDocs = droppedDocs.length ? droppedDocs : de.complete.docDragData.droppedDocuments; // if nothing was added to the end of the list, then presumably the dropped documents were already in the list, but possibly got reordered so we use them.                  const docs = this.childDocList; -                // reset drag manager docs, because we just dropped -                DragManager.docsBeingDragged = [];                  // still figuring out where to add the document                  if (docs && newDocs.length) {                      const insertInd = dropInd === -1 ? docs.length : dropInd + dropAfter; @@ -456,6 +454,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection                      newDocs.filter(ndoc => docs.indexOf(ndoc) !== -1).forEach(ndoc => docs.splice(docs.indexOf(ndoc), 1));                      docs.splice(insertInd - offset, 0, ...newDocs);                  } +                // reset drag manager docs, because we just dropped +                DragManager.docsBeingDragged.length = 0;              }          } else if (de.complete.linkDragData?.dragDocument.context === this.props.Document && de.complete.linkDragData?.linkDragView?.props.CollectionFreeFormDocumentView?.()) {              const source = Docs.Create.TextDocument('', { _width: 200, _height: 75, _fitWidth: true, title: 'dropped annotation' }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index afb618b34..1ee1aec5a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -156,9 +156,7 @@ export interface DocumentViewSharedProps {      scriptContext?: any; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document      createNewFilterDoc?: () => void;      updateFilterDoc?: (doc: Doc) => void; -    // Parker added both of these -    originalBackgroundColor?: string; -    isNoteTakingView?: boolean; +    dontHideOnDrag?: boolean;  }  // these props are specific to DocuentViews @@ -494,12 +492,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps      startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {          if (this._mainCont.current) {              const dragData = new DragManager.DocumentDragData([this.props.Document]); -            if (this.props.isNoteTakingView) { -                dragData.draggedDocuments.forEach((doc) => { -                doc.backgroundColor = "#C9DAEF"; -                doc.opacity = 0.5; -              }); -            }              const [left, top] = this.props.ScreenToLocalTransform().scale(this.NativeDimScaling).inverse().transformPoint(0, 0);              dragData.offset = this.props                  .ScreenToLocalTransform() @@ -511,22 +503,16 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps              dragData.treeViewDoc = this.props.treeViewDoc;              dragData.removeDocument = this.props.removeDocument;              dragData.moveDocument = this.props.moveDocument; -            //dragData.dimSource :  -            // dragEffects field, set dim  +            //dragData.dimSource : +            // dragEffects field, set dim              // add kv pairs to a doc, swap properties with the node while dragging, and then swap when dropping              // add a dragEffects prop to DocumentView as a function that sets up. Each view has its own prop, when you start dragging: -            // in Draganager, figure out which doc(s) you're dragging and change what opacity function returns   +            // in Draganager, figure out which doc(s) you're dragging and change what opacity function returns              const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView; -            ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));             -            DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStar && !this.props.isNoteTakingView)}, -                () => setTimeout(action(() => { -                  ffview && (ffview.ChildDrag = undefined) -                  //TODO: is there a better way than adding another field to the props? Not quite sure how "this" works tbh -                  if (this.props.isNoteTakingView) { -                    this.props.Document.backgroundColor = ""; -                    this.props.Document.opacity = 1; -                  } -                }))); // this needs to happen after the drop event is processed. +            ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView())); +            DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart && !this.props.dontHideOnDrag) }, () => +                setTimeout(action(() => ffview && (ffview.ChildDrag = undefined))) +            ); // this needs to happen after the drop event is processed.              ffview?.setupDragLines(false);          }      } diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index b8ee89ef2..add83f4e0 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -1001,7 +1001,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps              () => ({ sidebarHeight: this.sidebarHeight, textHeight: this.textHeight, autoHeight: this.autoHeight, marginsHeight: this.autoHeightMargins }),              ({ sidebarHeight, textHeight, autoHeight, marginsHeight }) => {                  const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight)); -                autoHeight && newHeight && this.props.setHeight?.(newHeight); +                if (autoHeight && newHeight && newHeight !== this.rootDoc.height) { +                    this.props.setHeight?.(newHeight); +                }              },              { fireImmediately: true }          ); @@ -1695,7 +1697,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps              if (this.props.setHeight && scrollHeight && this.props.renderDepth && !this.props.dontRegisterView) {                  // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation                  const setScrollHeight = () => (this.rootDoc[this.fieldKey + '-scrollHeight'] = scrollHeight); -                if (this.rootDoc === this.layoutDoc.doc || this.layoutDoc.resolvedDataDoc) { +                if (this.rootDoc === this.layoutDoc || this.layoutDoc.resolvedDataDoc) {                      setScrollHeight();                  } else {                      setTimeout(setScrollHeight, 10); // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template.  So set a timeout and hope its arrived... | 
