diff options
author | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-06-07 19:36:59 -0400 |
---|---|---|
committer | Nathan-SR <144961007+Nathan-SR@users.noreply.github.com> | 2024-06-07 19:36:59 -0400 |
commit | 97977e7156eb852c20422fa995bbf96529dfb4e5 (patch) | |
tree | c177a7375f0dbab033f46cceb3e7fe64b4624326 | |
parent | c8dc7104f8a4923bcfc70dcc5ff5f492666487bd (diff) |
sort overhaul for columnheader menu cleanup (sort is now a single action, not a persistent toggle; more like google sheets now)
-rw-r--r-- | src/client/views/EditableView.scss | 3 | ||||
-rw-r--r-- | src/client/views/EditableView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/collections/collectionSchema/CollectionSchemaView.tsx | 106 | ||||
-rw-r--r-- | src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx | 16 | ||||
-rw-r--r-- | src/client/views/collections/collectionSchema/SchemaRowBox.tsx | 7 |
6 files changed, 69 insertions, 71 deletions
diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss index e492068c8..d2f11f5e1 100644 --- a/src/client/views/EditableView.scss +++ b/src/client/views/EditableView.scss @@ -34,9 +34,8 @@ pointer-events: all; } - - .editableView-input:focus { border: none; outline: none; } + diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 5b690bf33..1652e6cd7 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -10,6 +10,7 @@ import { DocumentIconContainer } from './nodes/DocumentIcon'; import { FieldView, FieldViewProps } from './nodes/FieldView'; import { ObservableReactComponent } from './ObservableReactComponent'; import { OverlayView } from './OverlayView'; +import { Padding } from 'browndash-components'; export interface EditableProps { /** @@ -293,10 +294,10 @@ export class EditableView extends ObservableReactComponent<EditableProps> { // eslint-disable-next-line jsx-a11y/no-autofocus /> } else { - toDisplay = (<span + toDisplay = (<span className='editableView-static' style={{ fontStyle: this._props.fontStyle, - fontSize: this._props.fontSize, + fontSize: this._props.fontSize }}> { // eslint-disable-next-line react/jsx-props-no-spreading diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 31d88fb87..5fe9332f4 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -278,6 +278,9 @@ export class MainView extends ObservableReactComponent<{}> { library.add( ...[ + fa.faSort, + fa.faArrowUpZA, + fa.faArrowDownAZ, fa.faExclamationCircle, fa.faEdit, fa.faArrowDownShortWide, diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index 03e7ed5f3..a2f88eb80 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -37,6 +37,7 @@ import { Func } from 'mocha'; import { CollectionView } from '../CollectionView'; import { listSpec } from '../../../../fields/Schema'; import { GetEffectiveAcl } from '../../../../fields/util'; +import { ContextMenuProps } from '../../ContextMenuItem'; const { SCHEMA_NEW_NODE_HEIGHT } = require('../../global/globalCssVariables.module.scss'); // prettier-ignore @@ -96,6 +97,7 @@ export class CollectionSchemaView extends CollectionSubView() { @observable _colKeysFiltered: boolean = false; @observable _cellTags: ObservableMap = new ObservableMap<Doc, Array<string>>(); @observable _lentDocs: Doc[] = []; + @observable _docs: Doc[] = this.childDocs; // target HTMLelement portal for showing a popup menu to edit cell values. public get MenuTarget() { @@ -195,7 +197,7 @@ export class CollectionSchemaView extends CollectionSubView() { // ViewBoxInterface overrides override isUnstyledView = returnTrue; // used by style provider : turns off opacity, animation effects, scaling - rowIndex = (doc: Doc) => this.sortedDocs.docs.indexOf(doc); + rowIndex = (doc: Doc) => this.displayedDocs.docs.indexOf(doc); @action onKeyDown = (e: KeyboardEvent) => { @@ -205,9 +207,9 @@ export class CollectionSchemaView extends CollectionSubView() { { const lastDoc = this._selectedDocs.lastElement(); const lastIndex = this.rowIndex(lastDoc); - const curDoc = this.sortedDocs.docs[lastIndex]; + const curDoc = this.displayedDocs.docs[lastIndex]; if (lastIndex >= 0 && lastIndex < this.childDocs.length - 1) { - const newDoc = this.sortedDocs.docs[lastIndex + 1]; + const newDoc = this.displayedDocs.docs[lastIndex + 1]; if (this._selectedDocs.includes(newDoc)) { DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc)); this.deselectCell(curDoc); @@ -224,9 +226,9 @@ export class CollectionSchemaView extends CollectionSubView() { { const firstDoc = this._selectedDocs.lastElement(); const firstIndex = this.rowIndex(firstDoc); - const curDoc = this.sortedDocs.docs[firstIndex]; + const curDoc = this.displayedDocs.docs[firstIndex]; if (firstIndex > 0 && firstIndex < this.childDocs.length) { - const newDoc = this.sortedDocs.docs[firstIndex - 1]; + const newDoc = this.displayedDocs.docs[firstIndex - 1]; if (this._selectedDocs.includes(newDoc)) { DocumentView.DeselectView(DocumentView.getFirstDocumentView(curDoc)); this.deselectCell(curDoc); @@ -269,12 +271,6 @@ export class CollectionSchemaView extends CollectionSubView() { @action changeSelectedCellColumn = () => {}; - @undoBatch - setColumnSort = (field: string | undefined, desc: boolean = false) => { - this.layoutDoc.sortField = field; - this.layoutDoc.sortDesc = desc; - }; - addRow = (doc: Doc | Doc[]) => this.addDocument(doc); @undoBatch @@ -512,7 +508,7 @@ export class CollectionSchemaView extends CollectionSubView() { const startRow = Math.min(lastSelectedRow, index); const endRow = Math.max(lastSelectedRow, index); for (let i = startRow; i <= endRow; i++) { - const currDoc = this.sortedDocs.docs[i]; + const currDoc = this.displayedDocs.docs[i]; if (!this._selectedDocs.includes(currDoc)) { this.selectCell(currDoc, this._selectedCol, false, true); } @@ -552,7 +548,7 @@ export class CollectionSchemaView extends CollectionSubView() { this._lowestSelectedIndex = -1; }; - sortedSelectedDocs = () => this.sortedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); + sortedSelectedDocs = () => this.displayedDocs.docs.filter(doc => this._selectedDocs.includes(doc)); @computed get rowDropIndex() { @@ -584,9 +580,8 @@ export class CollectionSchemaView extends CollectionSubView() { const draggedDocs = de.complete.docDragData?.draggedDocuments; if (draggedDocs && super.onInternalDrop(e, de) && !this.sortField) { - const sortedDocs = this.sortedDocs.docs.slice(); -const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs.includes(doc)); - this.dataDoc[this.fieldKey ?? 'data'] = new List<Doc>([...this.sortedDocs.docs]); + const docs = this.displayedDocs.docs.slice(); + this._docs = docs; this.clearSelection(); draggedDocs.forEach(doc => { DocumentView.addViewRenderedCb(doc, dv => dv.select(true)); @@ -639,16 +634,13 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. return undefined; }; - addDocsFromChildCollection = (collection: Doc) => { - const childDocs = DocListCast(collection[Doc.LayoutFieldKey(collection)]); - childDocs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)}); + addDocsFromOtherCollection = (docs: Doc[]) => { + docs.forEach((doc: Doc) => {!this.displayedDocsFunc().includes(doc) && this._lentDocs.push(doc)}); + this._docs = this.childDocs.slice().concat(this._lentDocs); } - - removeChildCollectionDocs = (collection: Doc) => { - const children = DocListCast(collection[Doc.LayoutFieldKey(collection)]); - console.log('before: ' + this._lentDocs) - this._lentDocs.filter((doc: Doc) => !children.includes(doc)); - console.log('after: ' + this._lentDocs) + removeDocsFromOtherCollection = (docs: Doc[]) => { + this._lentDocs.filter((doc: Doc) => !docs.includes(doc)); + this._docs = this.childDocs.slice().concat(this._lentDocs); } @computed get fieldDefaultInput() { @@ -784,27 +776,46 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. this._filterColumnIndex = undefined; }; + @undoBatch + setColumnSort = (field: string | undefined, desc: boolean = false) => { + this.layoutDoc.sortField = field; + this.layoutDoc.sortDesc = desc; + }; + openContextMenu = (x: number, y: number, index: number) => { this.closeColumnMenu(); this.closeFilterMenu(); + const cm = ContextMenu.Instance; + cm.clearItems(); - ContextMenu.Instance.clearItems(); - ContextMenu.Instance.addItem({ + const revealOptions = cm.findByDescription('Sort column') + const sortOptions: ContextMenuProps[] = revealOptions && revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : []; + sortOptions.push({description: 'Sort A-Z', event: () => this.sortDocs(this._docs, this.columnKeys[index], false), icon: 'arrow-down-a-z',}); // prettier-ignore + sortOptions.push({description: 'Sort Z-A', event: () => this.sortDocs(this._docs, this.columnKeys[index], true), icon: 'arrow-up-z-a'}); // prettier-ignore + + cm.addItem({ description: `Change field`, event: () => this.openColumnMenu(index, false), icon: 'pencil-alt', }); - ContextMenu.Instance.addItem({ + cm.addItem({ description: 'Filter field', event: () => this.openFilterMenu(index), icon: 'filter', }); - ContextMenu.Instance.addItem({ + cm.addItem({ + description: 'Sort column', + addDivider: false, + noexpand: true, + subitems: sortOptions, + icon: 'sort' + }); + cm.addItem({ description: 'Delete column', event: () => this.removeColumn(index), icon: 'trash', }); - ContextMenu.Instance.displayMenu(x, y, undefined, false); + cm.displayMenu(x, y, undefined, false); }; @action @@ -1014,34 +1025,33 @@ const filteredChildDocs = sortedDocs.filter((doc: Doc) => !this._lentDocs. } }; - @computed get sortedDocs() { + @computed get displayedDocs() { const draggedDocs = this.isContentActive() ? DragManager.docsBeingDragged : []; - const field = StrCast(this.layoutDoc.sortField); - const desc = BoolCast(this.layoutDoc.sortDesc); // is this an ascending or descending sort - const staticDocs = this.childDocs.filter(d => !draggedDocs.includes(d)).concat(this._lentDocs.filter(d => !draggedDocs.includes(d))); - const docs = !field - ? staticDocs - : [...staticDocs].sort((docA, docB) => { - // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b - const aStr = Field.toString(docA[field] as FieldType); - const bStr = Field.toString(docB[field] as FieldType); - let out = 0; - if (aStr < bStr) out = -1; - if (aStr > bStr) out = 1; - if (desc) out *= -1; - return out; - }); - + const docs = this._docs.filter(d => !draggedDocs.includes(d)); docs.splice(this.rowDropIndex, 0, ...draggedDocs); return { docs }; } + @action + sortDocs = (docs: Doc[], field: string, desc: boolean) => { + docs = docs.sort((docA, docB) => { + // this sorts the documents based on the selected field. returning -1 for a before b, 0 for a = b, 1 for a > b + const aStr = Field.toString(docA[field] as FieldType); + const bStr = Field.toString(docB[field] as FieldType); + let out = 0; + if (aStr < bStr) out = -1; + if (aStr > bStr) out = 1; + if (desc) out *= -1; + return out; + }); + } + rowHeightFunc = () => (BoolCast(this.layoutDoc._schema_singleLine) ? CollectionSchemaView._rowSingleLineHeight : CollectionSchemaView._rowHeight); isContentActive = () => this._props.isSelected() || this._props.isContentActive(); screenToLocal = () => this.ScreenToLocalBoxXf().translate(-this.tableWidth, 0); previewWidthFunc = () => this.previewWidth; onPassiveWheel = (e: WheelEvent) => e.stopPropagation(); - displayedDocsFunc = () => this.sortedDocs.docs; + displayedDocsFunc = () => this.displayedDocs.docs; _oldWheel: any; render() { return ( diff --git a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx index bda9fc9b7..dd4a13776 100644 --- a/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx +++ b/src/client/views/collections/collectionSchema/SchemaColumnHeader.tsx @@ -68,19 +68,6 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea @action updateAlt = (newAlt: string) => {this._altTitle = newAlt;} @action updateKeyDropdown = (value: string) => {this._props.schemaView.updateKeySearch(value)} - @action - sortClicked = (e: React.PointerEvent) => { - e.stopPropagation(); - e.preventDefault(); - if (this._props.sortField === this.fieldKey && this._props.sortDesc) { - this._props.setSort(undefined); - } else if (this._props.sortField === this.fieldKey) { - this._props.setSort(this.fieldKey, true); - } else { - this._props.setSort(this.fieldKey, false); - } - }; - openKeyDropdown = () => { this._props.schemaView.openColumnMenu(this._props.columnIndex, false) } @@ -190,9 +177,6 @@ export class SchemaColumnHeader extends ObservableReactComponent<SchemaColumnHea <div className="schema-header-button" onPointerDown={e => this._props.openContextMenu(e.clientX, e.clientY, this._props.columnIndex)}> <FontAwesomeIcon icon="ellipsis-h" /> </div> - <div className="schema-sort-button" onPointerDown={this.sortClicked} style={this._props.sortField === this.fieldKey ? { backgroundColor: Colors.MEDIUM_BLUE } : {}}> - <FontAwesomeIcon icon="caret-right" style={this._props.sortField === this.fieldKey ? { transform: `rotate(${this._props.sortDesc ? '270deg' : '90deg'})` } : {}} /> - </div> </div> </div> ); diff --git a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx index 099670022..665704de1 100644 --- a/src/client/views/collections/collectionSchema/SchemaRowBox.tsx +++ b/src/client/views/collections/collectionSchema/SchemaRowBox.tsx @@ -7,7 +7,7 @@ import { CgClose, CgLock, CgLockUnlock, CgMenu } from 'react-icons/cg'; import { FaExternalLinkAlt } from 'react-icons/fa'; import { returnFalse, setupMoveUpEvents } from '../../../../ClientUtils'; import { emptyFunction } from '../../../../Utils'; -import { Doc } from '../../../../fields/Doc'; +import { Doc, DocListCast } from '../../../../fields/Doc'; import { BoolCast } from '../../../../fields/Types'; import { Transform } from '../../../util/Transform'; import { undoable } from '../../../util/UndoManager'; @@ -73,13 +73,14 @@ export class SchemaRowBox extends ViewBoxBaseComponent<SchemaRowBoxProps>() { event: () => this._props.addDocTab(this.Document, OpenWhere.addRight), icon: 'magnifying-glass', }); - if (this.Document['type'] === 'collection') { + const childDocs = DocListCast(this.Document[Doc.LayoutFieldKey(this.Document)]) + if (this.Document['type'] === 'collection' && childDocs.length) { ContextMenu.Instance.addItem({ description: this.Document._childrenSharedWithSchema ? 'Remove children from schema' : 'Add children to schema', event: () => { this.Document._childrenSharedWithSchema = !this.Document._childrenSharedWithSchema; this.Document._childrenSharedWithSchema ? - this.schemaView.addDocsFromChildCollection(this.Document) : this.schemaView.removeChildCollectionDocs(this.Document); + this.schemaView.addDocsFromOtherCollection(childDocs) : this.schemaView.removeDocsFromOtherCollection(childDocs); }, icon: this.Document._childrenSharedWithSchema ? 'minus' : 'plus', }); |