diff options
| author | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-03-22 22:11:37 -0400 |
|---|---|---|
| committer | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-03-22 22:11:37 -0400 |
| commit | 3c5bc5b89c3158c6c1dce02f99aa0c08d24dcb39 (patch) | |
| tree | 99bed6d83f5a01ff2654cd4fb635ea5c48bcc820 /src/client/views/collections/collectionSchema | |
| parent | 26d7e045c5b0a9a29612e68d976e35c0e7e23d00 (diff) | |
| parent | a974aa4e6573c8becf93f78610406747fec14c1c (diff) | |
Merge branch 'master' into nathan-starter
Diffstat (limited to 'src/client/views/collections/collectionSchema')
3 files changed, 142 insertions, 120 deletions
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index fed4e89cf..ac0bd2378 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -38,91 +38,97 @@ background: yellow; } } + } - .schema-column-menu, - .schema-filter-menu { - background: $light-gray; - position: absolute; - min-width: 200px; - max-width: 400px; - display: flex; - flex-direction: column; - align-items: flex-start; - z-index: 1; - - .schema-key-search-input { - width: calc(100% - 20px); - margin: 10px; - } + .schema-preview-divider { + height: 100%; + background: black; + cursor: ew-resize; + } +} - .schema-search-result { - cursor: pointer; - padding: 5px 10px; - width: 100%; +.schema-column-menu, +.schema-filter-menu { + background: $light-gray; + position: relative; + min-width: 200px; + max-width: 400px; + display: flex; + flex-direction: column; + align-items: flex-start; + z-index: 1; - &:hover { - background-color: $medium-gray; - } + .schema-key-search-input { + width: calc(100% - 20px); + margin: 10px; + } - .schema-search-result-type, - .schema-search-result-desc { - color: $dark-gray; - font-size: $body-text; - } - } + .schema-search-result { + cursor: pointer; + padding: 5px 10px; + width: 100%; - .schema-key-search, - .schema-new-key-options { - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - } + &:hover { + background-color: $medium-gray; + } + .schema-search-result-type { + font-family: 'Courier New', Courier, monospace; + } - .schema-new-key-options { - margin: 10px; - .schema-key-warning { - color: red; - font-weight: normal; - align-self: center; - } - } + .schema-search-result-type, + .schema-search-result-desc { + color: $dark-gray; + font-size: $body-text; + } + .schema-search-result-desc { + font-style: italic; + } + } - .schema-key-list { - width: 100%; - max-height: 300px; - overflow-y: auto; - } + .schema-key-search, + .schema-new-key-options { + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + } - .schema-key-type-option { - margin: 2px 0px; + .schema-new-key-options { + margin: 10px; + .schema-key-warning { + color: red; + font-weight: normal; + align-self: center; + } + } - input { - margin-right: 5px; - } - } + .schema-key-list { + width: 100%; + max-height: 300px; + overflow-y: auto; + } - .schema-key-default-val { - margin: 5px 0; - } + .schema-key-type-option { + margin: 2px 0px; - .schema-column-menu-button { - cursor: pointer; - padding: 2px 5px; - background: $medium-blue; - border-radius: 9999px; - color: $white; - width: fit-content; - margin: 5px; - align-self: center; - } + input { + margin-right: 5px; } } - .schema-preview-divider { - height: 100%; - background: black; - cursor: ew-resize; + .schema-key-default-val { + margin: 5px 0; + } + + .schema-column-menu-button { + cursor: pointer; + padding: 2px 5px; + background: $medium-blue; + border-radius: 9999px; + color: $white; + width: fit-content; + margin: 5px; + align-self: center; } } @@ -133,6 +139,7 @@ .row-menu { display: flex; justify-content: center; + cursor: pointer; } } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 71938d13e..631ad7132 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -1,31 +1,33 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, makeObservable, observable, ObservableMap, observe } from 'mobx'; +import { Popup, PopupTrigger, Type } from 'browndash-components'; +import { ObservableMap, action, computed, makeObservable, observable, observe } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; +import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; import { Doc, DocListCast, Field, NumListCast, Opt, StrListCast } from '../../../../fields/Doc'; +import { DocData } from '../../../../fields/DocSymbols'; import { Id } from '../../../../fields/FieldSymbols'; import { List } from '../../../../fields/List'; import { listSpec } from '../../../../fields/Schema'; import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyString, returnFalse, returnIgnore, returnNever, returnTrue, setupMoveUpEvents, smoothScroll } from '../../../../Utils'; -import { Docs, DocumentOptions, DocUtils, FInfo } from '../../../documents/Documents'; +import { DocUtils, Docs, DocumentOptions, FInfo } from '../../../documents/Documents'; import { DocumentManager } from '../../../util/DocumentManager'; import { DragManager, dropActionType } from '../../../util/DragManager'; import { SelectionManager } from '../../../util/SelectionManager'; -import { undoable, undoBatch } from '../../../util/UndoManager'; +import { SettingsManager } from '../../../util/SettingsManager'; +import { undoBatch, undoable } from '../../../util/UndoManager'; import { ContextMenu } from '../../ContextMenu'; import { EditableView } from '../../EditableView'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; import { Colors } from '../../global/globalEnums'; import { DocumentView } from '../../nodes/DocumentView'; -import { FocusViewOptions, FieldViewProps } from '../../nodes/FieldView'; +import { FieldViewProps, FocusViewOptions } from '../../nodes/FieldView'; import { KeyValueBox } from '../../nodes/KeyValueBox'; -import { ObservableReactComponent } from '../../ObservableReactComponent'; -import { DefaultStyleProvider, StyleProp } from '../../StyleProvider'; import { CollectionSubView } from '../CollectionSubView'; import './CollectionSchemaView.scss'; import { SchemaColumnHeader } from './SchemaColumnHeader'; import { SchemaRowBox } from './SchemaRowBox'; -import { faLessThanEqual } from '@fortawesome/free-solid-svg-icons'; const { default: { SCHEMA_NEW_NODE_HEIGHT } } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore export enum ColumnType { @@ -165,7 +167,7 @@ export class CollectionSchemaView extends CollectionSubView() { (change as any).added.forEach((doc: Doc) => // for each document added Doc.GetAllPrototypes(doc.value as Doc).forEach(proto => // for all of its prototypes (and itself) Object.keys(proto).forEach(action(key => // check if any of its keys are new, and add them - !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo(key, key === 'author')))))); + !this.fieldInfos.get(key) && this.fieldInfos.set(key, new FInfo("-no description-", key === 'author')))))); break; case 'update': //let oldValue = change.oldValue; // fill this in if the entire child list will ever be reassigned with a new list } @@ -294,7 +296,7 @@ export class CollectionSchemaView extends CollectionSubView() { }; @action - addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[key] = defaultVal)); + addNewKey = (key: string, defaultVal: any) => this.childDocs.forEach(doc => (doc[DocData][key] = defaultVal)); @undoBatch removeColumn = (index: number) => { @@ -747,6 +749,7 @@ export class CollectionSchemaView extends CollectionSubView() { } else { this.setKey(this._menuValue, this._newFieldDefault); } + this._columnMenuIndex = undefined; })}> done </div> @@ -754,12 +757,12 @@ export class CollectionSchemaView extends CollectionSubView() { ); } - onPassiveWheel = (e: WheelEvent) => { + onKeysPassiveWheel = (e: WheelEvent) => { // if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this) - if (!this._oldWheel.scrollTop && e.deltaY <= 0) e.preventDefault(); + if (!this._oldKeysWheel.scrollTop && e.deltaY <= 0) e.preventDefault(); e.stopPropagation(); }; - _oldWheel: any; + _oldKeysWheel: any; @computed get keysDropdown() { return ( <div className="schema-key-search"> @@ -774,9 +777,9 @@ export class CollectionSchemaView extends CollectionSubView() { <div className="schema-key-list" ref={r => { - this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); - this._oldWheel = r; - r?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); + this._oldKeysWheel?.removeEventListener('wheel', this.onKeysPassiveWheel); + this._oldKeysWheel = r; + r?.addEventListener('wheel', this.onKeysPassiveWheel, { passive: false }); }}> {this._menuKeys.map(key => ( <div @@ -787,14 +790,14 @@ export class CollectionSchemaView extends CollectionSubView() { }}> <p> <span className="schema-search-result-key"> - {key} - {this.fieldInfos.get(key)!.fieldType ? ', ' : ''} + <b>{key}</b> + {this.fieldInfos.get(key)!.fieldType ? ':' : ''} </span> <span className="schema-search-result-type" style={{ color: this.fieldInfos.get(key)!.readOnly ? 'red' : 'inherit' }}> {this.fieldInfos.get(key)!.fieldType} </span> + <span className="schema-search-result-desc"> {this.fieldInfos.get(key)!.description}</span> </p> - <p className="schema-search-result-desc">{this.fieldInfos.get(key)!.description}</p> </div> ))} </div> @@ -806,16 +809,17 @@ export class CollectionSchemaView extends CollectionSubView() { const x = this._columnMenuIndex! == -1 ? 0 : this.displayColumnWidths.reduce((total, curr, index) => total + (index < this._columnMenuIndex! ? curr : 0), CollectionSchemaView._rowMenuWidth); return ( <div className="schema-column-menu" style={{ left: x, minWidth: CollectionSchemaView._minColWidth }}> - <input className="schema-key-search-input" type="text" value={this._menuValue} onKeyDown={this.onSearchKeyDown} onChange={this.updateKeySearch} onPointerDown={e => e.stopPropagation()} /> + <input className="schema-key-search-input" type="text" onKeyDown={this.onSearchKeyDown} onChange={this.updateKeySearch} onPointerDown={e => e.stopPropagation()} /> + {this._makeNewField ? this.newFieldMenu : this.keysDropdown} + </div> + ); + } + get renderKeysMenu() { + console.log('RNDERMENUT:' + this._columnMenuIndex); + return ( + <div className="schema-column-menu" style={{ left: 0, minWidth: CollectionSchemaView._minColWidth }}> + <input className="schema-key-search-input" type="text" onKeyDown={this.onSearchKeyDown} onChange={this.updateKeySearch} onPointerDown={e => e.stopPropagation()} /> {this._makeNewField ? this.newFieldMenu : this.keysDropdown} - <div - className="schema-column-menu-button" - onPointerDown={action(e => { - e.stopPropagation(); - this.closeColumnMenu(); - })}> - cancel - </div> </div> ); } @@ -899,6 +903,8 @@ export class CollectionSchemaView extends CollectionSubView() { isContentActive = () => this._props.isSelected() || this._props.isContentActive(); screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; + onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); + _oldWheel: any; render() { return ( <div className="collectionSchemaView" ref={(ele: HTMLDivElement | null) => this.createDashEventsTarget(ele)} onDrop={this.onExternalDrop.bind(this)}> @@ -907,15 +913,23 @@ export class CollectionSchemaView extends CollectionSubView() { className="schema-table" style={{ width: `calc(100% - ${this.previewWidth}px)` }} onWheel={e => this._props.isContentActive() && e.stopPropagation()} - ref={r => { - // prevent wheel events from passively propagating up through containers - r?.addEventListener('wheel', (e: WheelEvent) => {}, { passive: false }); + ref={ele => { + // prevent wheel events from passively propagating up through containers and prevents containers from preventDefault which would block scrolling + this._oldWheel?.removeEventListener('wheel', this.onPassiveWheel); + (this._oldWheel = ele)?.addEventListener('wheel', this.onPassiveWheel, { passive: false }); }}> <div className="schema-header-row" style={{ height: this.rowHeightFunc() }}> <div className="row-menu" style={{ width: CollectionSchemaView._rowMenuWidth }}> - <div className="schema-header-button" onPointerDown={e => (this._columnMenuIndex === -1 ? this.closeColumnMenu() : this.openColumnMenu(-1, true))}> - <FontAwesomeIcon icon="plus" /> - </div> + <Popup + placement="right" + background={SettingsManager.userBackgroundColor} + color={SettingsManager.userColor} + toggle={<FontAwesomeIcon onPointerDown={e => this.openColumnMenu(-1, true)} icon="plus" />} + trigger={PopupTrigger.CLICK} + type={Type.TERT} + isOpen={this._columnMenuIndex !== -1 ? false : undefined} + popup={this.renderKeysMenu} + /> </div> {this.columnKeys.map((key, index) => ( <SchemaColumnHeader @@ -936,7 +950,7 @@ export class CollectionSchemaView extends CollectionSubView() { /> ))} </div> - {this._columnMenuIndex !== undefined && this.renderColumnMenu} + {this._columnMenuIndex !== undefined && this._columnMenuIndex !== -1 && this.renderColumnMenu} {this._filterColumnIndex !== undefined && this.renderFilterMenu} <CollectionSchemaViewDocs schema={this} childDocs={this.sortedDocsFunc} rowHeight={this.rowHeightFunc} setRef={(ref: HTMLDivElement | null) => (this._tableContentRef = ref)} /> {this.layoutDoc.chromeHidden ? null : ( diff --git a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx index 1c4520ae2..734345255 100644 --- a/src/client/views/collections/collectionSchema/SchemaTableCell.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTableCell.tsx @@ -1,8 +1,11 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Popup, Size, Type } from 'browndash-components'; import { action, computed, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import { extname } from 'path'; import * as React from 'react'; import DatePicker from 'react-datepicker'; +import 'react-datepicker/dist/react-datepicker.css'; import Select from 'react-select'; import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero } from '../../../../Utils'; import { DateField } from '../../../../fields/DateField'; @@ -12,6 +15,8 @@ import { BoolCast, Cast, DateCast, DocCast, FieldValue, StrCast } from '../../.. import { ImageField } from '../../../../fields/URLField'; import { FInfo, FInfoFieldType } from '../../../documents/Documents'; import { DocFocusOrOpen } from '../../../util/DocumentManager'; +import { dropActionType } from '../../../util/DragManager'; +import { SettingsManager } from '../../../util/SettingsManager'; import { Transform } from '../../../util/Transform'; import { undoBatch, undoable } from '../../../util/UndoManager'; import { EditableView } from '../../EditableView'; @@ -24,12 +29,7 @@ import { KeyValueBox } from '../../nodes/KeyValueBox'; import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox'; import { ColumnType, FInfotoColType } from './CollectionSchemaView'; import './CollectionSchemaView.scss'; -import 'react-datepicker/dist/react-datepicker.css'; -import { Popup, Size, Type } from 'browndash-components'; -import { IconLookup, faCaretDown } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { SettingsManager } from '../../../util/SettingsManager'; -import { dropActionType } from '../../../util/DragManager'; +import { SnappingManager } from '../../../util/SnappingManager'; export interface SchemaTableCellProps { Document: Doc; @@ -132,14 +132,14 @@ export class SchemaTableCell extends ObservableReactComponent<SchemaTableCellPro contents={undefined} fieldContents={fieldProps} editing={this.selected ? undefined : false} - GetValue={() => Field.toKeyValueString(this._props.Document, this._props.fieldKey)} + GetValue={() => Field.toKeyValueString(this._props.Document, this._props.fieldKey, SnappingManager.MetaKey)} SetValue={undoable((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); - } /*else { - this._props.setSelectedColumnValues(this._props.fieldKey.replace(/^_/, ''), value); - }*/ - const ret = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value); + this._props.finishEdit?.(); + return true; + } + const ret = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(this._props.Document) ? true : undefined); this._props.finishEdit?.(); return ret; }, 'edit schema cell')} @@ -354,8 +354,7 @@ export class SchemaBoolCell extends ObservableReactComponent<SchemaTableCellProp onChange={undoBatch((value: React.ChangeEvent<HTMLInputElement> | undefined) => { if ((value?.nativeEvent as any).shiftKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString()); - } - KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString()); + } else KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), (color === 'black' ? '=' : '') + value?.target?.checked.toString()); })} /> <EditableView @@ -366,8 +365,10 @@ export class SchemaBoolCell extends ObservableReactComponent<SchemaTableCellProp SetValue={undoBatch((value: string, shiftDown?: boolean, enterKey?: boolean) => { if (shiftDown && enterKey) { this._props.setColumnValues(this._props.fieldKey.replace(/^_/, ''), value); + this._props.finishEdit?.(); + return true; } - const set = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value); + const set = KeyValueBox.SetField(this._props.Document, this._props.fieldKey.replace(/^_/, ''), value, Doc.IsDataProto(this._props.Document) ? true : undefined); this._props.finishEdit?.(); return set; })} |
