From dca61505ba138eef3819b16b760ec81becf9329e Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 13 May 2023 09:55:48 -0400 Subject: changed EditableViews to support oneline and multiline. Also added transformer UI to allow documents to be entered. changed transformer to write doc id's, not variables.. made schema view support oneline and fixed bug with docdecoration hader occluding things invisibly. updated web pages to be zoomable and for its anchors to update web page and scroll location properly. made autolinkanchor directly go to target on click. --- .../views/collections/CollectionStackingView.scss | 6 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 18 ++++----- .../collectionSchema/CollectionSchemaView.scss | 4 +- .../collectionSchema/CollectionSchemaView.tsx | 23 ++++++----- .../collectionSchema/SchemaColumnHeader.tsx | 1 + .../collections/collectionSchema/SchemaRowBox.tsx | 10 +++-- .../collectionSchema/SchemaTableCell.tsx | 44 +++++++++++++++------- 7 files changed, 67 insertions(+), 39 deletions(-) (limited to 'src/client/views/collections') diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index f3397e2c4..99a68e94b 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -372,7 +372,8 @@ .editableView-container-editing-oneLine, .editableView-container-editing { color: grey; - padding-top: 10px; + padding-top: 5px; + padding-bottom: 5px; width: 100%; } @@ -387,7 +388,8 @@ letter-spacing: 2px; color: grey; border: 0px; - padding-top: 10px; // 12px 10px 11px 10px; + padding-top: 5px; // 12px 10px 11px 10px; + padding-bottom: 5px; // 12px 10px 11px 10px; } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 29bdc0e2d..08e3174d1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -53,7 +53,6 @@ import { MarqueeView } from './MarqueeView'; import React = require('react'); export type collectionFreeformViewProps = { - noPointerWheel?: () => boolean; // turn off pointerwheel interactions (see PDFViewer) NativeWidth?: () => number; NativeHeight?: () => number; originTopLeft?: boolean; @@ -1023,13 +1022,14 @@ export class CollectionFreeFormView extends CollectionSubView= 0.05 || localTransform.Scale > this.zoomScaling()) { const safeScale = Math.min(Math.max(0.05, localTransform.Scale), 20); this.props.Document[this.scaleFieldKey] = Math.abs(safeScale); @@ -1039,17 +1039,19 @@ export class CollectionFreeFormView extends CollectionSubView { - if (this.props.noPointerWheel?.() || this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom + if (this.Document._isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom PresBox.Instance?.pauseAutoPres(); if (this.layoutDoc._Transform || DocListCast(Doc.MyOverlayDocs?.data).includes(this.props.Document) || this.props.Document.treeViewOutlineMode === TreeViewType.outline) return; e.stopPropagation(); - e.preventDefault(); switch (!e.ctrlKey ? Doc.UserDoc().freeformScrollMode : freeformScrollMode.Pan) { case freeformScrollMode.Pan: // if ctrl is selected then zoom if (e.ctrlKey) { if (this.props.isContentActive(true)) { - this.zoom(e.clientX, e.clientY, e.deltaY); // if (!this.props.isAnnotationOverlay) // bcz: do we want to zoom in on images/videos/etc? + if (this.props.isAnnotationOverlayScrollable) { + // bcz: zooming on a webbox doesn't get the correct coordinates here for unknown reasons. + // so better to do nothing than having things jump around. + } else this.zoom(e.screenX, e.screenY, e.deltaY); } } // otherwise pan else if (this.props.isContentActive(true)) { @@ -1123,16 +1125,14 @@ export class CollectionFreeFormView extends CollectionSubView { - this.rootDoc.scrollTop = relTop * maxScrollTop; - }, 10); + setTimeout(() => (this.rootDoc.scrollTop = relTop * maxScrollTop), 10); newPanY = minPanY; } !this.Document._verticalScroll && (this.Document[this.panXFieldKey] = this.isAnnotationOverlay ? newPanX : panX); diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index a9434fde3..3a0c2c85c 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -182,8 +182,10 @@ .schema-table-cell, .row-menu { border: 1px solid $medium-gray; - overflow: hidden; + overflow-x: hidden; + overflow-y: auto; padding: 5px; + display: inline-block; } .schema-row { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index a59d7e5a3..588affc1c 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -56,7 +56,8 @@ export class CollectionSchemaView extends CollectionSubView() { private _documentOptions: DocumentOptions = new DocumentOptions(); private _tableContentRef: HTMLDivElement | null = null; - public static _rowHeight: number = 50; + static _rowHeight: number = 50; + static _rowSingleLineHeight: number = 32; public static _minColWidth: number = 25; public static _rowMenuWidth: number = 60; public static _previewDividerWidth: number = 4; @@ -515,9 +516,9 @@ export class CollectionSchemaView extends CollectionSubView() { if (found) { const rect = found.getBoundingClientRect(); const localRect = this.props.ScreenToLocalTransform().transformBounds(rect.left, rect.top, rect.width, rect.height); - if (localRect.y < CollectionSchemaView._rowHeight || localRect.y + localRect.height > this.props.PanelHeight()) { + if (localRect.y < this.rowHeightFunc() || localRect.y + localRect.height > this.props.PanelHeight()) { let focusSpeed = options.zoomTime ?? 50; - smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - CollectionSchemaView._rowHeight, options.easeFunc); + smoothScroll(focusSpeed, this._tableContentRef!, localRect.y + this._tableContentRef!.scrollTop - this.rowHeightFunc(), options.easeFunc); return focusSpeed; } } @@ -836,6 +837,7 @@ export class CollectionSchemaView extends CollectionSubView() { }); return { docs }; } + rowHeightFunc = () => (BoolCast(this.layoutDoc._singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); sortedDocsFunc = () => this.sortedDocs; isContentActive = () => this.props.isSelected() || this.props.isContentActive(); screenToLocal = () => this.props.ScreenToLocalTransform().translate(-this.tableWidth, 0); @@ -850,7 +852,7 @@ export class CollectionSchemaView extends CollectionSubView() { // prevent wheel events from passively propagating up through containers r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false }); }}> -
+
(this._columnMenuIndex === -1 ? this.closeColumnMenu() : this.openColumnMenu(-1, true))}> @@ -865,6 +867,7 @@ export class CollectionSchemaView extends CollectionSubView() { sortField={this.sortField} sortDesc={this.sortDesc} setSort={this.setSort} + rowHeight={this.rowHeightFunc} removeColumn={this.removeColumn} resizeColumn={this.startResize} openContextMenu={this.openContextMenu} @@ -875,7 +878,7 @@ export class CollectionSchemaView extends CollectionSubView() {
{this._columnMenuIndex !== undefined && this.renderColumnMenu} {this._filterColumnIndex !== undefined && this.renderFilterMenu} - (this._tableContentRef = ref)} /> + (this._tableContentRef = ref)} />
{this.previewWidth > 0 &&
} @@ -922,20 +925,20 @@ interface CollectionSchemaViewDocsProps { schema: CollectionSchemaView; setRef: (ref: HTMLDivElement | null) => void; childDocs: () => { docs: Doc[] }; + rowHeight: () => number; } @observer class CollectionSchemaViewDocs extends React.Component { tableWidthFunc = () => this.props.schema.tableWidth; - rowHeightFunc = () => CollectionSchemaView._rowHeight; - childScreenToLocal = computedFn((index: number) => () => this.props.schema.props.ScreenToLocalTransform().translate(0, -CollectionSchemaView._rowHeight - index * this.rowHeightFunc())); + childScreenToLocal = computedFn((index: number) => () => this.props.schema.props.ScreenToLocalTransform().translate(0, -this.props.rowHeight() - index * this.props.rowHeight())); render() { return ( -
+
{this.props.childDocs().docs.map((doc: Doc, index: number) => { const dataDoc = !doc.isTemplateDoc && !doc.isTemplateForField ? undefined : this.props.schema.props.DataDoc; return ( -
+
void; removeColumn: (index: number) => void; + rowHeight: () => number; resizeColumn: (e: any, index: number) => void; dragColumn: (e: any, index: number) => boolean; openContextMenu: (x: number, y: number, index: number) => void; diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index ca9e0bda0..34631e0b7 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -2,6 +2,9 @@ import React = require('react'); import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { computed } from 'mobx'; import { observer } from 'mobx-react'; +import { computedFn } from 'mobx-utils'; +import { Doc } from '../../../../fields/Doc'; +import { BoolCast } from '../../../../fields/Types'; import { DragManager } from '../../../util/DragManager'; import { SnappingManager } from '../../../util/SnappingManager'; import { undoBatch } from '../../../util/UndoManager'; @@ -12,8 +15,6 @@ import { FieldView, FieldViewProps } from '../../nodes/FieldView'; import { CollectionSchemaView } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; import { SchemaTableCell } from './SchemaTableCell'; -import { computedFn } from 'mobx-utils'; -import { Doc } from '../../../../fields/Doc'; @observer export class SchemaRowBox extends ViewBoxBaseComponent() { @@ -95,7 +96,7 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { return (
{ @@ -132,13 +133,16 @@ export class SchemaRowBox extends ViewBoxBaseComponent() { Document={this.rootDoc} col={index} fieldKey={key} + allowCRs={false} // to enter text with new lines, must use \n columnWidth={this.columnWidth(index)} + rowHeight={this.schemaView.rowHeightFunc} isRowActive={this.props.isContentActive} getFinfo={this.getFinfo} selectCell={this.selectCell} deselectCell={this.deselectCell} selectedCell={this.selectedCell} setColumnValues={this.setColumnValues} + oneLine={BoolCast(this.schemaDoc?._singleLine)} /> ))}
diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 712bd4491..12daa1252 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -5,22 +5,24 @@ import { extname } from 'path'; import DatePicker from 'react-datepicker'; import { DateField } from '../../../../fields/DateField'; import { Doc, DocListCast, Field } from '../../../../fields/Doc'; +import { RichTextField } from '../../../../fields/RichTextField'; import { BoolCast, Cast, DateCast, FieldValue } from '../../../../fields/Types'; import { ImageField } from '../../../../fields/URLField'; import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnZero, Utils } from '../../../../Utils'; import { FInfo } from '../../../documents/Documents'; +import { DocFocusOrOpen } from '../../../util/DocumentManager'; import { dropActionType } from '../../../util/DragManager'; import { Transform } from '../../../util/Transform'; import { undoBatch } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; import { Colors } from '../../global/globalEnums'; +import { OpenWhere } from '../../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../../nodes/FieldView'; +import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { KeyValueBox } from '../../nodes/KeyValueBox'; import { DefaultStyleProvider } from '../../StyleProvider'; -import { CollectionSchemaView, ColumnType, FInfotoColType } from './CollectionSchemaView'; +import { ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; -import { RichTextField } from '../../../../fields/RichTextField'; -import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; export interface SchemaTableCellProps { Document: Doc; @@ -29,17 +31,24 @@ export interface SchemaTableCellProps { selectCell: (doc: Doc, col: number) => void; selectedCell: () => [Doc, number] | undefined; fieldKey: string; + maxWidth?: () => number; columnWidth: () => number; + rowHeight: () => number; + padding?: number; // default is 5 -- see scss isRowActive: () => boolean | undefined; getFinfo: (fieldKey: string) => FInfo | undefined; setColumnValues: (field: string, value: string) => boolean; + oneLine?: boolean; // whether all input should fit on one line vs allowing textare multiline inputs + allowCRs?: boolean; // allow carriage returns in text input (othewrise CR ends the edit) + finishEdit?: () => void; // notify container that edit is over (eg. to hide view in DashFieldView) } @observer export class SchemaTableCell extends React.Component { - public static colRowHeightFunc() { - return CollectionSchemaView._rowHeight; - } + static addFieldDoc = (doc: Doc, where: OpenWhere) => { + DocFocusOrOpen(doc); + return true; + }; public static renderProps(props: SchemaTableCellProps) { const { Document, fieldKey, getFinfo, columnWidth, isRowActive } = props; let protoCount = 0; @@ -71,12 +80,12 @@ export class SchemaTableCell extends React.Component { whenChildContentsActiveChanged: emptyFunction, ScreenToLocalTransform: Transform.Identity, focus: emptyFunction, - addDocTab: returnFalse, + addDocTab: SchemaTableCell.addFieldDoc, pinToPres: returnZero, Document, fieldKey, PanelWidth: columnWidth, - PanelHeight: SchemaTableCell.colRowHeightFunc, + PanelHeight: props.rowHeight, }; const readOnly = getFinfo(fieldKey)?.readOnly ?? false; const cursor = !readOnly ? 'text' : 'default'; @@ -98,8 +107,11 @@ export class SchemaTableCell extends React.Component { style={{ color, textDecoration, + width: '100%', }}> } editing={this.selected ? undefined : false} GetValue={() => Field.toKeyValueString(this.props.Document, this.props.fieldKey)} @@ -107,7 +119,9 @@ export class SchemaTableCell extends React.Component { if (shiftDown && enterKey) { this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value); } - return KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value); + const ret = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value); + this.props.finishEdit?.(); + return ret; })} />
@@ -121,7 +135,7 @@ export class SchemaTableCell extends React.Component { if (cellValue instanceof RichTextField) return ColumnType.RTF; if (typeof cellValue === 'number') return ColumnType.Any; if (typeof cellValue === 'string') return ColumnType.Any; - if (typeof cellValue === 'boolean') return ColumnType.Any; + if (typeof cellValue === 'boolean') return ColumnType.Boolean; const columnTypeStr = this.props.getFinfo(this.props.fieldKey)?.fieldType; if (columnTypeStr && columnTypeStr in FInfotoColType) { @@ -148,7 +162,7 @@ export class SchemaTableCell extends React.Component {
!this.selected && this.props.selectCell(this.props.Document, this.props.col))} - style={{ width: this.props.columnWidth(), border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> + style={{ padding: this.props.padding, maxWidth: this.props.maxWidth?.(), width: this.props.columnWidth() || undefined, border: this.selected ? `solid 2px ${Colors.MEDIUM_BLUE}` : undefined }}> {this.content}
); @@ -211,8 +225,8 @@ export class SchemaImageCell extends React.Component { const aspect = Doc.NativeAspect(this.props.Document); // aspect ratio // let width = Math.max(75, this.props.columnWidth); // get a with that is no smaller than 75px // const height = Math.max(75, width / aspect); // get a height either proportional to that or 75 px - const height = CollectionSchemaView._rowHeight - 10; - const width = height * aspect; // increase the width of the image if necessary to maintain proportionality + const height = this.props.rowHeight() ? this.props.rowHeight() - (this.props.padding || 6) * 2 : undefined; + const width = height ? height * aspect : undefined; // increase the width of the image if necessary to maintain proportionality return ; } @@ -288,7 +302,9 @@ export class SchemaBoolCell extends React.Component { if (shiftDown && enterKey) { this.props.setColumnValues(this.props.fieldKey.replace(/^_/, ''), value); } - return KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value); + const set = KeyValueBox.SetField(this.props.Document, this.props.fieldKey.replace(/^_/, ''), value); + this.props.finishEdit?.(); + return set; })} />
-- cgit v1.2.3-70-g09d2