aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBob Zeleznik <zzzman@gmail.com>2020-07-14 23:55:59 -0400
committerBob Zeleznik <zzzman@gmail.com>2020-07-14 23:55:59 -0400
commit95429adb77402ce2a218c5585ceef4db0c8494db (patch)
tree266de306f27c13494298f3644640b6fefd634797 /src
parent6c96bd6c8ef06e1ecb75ca39a575155dafcc26f1 (diff)
converted collectionChrome into a menu bar
Diffstat (limited to 'src')
-rw-r--r--src/client/views/MainView.tsx6
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx2
-rw-r--r--src/client/views/collections/CollectionMenu.scss475
-rw-r--r--src/client/views/collections/CollectionMenu.tsx443
-rw-r--r--src/client/views/collections/CollectionView.tsx11
5 files changed, 888 insertions, 49 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 428fb835b..95b2dfcdb 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -392,7 +392,7 @@ export class MainView extends React.Component {
doc.dockingConfig ? this.openWorkspace(doc) :
CollectionDockingView.AddRightSplit(doc, libraryPath);
}
- sidebarScreenToLocal = () => new Transform(0, RichTextMenu.Instance.Pinned ? -35 : 0, 1);
+ sidebarScreenToLocal = () => new Transform(0, (RichTextMenu.Instance.Pinned ? -35 : 0) + (InkOptionsMenu.Instance.Pinned ? -35 : 0) + (CollectionMenu.Instance.Pinned ? -35 : 0), 1);
mainContainerXf = () => this.sidebarScreenToLocal().translate(0, -this._buttonBarHeight);
@computed get flyout() {
@@ -469,11 +469,13 @@ export class MainView extends React.Component {
@computed get mainContent() {
const sidebar = this.userDoc?.["tabs-panelContainer"];
+ const n = (RichTextMenu.Instance?.Pinned ? 1 : 0) + (InkOptionsMenu.Instance?.Pinned ? 1 : 0) + (CollectionMenu.Instance?.Pinned ? 1 : 0);
+ const height = `calc(100% - ${n * Number(ANTIMODEMENU_HEIGHT.replace("px", ""))}px)`;
return !this.userDoc || !(sidebar instanceof Doc) ? (null) : (
<div className="mainView-mainContent" style={{
color: this.darkScheme ? "rgb(205,205,205)" : "black",
//change to times 2 for both pinned
- height: (RichTextMenu.Instance?.Pinned || InkOptionsMenu.Instance?.Pinned) ? (RichTextMenu.Instance?.Pinned && InkOptionsMenu.Instance?.Pinned) ? `calc(100% - 2*${ANTIMODEMENU_HEIGHT})` : `calc(100% - ${ANTIMODEMENU_HEIGHT})` : "100%",
+ height,
width: (FormatShapePane.Instance?.Pinned) ? `calc(100% - 200px)` : "100%"
}} >
<div style={{ display: "contents", flexDirection: "row", position: "relative" }}>
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index f408e24a8..657296566 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -436,7 +436,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
const cur = this._containerRef.current;
// bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
- this._goldenLayout && this._goldenLayout.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
+ this._goldenLayout?.updateSize(cur!.getBoundingClientRect().width, cur!.getBoundingClientRect().height);
}
@action
diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss
index 6280670d8..c1a3f9c09 100644
--- a/src/client/views/collections/CollectionMenu.scss
+++ b/src/client/views/collections/CollectionMenu.scss
@@ -1,12 +1,471 @@
-.antimodeMenu-button {
- padding:0;
- width:40px;
+@import "../globalCssVariables";
+
+
+.collectionMenu-cont {
+ position:relative;
+ display:inline-flex;
+ width: 100%;
+ opacity: 0.9;
+ z-index: 9001;
+ transition: top .5s;
+ background: #121721;
+ color: white;
+ transform-origin: top left;
+
+ .antimodeMenu-button {
+ padding:0;
+ width:40px;
+ display: flex;
+ svg {
+ margin:auto;
+ }
+ }
+
+ .collectionViewChrome {
+ display: flex;
+ padding-bottom: 1px;
+ height: 32px;
+ border-bottom: .5px solid rgb(180, 180, 180);
+ overflow: visible;
+ z-index: 9001;
+
+ .collectionViewBaseChrome {
+ display: flex;
+
+ .collectionViewBaseChrome-viewPicker {
+ font-size: 75%;
+ //text-transform: uppercase;
+ //letter-spacing: 2px;
+ background: #121721;
+ color: white;
+ outline-color: black;
+ border: none;
+ //padding: 12px 10px 11px 10px;
+ }
+
+ .collectionViewBaseChrome-viewPicker:active {
+ outline-color: black;
+ }
+
+ .collectionViewBaseChrome-button {
+ font-size: 75%;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ background: rgb(238, 238, 238);
+ color: purple;
+ outline-color: black;
+ border: none;
+ padding: 12px 10px 11px 10px;
+ margin-left: 10px;
+ }
+
+ .collectionViewBaseChrome-cmdPicker {
+ margin-left: 3px;
+ margin-right: 0px;
+ font-size: 75%;
+ background: #121721;
+ border: none;
+ color: white;
+ }
+
+ .commandEntry-outerDiv {
+ pointer-events: all;
+ background-color: #121721;
+ display: flex;
+ flex-direction: row;
+ height: 30px;
+
+ .commandEntry-drop {
+ color: white;
+ width: 30px;
+ margin-top: auto;
+ margin-bottom: auto;
+ }
+ }
+
+ .collectionViewBaseChrome-collapse {
+ transition: all .5s, opacity 0.3s;
+ position: absolute;
+ width: 40px;
+ transform-origin: top left;
+ pointer-events: all;
+ // margin-top: 10px;
+ }
+
+ @media only screen and (max-device-width: 480px) {
+ .collectionViewBaseChrome-collapse {
+ display: none;
+ }
+ }
+
+ .collectionViewBaseChrome-template,
+ .collectionViewBaseChrome-viewModes {
+ display: grid;
+ background: rgb(238, 238, 238);
+ color: grey;
+ margin-top: auto;
+ margin-bottom: auto;
+ }
+ .collectionViewBaseChrome-viewSpecs {
+ margin-left: 5px;
+ display: grid;
+
+ .collectionViewBaseChrome-filterIcon {
+ position: relative;
+ display: flex;
+ margin: auto;
+ background: #121721;
+ color: white;
+ width: 30px;
+ height: 30px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .collectionViewBaseChrome-viewSpecsInput {
+ padding: 12px 10px 11px 10px;
+ border: 0px;
+ color: grey;
+ text-align: center;
+ letter-spacing: 2px;
+ outline-color: black;
+ font-size: 75%;
+ background: rgb(238, 238, 238);
+ height: 100%;
+ width: 75px;
+ }
+
+ .collectionViewBaseChrome-viewSpecsMenu {
+ overflow: hidden;
+ transition: height .5s, display .5s;
+ position: absolute;
+ top: 60px;
+ z-index: 100;
+ display: flex;
+ flex-direction: column;
+ background: rgb(238, 238, 238);
+ box-shadow: grey 2px 2px 4px;
+
+ .qs-datepicker {
+ left: unset;
+ right: 0;
+ }
+
+ .collectionViewBaseChrome-viewSpecsMenu-row {
+ display: grid;
+ grid-template-columns: 150px 200px 150px;
+ margin-top: 10px;
+ margin-right: 10px;
+
+ .collectionViewBaseChrome-viewSpecsMenu-rowLeft,
+ .collectionViewBaseChrome-viewSpecsMenu-rowMiddle,
+ .collectionViewBaseChrome-viewSpecsMenu-rowRight {
+ font-size: 75%;
+ letter-spacing: 2px;
+ color: grey;
+ margin-left: 10px;
+ padding: 5px;
+ border: none;
+ outline-color: black;
+ }
+ }
+
+ .collectionViewBaseChrome-viewSpecsMenu-lastRow {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ grid-gap: 10px;
+ margin: 10px;
+ }
+ }
+ }
+ }
+
+ .collectionStackingViewChrome-cont,
+ .collectionTreeViewChrome-cont,
+ .collection3DCarouselViewChrome-cont {
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .collectionGridViewChrome-cont {
+ display: flex;
+ margin-left: 10;
+
+ .collectionGridViewChrome-viewPicker {
+ font-size: 75%;
+ //text-transform: uppercase;
+ //letter-spacing: 2px;
+ background: #121721;
+ color: white;
+ outline-color: black;
+ border: none;
+ //padding: 12px 10px 11px 10px;
+ }
+
+ .collectionGridViewChrome-viewPicker:active {
+ outline-color: black;
+ }
+
+ .grid-control {
+ align-self: center;
+ display: flex;
+ flex-direction: row;
+ margin-right: 5px;
+
+ .grid-icon {
+ margin-right: 5px;
+ align-self: center;
+ }
+
+ .flexLabel {
+ margin-bottom: 0;
+ }
+ }
+
+ .collectionGridViewChrome-entryBox {
+ width: 50%;
+ }
+ }
+
+
+ .collectionStackingViewChrome-sort,
+ .collectionTreeViewChrome-sort {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .collectionStackingViewChrome-sortIcon,
+ .collectionTreeViewChrome-sortIcon {
+ transition: transform .5s;
+ margin-left: 10px;
+ }
+ }
+
+ button:hover {
+ transform: scale(1);
+ }
+
+
+ .collectionStackingViewChrome-pivotField-cont,
+ .collectionTreeViewChrome-pivotField-cont,
+ .collection3DCarouselViewChrome-scrollSpeed-cont {
+ justify-self: right;
+ display: flex;
+ font-size: 75%;
+ letter-spacing: 2px;
+
+ .collectionStackingViewChrome-pivotField-label,
+ .collectionTreeViewChrome-pivotField-label,
+ .collection3DCarouselViewChrome-scrollSpeed-label {
+ vertical-align: center;
+ padding-left: 10px;
+ margin: auto;
+ }
+
+ .collectionStackingViewChrome-pivotField,
+ .collectionTreeViewChrome-pivotField,
+ .collection3DCarouselViewChrome-scrollSpeed {
+ color: white;
+ width: 100%;
+ min-width: 100px;
+ display: flex;
+ align-items: center;
+ background: rgb(238, 238, 238);
+
+ .editable-view-input,
+ input,
+ .editableView-container-editing-oneLine,
+ .editableView-container-editing {
+ margin: auto;
+ border: 0px;
+ color: grey !important;
+ text-align: center;
+ letter-spacing: 2px;
+ outline-color: black;
+ height: 100%;
+ }
+
+ .react-autosuggest__container {
+ margin: 0;
+ color: grey;
+ padding: 0px;
+ }
+ }
+ }
+
+ .collectionStackingViewChrome-pivotField:hover,
+ .collectionTreeViewChrome-pivotField:hover,
+ .collection3DCarouselViewChrome-scrollSpeed:hover {
+ cursor: text;
+ }
+
+ }
+}
+
+.collectionFreeFormMenu-cont {
+ width: 60px;
display: flex;
- svg {
- margin:auto;
+ position: relative;
+ align-items: center;
+
+ .fwdKeyframe,
+ .numKeyframe,
+ .backKeyframe {
+ cursor: pointer;
+ position: absolute;
+ width: 20;
+ height: 30;
+ bottom: 0;
+ background: #121721;
+ display: flex;
+ align-items: center;
+ color: white;
+ }
+
+ .backKeyframe {
+ left: 0;
+
+ svg {
+ display: block;
+ margin: auto;
+ }
+ }
+
+ .numKeyframe {
+ left: 20;
+ display: flex;
+ flex-direction: column;
+ padding: 5px;
+ }
+
+ .fwdKeyframe {
+ left: 40;
+
+ svg {
+ display: block;
+ margin: auto;
+ }
}
}
-.collectionViewChrome-cont {
- position:relative;
- display:inline-flex;
+
+.collectionSchemaViewChrome-cont {
+ display: flex;
+ font-size: 10.5px;
+
+ .collectionSchemaViewChrome-toggle {
+ display: flex;
+ margin-left: 10px;
+ }
+
+ .collectionSchemaViewChrome-label {
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ margin-right: 5px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ .collectionSchemaViewChrome-toggler {
+ width: 100px;
+ height: 41px;
+ background-color: black;
+ position: relative;
+ }
+
+ .collectionSchemaViewChrome-togglerButton {
+ width: 47px;
+ height: 35px;
+ background-color: $light-color-secondary;
+ // position: absolute;
+ transition: all 0.5s ease;
+ // top: 3px;
+ margin-top: 3px;
+ color: gray;
+ letter-spacing: 2px;
+ text-transform: uppercase;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ text-align: center;
+
+ &.on {
+ margin-left: 3px;
+ }
+
+ &.off {
+ margin-left: 50px;
+ }
+ }
+}
+
+
+.commandEntry-outerDiv {
+ display: flex;
+ flex-direction: column;
+ height: 40px;
+}
+
+.commandEntry-inputArea {
+ display: flex;
+ flex-direction: row;
+ width: 150px;
+ margin: auto auto auto auto;
+}
+
+.react-autosuggest__container {
+ position: relative;
+ width: 100%;
+ margin-left: 5px;
+ margin-right: 5px;
+}
+
+.react-autosuggest__input {
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ width: 100%;
+}
+
+.react-autosuggest__input--focused {
+ outline: none;
+}
+
+.react-autosuggest__input--open {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+
+.react-autosuggest__suggestions-container {
+ display: none;
+}
+
+.react-autosuggest__suggestions-container--open {
+ display: block;
+ position: fixed;
+ overflow-y: auto;
+ max-height: 400px;
+ width: 180px;
+ border: 1px solid #aaa;
+ background-color: #fff;
+ font-family: Helvetica, sans-serif;
+ font-weight: 300;
+ font-size: 16px;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ z-index: 2;
+}
+
+.react-autosuggest__suggestions-list {
+ margin: 0;
+ padding: 0;
+ list-style-type: none;
+}
+
+.react-autosuggest__suggestion {
+ cursor: pointer;
+ padding: 10px 20px;
+}
+
+.react-autosuggest__suggestion--highlighted {
+ background-color: #ddd;
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index d79ffffa1..1644bc726 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -1,19 +1,20 @@
import React = require("react");
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, reaction, runInAction } from "mobx";
+import { action, computed, observable, reaction, runInAction, Lambda } from "mobx";
import { observer } from "mobx-react";
-import { Doc, DocListCast } from "../../../fields/Doc";
+import { Doc, DocListCast, Opt } from "../../../fields/Doc";
import { BoolCast, Cast, StrCast, NumCast } from "../../../fields/Types";
import AntimodeMenu from "../AntimodeMenu";
import "./CollectionMenu.scss";
import { undoBatch } from "../../util/UndoManager";
-import { CollectionViewType, CollectionView } from "./CollectionView";
+import { CollectionViewType, CollectionView, COLLECTION_BORDER_WIDTH } from "./CollectionView";
import { emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils";
-import { CollectionGridViewChrome } from "./CollectionViewChromes";
import { DragManager } from "../../util/DragManager";
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
import { List } from "../../../fields/List";
-import { SelectionManager } from "../../util/SelectionManager";
+import { EditableView } from "../EditableView";
+import { Id } from "../../../fields/FieldSymbols";
+import { listSpec } from "../../../fields/Schema";
@observer
export default class CollectionMenu extends AntimodeMenu {
@@ -33,19 +34,10 @@ export default class CollectionMenu extends AntimodeMenu {
Doc.UserDoc()["menuCollections-pinned"] = this.Pinned = !this.Pinned;
}
- @computed get aButton() {
- return <div className="btn-draw" key="draw">
- <button className="antimodeMenu-button" key="abutton" onClick={() => alert("clicked")} style={{ fontSize: "20" }}>
- <FontAwesomeIcon icon="palette" size="lg" />
- </button>
- </div>;
- }
-
render() {
return this.getElement([
- this.aButton,
!this.SelectedCollection ? <></> : <CollectionViewBaseChrome CollectionView={this.SelectedCollection} type={StrCast(this.SelectedCollection.props.Document._viewType) as CollectionViewType} />,
- <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: this.Pinned ? "#121212" : "" }}>
+ <button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: "#121721" }}>
<FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
</button>
]);
@@ -55,7 +47,6 @@ export default class CollectionMenu extends AntimodeMenu {
interface CollectionViewChromeProps {
CollectionView: CollectionView;
type: CollectionViewType;
- collapse?: (value: boolean) => any;
}
const stopPropagation = (e: React.SyntheticEvent) => e.stopPropagation();
@@ -154,12 +145,12 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
@computed get subChrome() {
switch (this.props.type) {
case CollectionViewType.Freeform: return (<CollectionFreeFormViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
- // case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
- // case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
- // case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
- // case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
- // case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" PanelWidth={this.props.PanelWidth} CollectionView={this.props.CollectionView} type={this.props.type} />);
- // case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Stacking: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Schema: return (<CollectionSchemaViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Tree: return (<CollectionTreeViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Masonry: return (<CollectionStackingViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Carousel3D: return (<Collection3DCarouselViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
+ case CollectionViewType.Grid: return (<CollectionGridViewChrome key="collchrome" CollectionView={this.props.CollectionView} type={this.props.type} />);
default: return null;
}
}
@@ -230,8 +221,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
}
@computed get viewModes() {
- const collapsed = this.props.CollectionView.props.Document._chromeStatus !== "enabled";
- return <div className="collectionViewBaseChrome-viewModes" style={{ display: collapsed ? "none" : undefined }}>
+ return <div className="collectionViewBaseChrome-viewModes" >
<div className="commandEntry-outerDiv" title="drop document to apply or drag to create button" ref={this._viewRef} onPointerDown={this.dragViewDown}>
<div className="commandEntry-drop">
<FontAwesomeIcon icon="bullseye" size="2x" />
@@ -258,7 +248,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
render() {
const scale = Math.min(1, this.props.CollectionView.props.ScreenToLocalTransform()?.Scale);
return (
- <div className="collectionViewChrome-cont" style={{
+ <div className="collectionMenu-cont" style={{
top: 0,
transform: `scale(${scale})`,
width: "100%"
@@ -293,7 +283,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
@undoBatch
@action
nextKeyframe = (): void => {
- const currentFrame = NumCast(this.Document.currentFrame);
+ const currentFrame = Cast(this.Document.currentFrame, "number", null);
if (currentFrame === undefined) {
this.Document.currentFrame = 0;
CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
@@ -305,7 +295,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
@undoBatch
@action
prevKeyframe = (): void => {
- const currentFrame = NumCast(this.Document.currentFrame);
+ const currentFrame = Cast(this.Document.currentFrame, "number", null);
if (currentFrame === undefined) {
this.Document.currentFrame = 0;
CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
@@ -315,7 +305,7 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
}
render() {
return this.Document.isAnnotationOverlay ? (null) :
- <div className="collectionFreeFormViewChrome-cont">
+ <div className="collectionFreeFormMenu-cont">
<div key="back" title="back frame" className="backKeyframe" onClick={this.prevKeyframe}>
<FontAwesomeIcon icon={"caret-left"} size={"lg"} />
</div>
@@ -329,3 +319,400 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
</div>;
}
}
+@observer
+export class CollectionStackingViewChrome extends React.Component<CollectionViewChromeProps> {
+ @observable private _currentKey: string = "";
+ @observable private suggestions: string[] = [];
+
+ @computed private get descending() { return StrCast(this.props.CollectionView.props.Document._columnsSort) === "descending"; }
+ @computed get pivotField() { return StrCast(this.props.CollectionView.props.Document._pivotField); }
+
+ getKeySuggestions = async (value: string): Promise<string[]> => {
+ value = value.toLowerCase();
+ const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]);
+ 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 = [];
+ }
+
+ @action
+ setValue = (value: string) => {
+ this.props.CollectionView.props.Document._pivotField = value;
+ return true;
+ }
+
+ @action toggleSort = () => {
+ this.props.CollectionView.props.Document._columnsSort =
+ this.props.CollectionView.props.Document._columnsSort === "descending" ? "ascending" :
+ this.props.CollectionView.props.Document._columnsSort === "ascending" ? undefined : "descending";
+ }
+ @action resetValue = () => { this._currentKey = this.pivotField; };
+
+ render() {
+ return (
+ <div className="collectionStackingViewChrome-cont">
+ <div className="collectionStackingViewChrome-pivotField-cont">
+ <div className="collectionStackingViewChrome-pivotField-label">
+ GROUP BY:
+ </div>
+ <div className="collectionStackingViewChrome-sortIcon" onClick={this.toggleSort} style={{ transform: `rotate(${this.descending ? "180" : "0"}deg)` }}>
+ <FontAwesomeIcon icon="caret-up" size="2x" color="white" />
+ </div>
+ <div className="collectionStackingViewChrome-pivotField">
+ <EditableView
+ GetValue={() => this.pivotField}
+ 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
+ }
+ }}
+ oneLine
+ SetValue={this.setValue}
+ contents={this.pivotField ? this.pivotField : "N/A"}
+ />
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
+
+
+@observer
+export class CollectionSchemaViewChrome extends React.Component<CollectionViewChromeProps> {
+ // private _textwrapAllRows: boolean = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
+
+ @undoBatch
+ togglePreview = () => {
+ const dividerWidth = 4;
+ const borderWidth = Number(COLLECTION_BORDER_WIDTH);
+ const panelWidth = this.props.CollectionView.props.PanelWidth();
+ const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
+ const tableWidth = panelWidth - 2 * borderWidth - dividerWidth - previewWidth;
+ this.props.CollectionView.props.Document.schemaPreviewWidth = previewWidth === 0 ? Math.min(tableWidth / 3, 200) : 0;
+ }
+
+ @undoBatch
+ @action
+ toggleTextwrap = async () => {
+ const textwrappedRows = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []);
+ if (textwrappedRows.length) {
+ this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>([]);
+ } else {
+ const docs = DocListCast(this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey]);
+ const allRows = docs instanceof Doc ? [docs[Id]] : docs.map(doc => doc[Id]);
+ this.props.CollectionView.props.Document.textwrappedSchemaRows = new List<string>(allRows);
+ }
+ }
+
+
+ render() {
+ const previewWidth = NumCast(this.props.CollectionView.props.Document.schemaPreviewWidth);
+ const textWrapped = Cast(this.props.CollectionView.props.Document.textwrappedSchemaRows, listSpec("string"), []).length > 0;
+
+ return (
+ <div className="collectionSchemaViewChrome-cont">
+ <div className="collectionSchemaViewChrome-toggle">
+ <div className="collectionSchemaViewChrome-label">Show Preview: </div>
+ <div className="collectionSchemaViewChrome-toggler" onClick={this.togglePreview}>
+ <div className={"collectionSchemaViewChrome-togglerButton" + (previewWidth !== 0 ? " on" : " off")}>
+ {previewWidth !== 0 ? "on" : "off"}
+ </div>
+ </div>
+ </div>
+ </div >
+ );
+ }
+}
+
+@observer
+export class CollectionTreeViewChrome extends React.Component<CollectionViewChromeProps> {
+
+ get sortAscending() {
+ return this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"];
+ }
+ set sortAscending(value) {
+ this.props.CollectionView.props.Document[this.props.CollectionView.props.fieldKey + "-sortAscending"] = value;
+ }
+ @computed private get ascending() {
+ return Cast(this.sortAscending, "boolean", null);
+ }
+
+ @action toggleSort = () => {
+ if (this.sortAscending) this.sortAscending = undefined;
+ else if (this.sortAscending === undefined) this.sortAscending = false;
+ else this.sortAscending = true;
+ }
+
+ render() {
+ return (
+ <div className="collectionTreeViewChrome-cont">
+ <button className="collectionTreeViewChrome-sort" onClick={this.toggleSort}>
+ <div className="collectionTreeViewChrome-sortLabel">
+ Sort
+ </div>
+ <div className="collectionTreeViewChrome-sortIcon" style={{ transform: `rotate(${this.ascending === undefined ? "90" : this.ascending ? "180" : "0"}deg)` }}>
+ <FontAwesomeIcon icon="caret-up" size="2x" color="white" />
+ </div>
+ </button>
+ </div>
+ );
+ }
+}
+
+// Enter scroll speed for 3D Carousel
+@observer
+export class Collection3DCarouselViewChrome extends React.Component<CollectionViewChromeProps> {
+ @computed get scrollSpeed() {
+ return this.props.CollectionView.props.Document._autoScrollSpeed;
+ }
+
+ @action
+ setValue = (value: string) => {
+ const numValue = Number(StrCast(value));
+ if (numValue > 0) {
+ this.props.CollectionView.props.Document._autoScrollSpeed = numValue;
+ return true;
+ }
+ return false;
+ }
+
+ render() {
+ return (
+ <div className="collection3DCarouselViewChrome-cont">
+ <div className="collection3DCarouselViewChrome-scrollSpeed-cont">
+ <div className="collectionStackingViewChrome-scrollSpeed-label">
+ AUTOSCROLL SPEED:
+ </div>
+ <div className="collection3DCarouselViewChrome-scrollSpeed">
+ <EditableView
+ GetValue={() => StrCast(this.scrollSpeed)}
+ oneLine
+ SetValue={this.setValue}
+ contents={this.scrollSpeed ? this.scrollSpeed : 1000} />
+ </div>
+ </div>
+ </div>
+ );
+ }
+}
+
+/**
+ * Chrome for grid view.
+ */
+@observer
+export class CollectionGridViewChrome extends React.Component<CollectionViewChromeProps> {
+
+ private clicked: boolean = false;
+ private entered: boolean = false;
+ private decrementLimitReached: boolean = false;
+ @observable private resize = false;
+ private resizeListenerDisposer: Opt<Lambda>;
+
+ componentDidMount() {
+
+ runInAction(() => this.resize = this.props.CollectionView.props.PanelWidth() < 700);
+
+ // listener to reduce text on chrome resize (panel resize)
+ this.resizeListenerDisposer = computed(() => this.props.CollectionView.props.PanelWidth()).observe(({ newValue }) => {
+ runInAction(() => this.resize = newValue < 700);
+ });
+ }
+
+ componentWillUnmount() {
+ this.resizeListenerDisposer?.();
+ }
+
+ get numCols() { return NumCast(this.props.CollectionView.props.Document.gridNumCols, 10); }
+
+ /**
+ * Sets the value of `numCols` on the grid's Document to the value entered.
+ */
+ @undoBatch
+ onNumColsEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ if (e.key === "Enter" || e.key === "Tab") {
+ if (e.currentTarget.valueAsNumber > 0) {
+ this.props.CollectionView.props.Document.gridNumCols = e.currentTarget.valueAsNumber;
+ }
+
+ }
+ }
+
+ /**
+ * Sets the value of `rowHeight` on the grid's Document to the value entered.
+ */
+ // @undoBatch
+ // onRowHeightEnter = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ // if (e.key === "Enter" || e.key === "Tab") {
+ // if (e.currentTarget.valueAsNumber > 0 && this.props.CollectionView.props.Document.rowHeight as number !== e.currentTarget.valueAsNumber) {
+ // this.props.CollectionView.props.Document.rowHeight = e.currentTarget.valueAsNumber;
+ // }
+ // }
+ // }
+
+ /**
+ * Sets whether the grid is flexible or not on the grid's Document.
+ */
+ @undoBatch
+ toggleFlex = () => {
+ this.props.CollectionView.props.Document.gridFlex = !BoolCast(this.props.CollectionView.props.Document.gridFlex, true);
+ }
+
+ /**
+ * Increments the value of numCols on button click
+ */
+ onIncrementButtonClick = () => {
+ this.clicked = true;
+ this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)--;
+ undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1)();
+ this.entered = false;
+ }
+
+ /**
+ * Decrements the value of numCols on button click
+ */
+ onDecrementButtonClick = () => {
+ this.clicked = true;
+ if (!this.decrementLimitReached) {
+ this.entered && (this.props.CollectionView.props.Document.gridNumCols as number)++;
+ undoBatch(() => this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1)();
+ }
+ this.entered = false;
+ }
+
+ /**
+ * Increments the value of numCols on button hover
+ */
+ incrementValue = () => {
+ this.entered = true;
+ if (!this.clicked && !this.decrementLimitReached) {
+ this.props.CollectionView.props.Document.gridNumCols = this.numCols + 1;
+ }
+ this.decrementLimitReached = false;
+ this.clicked = false;
+ }
+
+ /**
+ * Decrements the value of numCols on button hover
+ */
+ decrementValue = () => {
+ this.entered = true;
+ if (!this.clicked) {
+ if (this.numCols !== 1) {
+ this.props.CollectionView.props.Document.gridNumCols = this.numCols - 1;
+ }
+ else {
+ this.decrementLimitReached = true;
+ }
+ }
+
+ this.clicked = false;
+ }
+
+ /**
+ * Toggles the value of preventCollision
+ */
+ toggleCollisions = () => {
+ this.props.CollectionView.props.Document.gridPreventCollision = !this.props.CollectionView.props.Document.gridPreventCollision;
+ }
+
+ /**
+ * Changes the value of the compactType
+ */
+ changeCompactType = (e: React.ChangeEvent<HTMLSelectElement>) => {
+ // need to change startCompaction so that this operation will be undoable.
+ this.props.CollectionView.props.Document.gridStartCompaction = e.target.selectedOptions[0].value;
+ }
+
+ render() {
+ return (
+ <div className="collectionGridViewChrome-cont" >
+ <span className="grid-control" style={{ width: this.resize ? "25%" : "30%" }}>
+ <span className="grid-icon">
+ <FontAwesomeIcon icon="columns" size="1x" />
+ </span>
+ <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.numCols.toString()} onKeyDown={this.onNumColsEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
+ <input className="columnButton" onClick={this.onIncrementButtonClick} onMouseEnter={this.incrementValue} onMouseLeave={this.decrementValue} type="button" value="↑" />
+ <input className="columnButton" style={{ marginRight: 5 }} onClick={this.onDecrementButtonClick} onMouseEnter={this.decrementValue} onMouseLeave={this.incrementValue} type="button" value="↓" />
+ </span>
+ {/* <span className="grid-control">
+ <span className="grid-icon">
+ <FontAwesomeIcon icon="text-height" size="1x" />
+ </span>
+ <input className="collectionGridViewChrome-entryBox" type="number" placeholder={this.props.CollectionView.props.Document.rowHeight as string} onKeyDown={this.onRowHeightEnter} onClick={(e: React.MouseEvent<HTMLInputElement, MouseEvent>) => { e.stopPropagation(); e.preventDefault(); e.currentTarget.focus(); }} />
+ </span> */}
+ <span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
+ <input type="checkbox" style={{ marginRight: 5 }} onChange={this.toggleCollisions} checked={!this.props.CollectionView.props.Document.gridPreventCollision} />
+ <label className="flexLabel">{this.resize ? "Coll" : "Collisions"}</label>
+ </span>
+
+ <select className="collectionGridViewChrome-viewPicker"
+ style={{ marginRight: 5 }}
+ onPointerDown={stopPropagation}
+ onChange={this.changeCompactType}
+ value={StrCast(this.props.CollectionView.props.Document.gridStartCompaction, StrCast(this.props.CollectionView.props.Document.gridCompaction))}>
+ {["vertical", "horizontal", "none"].map(type =>
+ <option className="collectionGridViewChrome-viewOption"
+ onPointerDown={stopPropagation}
+ value={type}>
+ {this.resize ? type[0].toUpperCase() + type.substring(1) : "Compact: " + type}
+ </option>
+ )}
+ </select>
+
+ <span className="grid-control" style={{ width: this.resize ? "12%" : "20%" }}>
+ <input style={{ marginRight: 5 }} type="checkbox" onChange={this.toggleFlex}
+ checked={BoolCast(this.props.CollectionView.props.Document.gridFlex, true)} />
+ <label className="flexLabel">{this.resize ? "Flex" : "Flexible"}</label>
+ </span>
+
+ <button onClick={() => this.props.CollectionView.props.Document.gridResetLayout = true}>
+ {!this.resize ? "Reset" :
+ <FontAwesomeIcon icon="redo-alt" size="1x" />}
+ </button>
+
+ </div>
+ );
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index e18fe319e..6cd6a827f 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -47,7 +47,6 @@ import { SubCollectionViewProps } from './CollectionSubView';
import { CollectionTimeView } from './CollectionTimeView';
import { CollectionTreeView } from "./CollectionTreeView";
import './CollectionView.scss';
-import { CollectionViewBaseChrome } from './CollectionViewChromes';
import CollectionMenu from './CollectionMenu';
const higflyout = require("@hig/flyout");
export const { anchorPoints } = higflyout;
@@ -235,16 +234,8 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
}
}
- @action
- private collapse = (value: boolean) => {
- this.props.Document._chromeStatus = value ? "collapsed" : "enabled";
- }
-
private SubView = (type: CollectionViewType, renderProps: CollectionRenderProps) => {
- // currently cant think of a reason for collection docking view to have a chrome. mind may change if we ever have nested docking views -syip
- const chrome = this.props.Document._chromeStatus === "disabled" || this.props.Document._chromeStatus === "replaced" || type === CollectionViewType.Docking ? (null) :
- <CollectionViewBaseChrome key="chrome" CollectionView={this} PanelWidth={this.bodyPanelWidth} type={type} collapse={this.collapse} />;
- return <>{chrome} {this.SubViewHelper(type, renderProps)}</>;
+ return this.SubViewHelper(type, renderProps);
}