aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/EditableView.scss10
-rw-r--r--src/client/views/EditableView.tsx30
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx2
-rw-r--r--src/client/views/collections/CollectionView.tsx34
-rw-r--r--src/client/views/collections/CollectionViewChromes.scss54
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx152
6 files changed, 268 insertions, 14 deletions
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<string>
+
+ };
oneLine?: boolean;
editing?: boolean;
onClick?: (e: React.MouseEvent) => boolean;
@@ -85,10 +93,26 @@ export class EditableView extends React.Component<EditableProps> {
render() {
if (this._editing) {
- return <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus
- onBlur={action(() => 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
+ ? <Autosuggest
+ {...this.props.autosuggestProps.autosuggestProps}
+ inputProps={{
+ className: "editableView-input",
+ onKeyDown: this.onKeyDown,
+ autoFocus: true,
+ onBlur: action(() => this._editing = false),
+ onPointerDown: this.stopPropagation,
+ onClick: this.stopPropagation,
+ onPointerUp: this.stopPropagation,
+ value: this.props.autosuggestProps.value,
+ onChange: this.props.autosuggestProps.onChange
+ }}
+ />
+ : <input className="editableView-input" defaultValue={this.props.GetValue()} onKeyDown={this.onKeyDown} autoFocus
+ onBlur={action(() => 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 (
<div className={`editableView-container-editing${this.props.oneLine ? "-oneLine" : ""}`}
style={{ display: this.props.display, height: "auto", maxHeight: `${this.props.height}` }}
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 72faf52c4..4cdbd8554 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -32,7 +32,7 @@ export interface CollectionRenderProps {
export interface CollectionViewProps extends FieldViewProps {
onContextMenu?: (e: React.MouseEvent) => 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<HTMLDivElement>;
}
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<FieldViewProps> {
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 (<CollectionSchemaView {...props} CollectionView={this} />);
- case CollectionViewType.Docking: return (<CollectionDockingView {...props} CollectionView={this} />);
- case CollectionViewType.Tree: return (<CollectionTreeView {...props} CollectionView={this} />);
- case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (<CollectionStackingView {...props} CollectionView={this} />); }
- case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (<CollectionStackingView {...props} CollectionView={this} />); }
+ case CollectionViewType.Schema: return (<CollectionSchemaView key="collview" {...props} CollectionView={this} />);
+ case CollectionViewType.Docking: return (<CollectionDockingView key="collview" {...props} CollectionView={this} />);
+ case CollectionViewType.Tree: return (<CollectionTreeView key="collview" {...props} CollectionView={this} />);
+ case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (<CollectionStackingView key="collview" {...props} CollectionView={this} />); }
+ case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (<CollectionStackingView key="collview" {...props} CollectionView={this} />); }
case CollectionViewType.Freeform:
default:
- return (<CollectionFreeFormView {...props} CollectionView={this} />);
+ return (<CollectionFreeFormView key="collview" {...props} CollectionView={this} />);
}
return (null);
}
+ private Chrome = (type: CollectionViewType) => {
+ if (this.isAnnotationOverlay || this.props.Document === CurrentUserUtils.UserDocument.sidebar) {
+ return (null);
+ }
+
+ switch (type) {
+ case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this} />);
+ 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<CollectionViewChromeProps> {
+ @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 (
+ <div className="collectionViewBaseChrome">
+ <select onChange={this.viewChanged}>
+ <option value="freeform" selected={this.props.CollectionView.props.Document.viewType === CollectionViewType.Freeform}>Freeform View</option>
+ <option value="schema" selected={this.props.CollectionView.props.Document.viewType === CollectionViewType.Schema}>Schema View</option>
+ <option value="treeview" selected={this.props.CollectionView.props.Document.viewType === CollectionViewType.Tree}>Tree View</option>
+ <option value="stacking" selected={this.props.CollectionView.props.Document.viewType === CollectionViewType.Stacking}>Stacking View</option>
+ <option value="masonry" selected={this.props.CollectionView.props.Document.viewType === CollectionViewType.Masonry}>Masonry View</option>
+ </select>
+ </div>
+ )
+ }
+}
+
+@observer
+export class CollectionStackingViewChrome extends React.Component<CollectionViewChromeProps> {
+ @observable private _currentKey: string = "";
+ @observable private suggestions: string[] = [];
+
+ @computed get sectionFilter() { return StrCast(this.props.CollectionView.props.Document.sectionFilter); }
+
+ getKeySuggestions = async (value: string): Promise<string[]> => {
+ value = value.toLowerCase();
+ let docs: Doc | Doc[] | Promise<Doc> | Promise<Doc[]> | (() => 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<string>();
+ 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 <p>{suggestion}</p>;
+ }
+
+ 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 (
+ <div className="collectionStackingViewChrome">
+ <CollectionViewBaseChrome CollectionView={this.props.CollectionView} />
+ <div className="collectionStackingViewChrome-sectionFilter-cont">
+ <div className="collectionStackingViewChrome-sectionFilter-label">
+ Group items by:
+ </div>
+ <div className="collectionStackingViewChrome-sectionFilter">
+ <EditableView
+ GetValue={() => 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"}
+ />
+ </div>
+ </div>
+ </div>
+ )
+ }
+} \ No newline at end of file