diff options
-rw-r--r-- | src/client/views/ContextMenu.tsx | 50 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.scss | 17 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 14 | ||||
-rw-r--r-- | src/client/views/Main.scss | 2 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.scss | 4 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/search/SearchBox.scss | 5 | ||||
-rw-r--r-- | src/client/views/search/SearchBox.tsx | 21 | ||||
-rw-r--r-- | views/stylesheets/authentication.css | 6 |
10 files changed, 104 insertions, 20 deletions
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 1bf6e383d..760736501 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from "./ContextMenuItem"; -import { observable, action, computed } from "mobx"; +import { observable, action, computed, runInAction, IReactionDisposer, reaction } from "mobx"; import { observer } from "mobx-react"; import "./ContextMenu.scss"; import { library } from '@fortawesome/fontawesome-svg-core'; @@ -27,6 +27,13 @@ export class ContextMenu extends React.Component { @observable private _width: number = 0; @observable private _height: number = 0; + @observable private _mouseX: number = -1; + @observable private _mouseY: number = -1; + @observable private _shouldDisplay: boolean = false; + @observable private _mouseDown: boolean = false; + + private _reactionDisposer?: IReactionDisposer; + constructor(props: Readonly<{}>) { super(props); @@ -34,6 +41,40 @@ export class ContextMenu extends React.Component { } @action + onPointerDown = (e: PointerEvent) => { + this._mouseDown = true; + this._mouseX = e.clientX; + this._mouseY = e.clientY; + } + @action + onPointerUp = (e: PointerEvent) => { + this._mouseDown = false; + let curX = e.clientX; + let curY = e.clientY; + if (this._mouseX !== curX || this._mouseY !== curY) { + this._shouldDisplay = false; + } + + this._shouldDisplay && (this._display = true); + } + componentWillUnmount() { + document.removeEventListener("pointerdown", this.onPointerDown); + document.removeEventListener("pointerup", this.onPointerUp); + this._reactionDisposer && this._reactionDisposer(); + } + + @action + componentDidMount = () => { + document.addEventListener("pointerdown", this.onPointerDown); + document.addEventListener("pointerup", this.onPointerUp); + + this._reactionDisposer = reaction( + () => this._shouldDisplay, + () => this._shouldDisplay && !this._mouseDown && runInAction(() => this._display = true) + ); + } + + @action clearItems() { this._items = []; } @@ -83,22 +124,21 @@ export class ContextMenu extends React.Component { } @action - displayMenu(x: number, y: number) { + displayMenu = (x: number, y: number) => { //maxX and maxY will change if the UI/font size changes, but will work for any amount //of items added to the menu this._pageX = x; this._pageY = y; - this._searchString = ""; - - this._display = true; + this._shouldDisplay = true; } @action closeMenu = () => { this.clearItems(); this._display = false; + this._shouldDisplay = false; } @computed get filteredItems(): (OriginalMenuProps | string[])[] { diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index 0b7411fca..3627edaae 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -24,13 +24,13 @@ $linkGap : 3px; .documentDecorations-resizer { pointer-events: auto; background: $alt-accent; - opacity: 0.8; + opacity: 1; } .documentDecorations-radius { pointer-events: auto; background: black; - opacity: 0.8; + opacity: 1; transform: translate(10px, 10px); grid-row: 4; } @@ -92,27 +92,30 @@ $linkGap : 3px; .title { background: $alt-accent; + opacity: 1; grid-column-start: 3; grid-column-end: 4; pointer-events: auto; overflow: hidden; + text-align: center; } } .documentDecorations-closeButton { background: $alt-accent; - opacity: 0.8; + opacity: 1; grid-column-start: 4; grid-column-end: 6; pointer-events: all; text-align: center; cursor: pointer; + padding-right: 10px; } .documentDecorations-minimizeButton { background: $alt-accent; - opacity: 0.8; + opacity: 1; grid-column-start: 1; grid-column-end: 3; pointer-events: all; @@ -121,6 +124,7 @@ $linkGap : 3px; position: absolute; left: 0px; top: 0px; + padding-top: 5px; width: $MINIMIZED_ICON_SIZE; height: $MINIMIZED_ICON_SIZE; } @@ -219,6 +223,11 @@ $linkGap : 3px; margin-top: 3px; } +.documentdecorations-times { + margin-top: 3px; + padding-right: 3px; +} + .templating-button, .docDecs-tagButton { width: 20px; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index df526e01c..d24762443 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,5 +1,5 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faLink, faTag } from '@fortawesome/free-solid-svg-icons'; +import { faLink, faTag, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; @@ -36,6 +36,7 @@ export const Flyout = higflyout.default; library.add(faLink); library.add(faTag); +library.add(faTimes); @observer export class DocumentDecorations extends React.Component<{}, { value: string }> { @@ -65,6 +66,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> @observable private _opacity = 1; @observable private _removeIcon = false; @observable public Interacting = false; + @observable private _isMoving = false; constructor(props: Readonly<{}>) { super(props); @@ -346,9 +348,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> document.addEventListener("pointermove", this.onRadiusMove); document.addEventListener("pointerup", this.onRadiusUp); } + if (!this._isMoving) { + SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplate ? dv.props.Document : Doc.GetProto(dv.props.Document)). + map(d => d.borderRounding = "0%"); + } } onRadiusMove = (e: PointerEvent): void => { + this._isMoving = true; let dist = Math.sqrt((e.clientX - this._radiusDown[0]) * (e.clientX - this._radiusDown[0]) + (e.clientY - this._radiusDown[1]) * (e.clientY - this._radiusDown[1])); SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplate ? dv.props.Document : Doc.GetProto(dv.props.Document)). map(d => d.borderRounding = `${Math.min(100, dist)}%`); @@ -361,6 +368,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> e.preventDefault(); this._isPointerDown = false; this._resizeUndo && this._resizeUndo.end(); + this._isMoving = false; document.removeEventListener("pointermove", this.onRadiusMove); document.removeEventListener("pointerup", this.onRadiusUp); } @@ -743,7 +751,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> {this._edtingTitle ? <input ref={this.keyinput} className="title" type="text" name="dynbox" value={this._title} onBlur={this.titleBlur} onChange={this.titleChanged} onKeyPress={this.titleEntered} /> : <div className="title" onPointerDown={this.onTitleDown} ><span>{`${this.selectionTitle}`}</span></div>} - <div className="documentDecorations-closeButton" title="Close Document" onPointerDown={this.onCloseDown}>X</div> + <div className="documentDecorations-closeButton" title="Close Document" onPointerDown={this.onCloseDown}> + <FontAwesomeIcon className="documentdecorations-times" icon={faTimes} size="lg" /> + </div> <div id="documentDecorations-topLeftResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> <div id="documentDecorations-topResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> <div id="documentDecorations-topRightResizer" className="documentDecorations-resizer" onPointerDown={this.onPointerDown} onContextMenu={(e) => e.preventDefault()}></div> diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index f76abaff3..a0b4b2f16 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -140,6 +140,8 @@ button:hover { // font-size: 8px; // user-select: none; // } + margin-top: -2.55px; + margin-left: -2.55px; } // add nodes menu. Note that the + button is actually an input label, not an actual button. diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 110d47941..00a9c0950 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -38,6 +38,7 @@ import { PreviewCursor } from './PreviewCursor'; import { FilterBox } from './search/FilterBox'; import { CollectionTreeView } from './collections/CollectionTreeView'; import { ClientUtils } from '../util/ClientUtils'; +import { SearchBox } from './search/SearchBox'; import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField'; import { DictationManager } from '../util/DictationManager'; @@ -538,7 +539,7 @@ export class MainView extends React.Component { } @observable isSearchVisible = false; - @action + @action.bound toggleSearch = () => { // console.log("search toggling") this.isSearchVisible = !this.isSearchVisible; diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 247f7d1ea..d86aab09c 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -33,8 +33,8 @@ } .formattedTextBox-inner-rounded { - height: calc(100% - 25px); - width: calc(100% - 40px); + height: calc(90%); + width: calc(85%); position: absolute; overflow: auto; top: 15; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 516e36d5b..330bd135d 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -616,7 +616,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let dh = NumCast(this.props.Document.height, 0); let sh = scrBounds.height; const ChromeHeight = MainOverlayTextBox.Instance.ChromeHeight; - this.props.Document.height = (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0); + this.props.Document.height = Math.max(10, (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0)); this.dataDoc.nativeHeight = nh ? sh : undefined; } } diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index fcdc79220..5ed33a596 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -37,6 +37,11 @@ margin-left: 2px; margin-right: 2px } + + &.searchBox-close { + color: $light-color; + max-height: 32px; + } } } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 2214ac8af..4dc409e77 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -4,6 +4,8 @@ import { observable, action, runInAction, flow, computed } from 'mobx'; import "./SearchBox.scss"; import "./FilterBox.scss"; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faTimes } from '@fortawesome/free-solid-svg-icons'; +import { library } from '@fortawesome/fontawesome-svg-core'; import { SetupDrag } from '../../util/DragManager'; import { Docs } from '../../documents/Documents'; import { NumCast, Cast } from '../../../new_fields/Types'; @@ -14,8 +16,12 @@ import { Id } from '../../../new_fields/FieldSymbols'; import { SearchUtil } from '../../util/SearchUtil'; import { RouteStore } from '../../../server/RouteStore'; import { FilterBox } from './FilterBox'; +import { ReadStream } from 'fs'; +import * as $ from 'jquery'; +import { MainView } from '../MainView'; import { Utils } from '../../../Utils'; +library.add(faTimes); @observer export class SearchBox extends React.Component { @@ -29,6 +35,7 @@ export class SearchBox extends React.Component { @observable private _visibleElements: JSX.Element[] = []; private resultsRef = React.createRef<HTMLDivElement>(); + public inputRef = React.createRef<HTMLInputElement>(); private _isSearch: ("search" | "placeholder" | undefined)[] = []; private _numTotalResults = -1; @@ -46,6 +53,15 @@ export class SearchBox extends React.Component { this.resultsScrolled = this.resultsScrolled.bind(this); } + componentDidMount = () => { + if (this.inputRef.current) { + this.inputRef.current.focus(); + runInAction(() => { + this._searchbarOpen = true; + }); + } + } + @action getViews = async (doc: Doc) => { const results = await SearchUtil.GetViewsOfDocument(doc); @@ -229,6 +245,7 @@ export class SearchBox extends React.Component { @action.bound closeSearch = () => { + console.log("closing search") FilterBox.Instance.closeFilter(); this.closeResults(); this._searchbarOpen = false; @@ -321,11 +338,12 @@ export class SearchBox extends React.Component { <span className="searchBox-barChild searchBox-collection" onPointerDown={SetupDrag(this.collectionRef, this.startDragCollection)} ref={this.collectionRef} title="Drag Results as Collection"> <FontAwesomeIcon icon="object-group" size="lg" /> </span> - <input value={this._searchString} onChange={this.onChange} type="text" placeholder="Search..." + <input value={this._searchString} onChange={this.onChange} type="text" placeholder="Search..." id="search-input" ref={this.inputRef} className="searchBox-barChild searchBox-input" onPointerDown={this.openSearch} onKeyPress={this.enter} style={{ width: this._searchbarOpen ? "500px" : "100px" }} /> <button className="searchBox-barChild searchBox-submit" onClick={this.submitSearch} onPointerDown={FilterBox.Instance.stopProp}>Submit</button> <button className="searchBox-barChild searchBox-filter" onClick={FilterBox.Instance.openFilter} onPointerDown={FilterBox.Instance.stopProp}>Filter</button> + <button className="searchBox-barChild searchBox-close" title={"Close Search Bar"} onPointerDown={MainView.Instance.toggleSearch}><FontAwesomeIcon icon={faTimes} size="lg" /></button> </div> <div className="searchBox-results" onScroll={this.resultsScrolled} style={{ display: this._resultsOpen ? "flex" : "none", @@ -336,5 +354,4 @@ export class SearchBox extends React.Component { </div> ); } - }
\ No newline at end of file diff --git a/views/stylesheets/authentication.css b/views/stylesheets/authentication.css index dea0474e4..36bb880af 100644 --- a/views/stylesheets/authentication.css +++ b/views/stylesheets/authentication.css @@ -69,10 +69,10 @@ body { .workspaceId { list-style-type: none; - font-family: Arial, Helvetica, sans-serif; + font-family: Arial, Helvetica, sans-serif; margin-left: -20px; cursor: grab; - padding-bottom: 15px; + padding-bottom: 15px; } .workspaceId:hover { @@ -106,7 +106,7 @@ body { } .overlay { - border: 2px solid yellow; + border: 2px gray; text-align: center; position: absolute; margin: auto; |