From 3b740e1c1ac74e7aac45c136ec9df1b37e2dbc16 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Tue, 23 Jul 2019 16:32:43 -0400 Subject: pretty ui for changing section fitler and added base for colletion chromes --- src/client/views/EditableView.scss | 10 +- src/client/views/EditableView.tsx | 30 +++- .../views/collections/CollectionBaseView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 34 ++++- .../views/collections/CollectionViewChromes.scss | 54 ++++++++ .../views/collections/CollectionViewChromes.tsx | 152 +++++++++++++++++++++ 6 files changed, 268 insertions(+), 14 deletions(-) create mode 100644 src/client/views/collections/CollectionViewChromes.scss create mode 100644 src/client/views/collections/CollectionViewChromes.tsx (limited to 'src') diff --git a/src/client/views/EditableView.scss b/src/client/views/EditableView.scss index a5150cd66..19512362e 100644 --- a/src/client/views/EditableView.scss +++ b/src/client/views/EditableView.scss @@ -1,20 +1,24 @@ -.editableView-container-editing, .editableView-container-editing-oneLine { +.editableView-container-editing, +.editableView-container-editing-oneLine { overflow-wrap: break-word; word-wrap: break-word; hyphens: auto; overflow: hidden; } + .editableView-container-editing-oneLine { span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - display:block; + display: block; } + input { - display:block; + display: block; } } + .editableView-input { width: 100%; background: inherit; diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index f2cdffd38..a5bb40243 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -2,6 +2,7 @@ import React = require('react'); import { observer } from 'mobx-react'; import { observable, action, trace } from 'mobx'; import "./EditableView.scss"; +import * as Autosuggest from 'react-autosuggest'; export interface EditableProps { /** @@ -28,6 +29,13 @@ export interface EditableProps { fontSize?: number; height?: number; display?: string; + autosuggestProps?: { + resetValue: () => void; + value: string, + onChange: (e: React.ChangeEvent, { newValue }: { newValue: string }) => void, + autosuggestProps: Autosuggest.AutosuggestProps + + }; oneLine?: boolean; editing?: boolean; onClick?: (e: React.MouseEvent) => boolean; @@ -85,10 +93,26 @@ export class EditableView extends React.Component { render() { if (this._editing) { - return this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} - style={{ display: this.props.display, fontSize: this.props.fontSize }} />; + return this.props.autosuggestProps + ? this._editing = false), + onPointerDown: this.stopPropagation, + onClick: this.stopPropagation, + onPointerUp: this.stopPropagation, + value: this.props.autosuggestProps.value, + onChange: this.props.autosuggestProps.onChange + }} + /> + : this._editing = false)} onPointerDown={this.stopPropagation} onClick={this.stopPropagation} onPointerUp={this.stopPropagation} + style={{ display: this.props.display, fontSize: this.props.fontSize }} />; } else { + if (this.props.autosuggestProps) this.props.autosuggestProps.resetValue(); return (
void; - children: (type: CollectionViewType, props: CollectionRenderProps) => JSX.Element | JSX.Element[] | null; + children: (type: CollectionViewType, props: CollectionRenderProps) => JSX.Element | JSX.Element[] | null | (JSX.Element | null)[]; className?: string; contentRef?: React.Ref; } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 045c8531e..ba9780c24 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,6 +17,7 @@ import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { StrCast, PromiseValue } from '../../../new_fields/Types'; import { DocumentType } from '../../documents/Documents'; +import { CollectionStackingViewChrome } from './CollectionViewChromes'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh); @@ -33,21 +34,40 @@ library.add(faImage); export class CollectionView extends React.Component { public static LayoutString(fieldStr: string = "data", fieldExt: string = "") { return FieldView.LayoutString(CollectionView, fieldStr, fieldExt); } - private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { + private SubViewHelper = (type: CollectionViewType, renderProps: CollectionRenderProps) => { let props = { ...this.props, ...renderProps }; switch (this.isAnnotationOverlay ? CollectionViewType.Freeform : type) { - case CollectionViewType.Schema: return (); - case CollectionViewType.Docking: return (); - case CollectionViewType.Tree: return (); - case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } - case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } + case CollectionViewType.Schema: return (); + case CollectionViewType.Docking: return (); + case CollectionViewType.Tree: return (); + case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } + case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Freeform: default: - return (); + return (); } return (null); } + private Chrome = (type: CollectionViewType) => { + if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) { + return (null); + } + + switch (type) { + case CollectionViewType.Stacking: return (); + default: + return null; + } + } + + private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => { + return [ + this.Chrome(type), + this.SubViewHelper(type, renderProps) + ] + } + get isAnnotationOverlay() { return this.props.fieldExt ? true : false; } static _applyCount: number = 0; diff --git a/src/client/views/collections/CollectionViewChromes.scss b/src/client/views/collections/CollectionViewChromes.scss new file mode 100644 index 000000000..e5cb1b546 --- /dev/null +++ b/src/client/views/collections/CollectionViewChromes.scss @@ -0,0 +1,54 @@ +@import "../globalCssVariables"; + +.collectionStackingViewChrome { + display: grid; + grid-template-columns: 1fr 1fr; + padding-bottom: 10px; + border-bottom: .5px solid lightgrey; + margin: 10px; + + .collectionStackingViewChrome-sectionFilter-cont { + justify-self: right; + display: flex; + font-size: 75%; + text-transform: uppercase; + letter-spacing: 2px; + + .collectionStackingViewChrome-sectionFilter-label { + vertical-align: center; + padding: 10px; + } + + .collectionStackingViewChrome-sectionFilter { + color: white; + width: fit-content; + text-align: center; + background: rgb(238, 238, 238); + height: 37px; + + .editable-view-input, + input, + .editableView-container-editing-oneLine, + .editableView-container-editing { + padding: 12px 10px 11px 10px; + border: 0px; + color: grey; + text-align: center; + text-transform: uppercase; + letter-spacing: 2px; + outline-color: black; + height: 100%; + } + + .react-autosuggest__container { + margin: 0; + color: grey; + padding: 0px; + } + } + } + + .collectionStackingViewChrome-sectionFilter:hover { + cursor: text; + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx new file mode 100644 index 000000000..ca1480ff2 --- /dev/null +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -0,0 +1,152 @@ +import * as React from "react"; +import { CollectionView } from "./CollectionView"; +import "./CollectionViewChromes.scss"; +import { CollectionViewType } from "./CollectionBaseView"; +import { undoBatch } from "../../util/UndoManager"; +import { action, observable, runInAction, computed } from "mobx"; +import { observer } from "mobx-react"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { DocLike } from "../MetadataEntryMenu"; +const higflyout = require("@hig/flyout"); +export const Flyout = higflyout.default; +import * as Autosuggest from 'react-autosuggest'; +import { EditableView } from "../EditableView"; +import { StrCast } from "../../../new_fields/Types"; + +interface CollectionViewChromeProps { + CollectionView: CollectionView; +} + +class CollectionViewBaseChrome extends React.Component { + @undoBatch + viewChanged = (e: React.ChangeEvent) => { + //@ts-ignore + switch (e.target.selectedOptions[0].value) { + case "freeform": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Freeform; + break; + case "schema": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Schema; + break; + case "treeview": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Tree; + break; + case "stacking": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Stacking; + break; + case "masonry": + this.props.CollectionView.props.Document.viewType = CollectionViewType.Masonry; + break; + default: + break; + } + } + + render() { + return ( +
+ +
+ ) + } +} + +@observer +export class CollectionStackingViewChrome extends React.Component { + @observable private _currentKey: string = ""; + @observable private suggestions: string[] = []; + + @computed get sectionFilter() { return StrCast(this.props.CollectionView.props.Document.sectionFilter); } + + getKeySuggestions = async (value: string): Promise => { + value = value.toLowerCase(); + let docs: Doc | Doc[] | Promise | Promise | (() => DocLike) + = () => DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldExt ? this.props.CollectionView.props.fieldExt : this.props.CollectionView.props.fieldKey]); + if (typeof docs === "function") { + docs = docs(); + } + docs = await docs; + if (docs instanceof Doc) { + return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value)); + } else { + const keys = new Set(); + docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); + return Array.from(keys).filter(key => key.toLowerCase().startsWith(value)); + } + } + + @action + onKeyChange = (e: React.ChangeEvent, { newValue }: { newValue: string }) => { + this._currentKey = newValue; + } + + getSuggestionValue = (suggestion: string) => suggestion; + + renderSuggestion = (suggestion: string) => { + return

{suggestion}

; + } + + onSuggestionFetch = async ({ value }: { value: string }) => { + const sugg = await this.getKeySuggestions(value); + runInAction(() => { + this.suggestions = sugg; + }); + } + + @action + onSuggestionClear = () => { + this.suggestions = []; + } + + setValue = (value: string) => { + this.props.CollectionView.props.Document.sectionFilter = value; + return true; + } + + @action resetValue = () => { this._currentKey = this.sectionFilter; } + + render() { + return ( +
+ +
+
+ Group items by: +
+
+ this.sectionFilter} + autosuggestProps={ + { + resetValue: this.resetValue, + value: this._currentKey, + onChange: this.onKeyChange, + autosuggestProps: { + inputProps: + { + value: this._currentKey, + onChange: this.onKeyChange + }, + getSuggestionValue: this.getSuggestionValue, + suggestions: this.suggestions, + alwaysRenderSuggestions: true, + renderSuggestion: this.renderSuggestion, + onSuggestionsFetchRequested: this.onSuggestionFetch, + onSuggestionsClearRequested: this.onSuggestionClear + } + }} + SetValue={this.setValue} + contents={this.sectionFilter ? this.sectionFilter : "N/A"} + /> +
+
+
+ ) + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2