From 9505eda799fdf3b0cd2e6bde2d80c18731caee2c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 10 Oct 2019 21:36:26 -0400 Subject: switching sidebar to a stacking view... --- src/server/authentication/models/current_user_utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 0fbfbf2f3..f3d5555ed 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -99,7 +99,7 @@ export class CurrentUserUtils { } if (doc.sidebar === undefined) { - const sidebar = Docs.Create.StackingDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); + const sidebar = Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); sidebar.forceActive = true; sidebar.lockedPosition = true; sidebar.gridGap = 5; -- cgit v1.2.3-70-g09d2 From a73a72586c72cd620c16dd7bc0baad88c8e49a34 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 11 Oct 2019 01:38:48 -0400 Subject: switching search around to left-hand side. --- src/client/documents/DocumentTypes.ts | 3 +- src/client/documents/Documents.ts | 10 +++++ src/client/views/GlobalKeyHandler.ts | 4 ++ src/client/views/MainView.tsx | 10 +++-- .../views/collections/CollectionTreeView.tsx | 5 ++- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/QueryBox.scss | 0 src/client/views/nodes/QueryBox.tsx | 50 ++++++++++++++++++++++ src/client/views/search/FilterBox.tsx | 4 +- src/client/views/search/IconBar.tsx | 14 ------ src/client/views/search/SearchBox.scss | 17 ++++++-- src/client/views/search/SearchBox.tsx | 2 - src/client/views/search/SearchItem.scss | 39 +++++++---------- src/client/views/search/SearchItem.tsx | 19 +++----- .../authentication/models/current_user_utils.ts | 6 +++ 15 files changed, 120 insertions(+), 66 deletions(-) create mode 100644 src/client/views/nodes/QueryBox.scss create mode 100644 src/client/views/nodes/QueryBox.tsx (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index e5d5885cd..7abaa4043 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -20,5 +20,6 @@ export enum DocumentType { DRAGBOX = "dragbox", PRES = "presentation", LINKFOLLOW = "linkfollow", - PRESELEMENT = "preselement" + PRESELEMENT = "preselement", + QUERY = "search", } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0114f82d8..7f6ab50d8 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -45,6 +45,7 @@ import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; import { PresElementBox } from "../views/presentationview/PresElementBox"; +import { QueryBox } from "../views/nodes/QueryBox"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -62,6 +63,7 @@ export interface DocumentOptions { panY?: number; page?: number; scale?: number; + fitWidth?: boolean; layout?: string | Doc; isTemplate?: boolean; templates?: List; @@ -119,6 +121,10 @@ export namespace Docs { layout: { view: HistogramBox, collectionView: [CollectionView, data] as CollectionViewType }, options: { height: 300, backgroundColor: "black" } }], + [DocumentType.QUERY, { + layout: { view: QueryBox }, + options: { width: 400, fitWidth: true } + }], [DocumentType.IMG, { layout: { view: ImageBox, ext: anno }, options: {} @@ -374,6 +380,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.HIST), new HistogramField(histoOp), options); } + export function QueryDocument(options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options); + } + export function TextDocument(options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options); } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index c519991a5..6815ff926 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -7,6 +7,8 @@ import { action, runInAction } from "mobx"; import { Doc } from "../../new_fields/Doc"; import { DictationManager } from "../util/DictationManager"; import SharingManager from "../util/SharingManager"; +import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; +import { Cast, PromiseValue } from "../../new_fields/Types"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -162,6 +164,8 @@ export default class KeyManager { break; case "f": MainView.Instance.isSearchVisible = !MainView.Instance.isSearchVisible; + MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0))); break; case "o": let target = SelectionManager.SelectedDocuments()[0]; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ba4224875..1ec21f638 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -12,7 +12,7 @@ import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; import { List } from '../../new_fields/List'; import { listSpec } from '../../new_fields/Schema'; -import { BoolCast, Cast, FieldValue, StrCast } from '../../new_fields/Types'; +import { BoolCast, Cast, FieldValue, StrCast, PromiseValue } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; @@ -463,7 +463,7 @@ export class MainView extends React.Component { return (null); } return : null, + //this.isSearchVisible ?
: null, ]; } @@ -648,7 +648,9 @@ export class MainView extends React.Component { @observable isSearchVisible = false; @action.bound toggleSearch = () => { - this.isSearchVisible = !this.isSearchVisible; + this.isSearchVisible = !MainView.Instance.isSearchVisible; + MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0))); } @computed private get dictationOverlay() { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 37eb151b1..6f5587b5a 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -260,7 +260,10 @@ class TreeView extends React.Component { let aspect = NumCast(this.props.document.nativeHeight) / NumCast(this.props.document.nativeWidth); if (aspect) return this.docWidth() * aspect; if (bounds) return this.docWidth() * (bounds.b - bounds.y) / (bounds.r - bounds.x); - return NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50; + return this.props.document.fitWidth ? (!this.props.document.nativeHeight ? NumCast(this.props.containingCollection.height) : + Math.min(this.docWidth() * NumCast(this.props.document.scrollHeight, NumCast(this.props.document.nativeHeight)) / NumCast(this.props.document.nativeWidth, + NumCast(this.props.containingCollection.height)))) : + NumCast(this.props.document.height) ? NumCast(this.props.document.height) : 50; })()); } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index e4b2ecffd..d4e7c6d4e 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -24,6 +24,7 @@ import { ImageBox } from "./ImageBox"; import { KeyValueBox } from "./KeyValueBox"; import { PDFBox } from "./PDFBox"; import { PresBox } from "./PresBox"; +import { QueryBox } from "./QueryBox"; import { PresElementBox } from "../presentationview/PresElementBox"; import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; @@ -99,7 +100,7 @@ export class DocumentContentsView extends React.Component { + public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(QueryBox, fieldKey); } + _docListChangedReaction: IReactionDisposer | undefined; + componentDidMount() { + } + + componentWillUnmount() { + this._docListChangedReaction && this._docListChangedReaction(); + } + + render() { + return
+ +
+ } +} \ No newline at end of file diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index da733d64b..b841190d4 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -33,7 +33,7 @@ export enum Keys { export class FilterBox extends React.Component { static Instance: FilterBox; - public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.HIST, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB]; + public _allIcons: string[] = [DocumentType.AUDIO, DocumentType.COL, DocumentType.IMG, DocumentType.LINK, DocumentType.PDF, DocumentType.TEXT, DocumentType.VID, DocumentType.WEB]; //if true, any keywords can be used. if false, all keywords are required. //this also serves as an indicator if the word status filter is applied @@ -393,7 +393,7 @@ export class FilterBox extends React.Component {
- {this.getActiveFilters()} + {/* {this.getActiveFilters()} */}
{this._filterOpen ? (
diff --git a/src/client/views/search/IconBar.tsx b/src/client/views/search/IconBar.tsx index c9924222f..bdeb57d5c 100644 --- a/src/client/views/search/IconBar.tsx +++ b/src/client/views/search/IconBar.tsx @@ -59,23 +59,9 @@ export class IconBar extends React.Component { render() { return (
-
-
- -
-
Select All
-
{FilterBox.Instance._allIcons.map((type: string) => )} -
-
- -
-
Clear
-
); } diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 0dd4d3dc5..bc11604a5 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -1,6 +1,15 @@ @import "../globalCssVariables"; @import "./NaviconButton.scss"; +.searchBox-container { + display: flex; + flex-direction: column; + width:100%; + height:100%; + position: absolute; + font-size: 10px; + line-height: 1; +} .searchBox-bar { height: 32px; display: flex; @@ -49,17 +58,17 @@ } .searchBox-quickFilter { - width: 500px; - margin-left: 25px; + width: 100%; + height: 40px; margin-top: 10px; } .searchBox-results { - margin-right: 136px; + display:flex; + flex-direction: column; top: 300px; display: flex; flex-direction: column; - margin-right: 72px; // height: 560px; height: 100%; // overflow: hidden; diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index be75a29e0..62c8c255e 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -346,8 +346,6 @@ export class SearchBox extends React.Component { className="searchBox-barChild searchBox-input" onPointerDown={this.openSearch} onKeyPress={this.enter} onFocus={this.openSearch} style={{ width: this._searchbarOpen ? "500px" : "100px" }} /> - -
{(this._numTotalResults > 0 || !this._searchbarOpen) ? (null) : (
diff --git a/src/client/views/search/SearchItem.scss b/src/client/views/search/SearchItem.scss index 62715c5eb..9f12994c3 100644 --- a/src/client/views/search/SearchItem.scss +++ b/src/client/views/search/SearchItem.scss @@ -2,19 +2,27 @@ .search-overview { display: flex; - flex-direction: row-reverse; + flex-direction: reverse; justify-content: flex-end; z-index: 0; } +.link-count { + background: black; + border-radius: 20px; + color: white; + width: 15px; + text-align: center; + margin-top: 5px; +} .searchBox-placeholder, .search-overview .search-item { - width: 500px; + width: 100%; background: $light-color-secondary; border-color: $intermediate-color; border-bottom-style: solid; padding: 10px; - min-height: 70px; + min-height: 50px; max-height: 150px; height: auto; z-index: 0; @@ -61,16 +69,6 @@ overflow: hidden; position: relative; - .link-count { - opacity: 1; - position: absolute; - z-index: 1000; - text-align: center; - -webkit-transition: opacity 0.2s ease-in-out; - -moz-transition: opacity 0.2s ease-in-out; - -o-transition: opacity 0.2s ease-in-out; - transition: opacity 0.2s ease-in-out; - } .link-extended { // display: none; @@ -112,7 +110,7 @@ .icon-icons, .icon-live { - height: 50px; + height: auto; margin: auto; overflow: hidden; @@ -174,9 +172,7 @@ .searchBox-instances:active { opacity: 1; background: $lighter-alt-accent; - -webkit-transform: scale(1); - -ms-transform: scale(1); - transform: scale(1); + width:150px } .search-item:hover { @@ -193,13 +189,10 @@ .searchBox-instances { float: left; opacity: 1; - width: 150px; + width: 0px; transition: all 0.2s ease; color: black; - transform-origin: top right; - -webkit-transform: scale(0); - -ms-transform: scale(0); - transform: scale(0); + overflow: hidden; } @@ -208,7 +201,7 @@ } .searchBox-placeholder { - min-height: 70px; + min-height: 50px; margin-left: 150px; text-transform: uppercase; text-align: left; diff --git a/src/client/views/search/SearchItem.tsx b/src/client/views/search/SearchItem.tsx index a7822ed46..b8cff16f2 100644 --- a/src/client/views/search/SearchItem.tsx +++ b/src/client/views/search/SearchItem.tsx @@ -213,15 +213,6 @@ export class SearchItem extends React.Component { @computed get linkCount() { return LinkManager.Instance.getAllRelatedLinks(this.props.doc).length; } - @computed - get linkString(): string { - let num = this.linkCount; - if (num === 1) { - return num.toString() + " link"; - } - return num.toString() + " links"; - } - @action pointerDown = (e: React.PointerEvent) => { e.preventDefault(); e.button === 0 && SearchBox.Instance.openSearch(e); } @@ -290,7 +281,11 @@ export class SearchItem extends React.Component {
-
+
+
+
{this.linkCount}
+
+
{StrCast(this.props.doc.title)}
{this.props.highlighting.length ? "Matched fields:" + this.props.highlighting.join(", ") : this.props.lines.length ? this.props.lines[0] : ""}
@@ -301,10 +296,6 @@ export class SearchItem extends React.Component {
{this.DocumentIcon()}
{this.props.doc.type ? this.props.doc.type : "Other"}
-
-
{this.linkCount}
-
{this.linkString}
-
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index f3d5555ed..32da29932 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -97,6 +97,12 @@ export class CurrentUserUtils { curPresentation.boxShadow = "0 0"; doc.curPresentation = curPresentation; } + if (doc.searchBox === undefined) { + const searchBox = Docs.Create.QueryDocument({ title: "Searching" }); + searchBox.boxShadow = "0 0"; + searchBox.ignoreClick = true; + doc.searchBox = searchBox; + } if (doc.sidebar === undefined) { const sidebar = Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Sidebar" }); -- cgit v1.2.3-70-g09d2 From 11f1fc68532bb75a231b7b697ccd6e5007a2b3f1 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 11 Oct 2019 08:36:44 -0400 Subject: fixed notifications bell when docs are shared. --- src/server/authentication/models/current_user_utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index f3d5555ed..e486ee727 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -46,7 +46,7 @@ export class CurrentUserUtils { // setup workspaces library item if (doc.workspaces === undefined) { - const workspaces = Docs.Create.TreeDocument([], { title: "Workspaces".toUpperCase(), height: 100 }); + const workspaces = Docs.Create.TreeDocument([], { title: "WORKSPACES", height: 100 }); workspaces.boxShadow = "0 0"; doc.workspaces = workspaces; } @@ -106,6 +106,7 @@ export class CurrentUserUtils { sidebar.xMargin = 5; sidebar.yMargin = 5; sidebar.boxShadow = "1 1 3"; + sidebar.workspaceLibrary = true; // flag that this is the document that shows the Notifications button when documents are shared doc.sidebar = sidebar; } PromiseValue(Cast(doc.sidebar, Doc)).then(sidebar => { -- cgit v1.2.3-70-g09d2 From 3afceef2f8c2be1bddf67cecd97086a41ec6dc48 Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 11 Oct 2019 16:47:42 -0400 Subject: changes to menu layouts --- src/client/documents/Documents.ts | 2 + src/client/views/GlobalKeyHandler.ts | 30 +++++- src/client/views/Main.tsx | 5 - src/client/views/MainView.tsx | 108 +++++++++++++-------- .../collections/CollectionMasonryViewFieldRow.tsx | 2 +- .../CollectionStackingViewFieldColumn.tsx | 4 +- src/client/views/nodes/ButtonBox.scss | 2 + src/client/views/nodes/DragBox.tsx | 4 +- src/client/views/nodes/IconBox.tsx | 4 +- src/client/views/search/IconBar.tsx | 2 +- src/client/views/search/IconButton.scss | 2 +- .../authentication/models/current_user_utils.ts | 73 +++++++++++--- 12 files changed, 167 insertions(+), 71 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7f6ab50d8..6b56fb443 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -74,6 +74,7 @@ export interface DocumentOptions { dropAction?: dropActionType; backgroundLayout?: string; chromeStatus?: string; + columnWidth?: number; fontSize?: number; curPage?: number; currentTimecode?: number; @@ -83,6 +84,7 @@ export interface DocumentOptions { dockingConfig?: string; autoHeight?: boolean; dbDoc?: Doc; + icon?: string; // [key: string]: Opt; } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 557b3e366..9d239d0bf 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -9,6 +9,7 @@ import { DictationManager } from "../util/DictationManager"; import SharingManager from "../util/SharingManager"; import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; import { Cast, PromiseValue } from "../../new_fields/Types"; +import { ScriptField } from "../../new_fields/ScriptField"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; @@ -162,12 +163,31 @@ export default class KeyManager { } } break; + case "c": + if (MainView.Instance.flyoutWidth > 0) { + MainView.Instance.flyoutWidth = 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } else { + MainView.Instance.flyoutWidth = 400; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Create, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } + break; + case "l": + if (MainView.Instance.flyoutWidth > 0) { + MainView.Instance.flyoutWidth = 0; + } else { + MainView.Instance.flyoutWidth = 400; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } + break; case "f": - stopPropagation = false; - preventDefault = false; - MainView.Instance.isSearchVisible = !MainView.Instance.isSearchVisible; - MainView.Instance.flyoutWidth = MainView.Instance.isSearchVisible ? 400 : 0; - PromiseValue(Cast(CurrentUserUtils.UserDocument.searchBox, Doc)).then(pv => pv && (pv.treeViewOpen = (MainView.Instance.flyoutWidth > 0))); + if (MainView.Instance.flyoutWidth > 0) { + MainView.Instance.flyoutWidth = 0; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Library, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } else { + MainView.Instance.flyoutWidth = 400; + PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); + } break; case "o": let target = SelectionManager.SelectedDocuments()[0]; diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 3bd898ac0..a91a2b69e 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -38,11 +38,6 @@ let swapDocs = async () => { if (info.id !== "__guest__") { // a guest will not have an id registered await CurrentUserUtils.loadUserDocument(info); - // updates old user documents to prevent chrome on tree view. - (await Cast(CurrentUserUtils.UserDocument.workspaces, Doc))!.chromeStatus = "disabled"; - (await Cast(CurrentUserUtils.UserDocument.recentlyClosed, Doc))!.chromeStatus = "disabled"; - (await Cast(CurrentUserUtils.UserDocument.sidebar, Doc))!.chromeStatus = "disabled"; - CurrentUserUtils.UserDocument.chromeStatus = "disabled"; await swapDocs(); } document.getElementById('root')!.addEventListener('wheel', event => { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 1ec21f638..6f60de1c4 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -15,7 +15,7 @@ import { listSpec } from '../../new_fields/Schema'; import { BoolCast, Cast, FieldValue, StrCast, PromiseValue } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse, Utils } from '../../Utils'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; import { ClientUtils } from '../util/ClientUtils'; @@ -40,6 +40,8 @@ import { PreviewCursor } from './PreviewCursor'; import { FilterBox } from './search/FilterBox'; import { OverlayView } from './OverlayView'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; +import { CollectionStackingView } from './collections/CollectionStackingView'; +import { ScriptField } from '../../new_fields/ScriptField'; @observer export class MainView extends React.Component { @@ -459,33 +461,63 @@ export class MainView extends React.Component { @computed get flyout() { let sidebar: FieldResult; - if (!this.userDoc || !((sidebar = this.userDoc.sidebar) instanceof Doc)) { + if (!this.userDoc || !((sidebar = this.userDoc.sidebarContainer) instanceof Doc)) { return (null); } - return - ; + (Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc).columnWidth = this.flyoutWidthFunc() / 3 - 30; + return
+
+ + +
+
+ + +
; } @computed @@ -493,7 +525,7 @@ export class MainView extends React.Component { if (!this.userDoc) { return (
{this.dockingContent}
); } - let sidebar = this.userDoc.sidebar; + let sidebar = this.userDoc.sidebarContainer; if (!(sidebar instanceof Doc)) { return (null); } @@ -585,16 +617,16 @@ export class MainView extends React.Component { // let googlePhotosSearch = () => GooglePhotosClientUtils.CollectionFromSearch(Docs.Create.MasonryDocument, { included: [GooglePhotosClientUtils.ContentCategories.LANDSCAPES] }); let btns: [React.RefObject, IconName, string, () => Doc | Promise][] = [ - [React.createRef(), "object-group", "Add Collection", addColNode], - [React.createRef(), "tv", "Add Presentation Trail", addPresNode], - [React.createRef(), "globe-asia", "Add Website", addWebNode], - [React.createRef(), "bolt", "Add Button", addButtonDocument], - [React.createRef(), "file", "Add Document Dragger", addDragboxNode], + //[React.createRef(), "object-group", "Add Collection", addColNode], + //[React.createRef(), "tv", "Add Presentation Trail", addPresNode], + //[React.createRef(), "globe-asia", "Add Website", addWebNode], + //[React.createRef(), "bolt", "Add Button", addButtonDocument], + //[React.createRef(), "file", "Add Document Dragger", addDragboxNode], // [React.createRef(), "object-group", "Test Google Photos Search", googlePhotosSearch], - [React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode + //[React.createRef(), "cloud-upload-alt", "Import Directory", addImportCollectionNode], //remove at some point in favor of addImportCollectionNode //[React.createRef(), "play", "Add Youtube Searcher", addYoutubeSearcher], ]; - if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); + //if (!ClientUtils.RELEASE) btns.unshift([React.createRef(), "cat", "Add Cat Image", addImageNode]); return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > @@ -603,7 +635,7 @@ export class MainView extends React.Component {
    -
  • + {/*
  • */}
  • {btns.map(btn => @@ -612,7 +644,7 @@ export class MainView extends React.Component {
)} -
  • + {/*
  • */}
  • */} -
  • -
  • - {btns.map(btn => -
  • - -
  • )} - {/*
  • */} -
  • -
  • -
  • -
  • -
  • -
  • -
  • - + {/*
  • */} + + + + {DocListCast(CurrentUserUtils.UserDocument.docButtons).map(doc =>
    + 35 / NumCast(doc.nativeWidth, 35)} + PanelWidth={() => 35} + PanelHeight={() => 35} + renderDepth={0} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} + {/*
  • */} + + + + + + +
    ; } @@ -668,16 +674,6 @@ export class MainView extends React.Component { this._colorPickerDisplay = close ? false : !this._colorPickerDisplay; } - /* @TODO this should really be moved into a moveable toolbar component, but for now let's put it here to meet the deadline */ - @computed - get miscButtons() { - return [ - //this.isSearchVisible ?
    : null, - ]; - - } - - @observable isSearchVisible = false; @action.bound toggleSearch = () => { PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); @@ -716,7 +712,6 @@ export class MainView extends React.Component { {this.nodesMenu()} - {this.miscButtons} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 6f5587b5a..a325e86c6 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -188,7 +188,7 @@ class TreeView extends React.Component { onWorkspaceContextMenu = (e: React.MouseEvent): void => { if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 - if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) { + if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking && this.props.document !== CurrentUserUtils.UserDocument.workspaces) { ContextMenu.Instance.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.document), icon: "tv" }); ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "inTab"), icon: "folder" }); ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, this.resolvedDataDoc, "onRight"), icon: "caret-square-right" }); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.scss b/src/client/views/nodes/CollectionFreeFormDocumentView.scss index c0d9e1267..af9232c2f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.scss +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.scss @@ -2,4 +2,6 @@ transform-origin: left top; position: absolute; background-color: transparent; + top:0; + left:0; } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 758222e52..20920a9b8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -614,6 +614,7 @@ export class DocumentView extends DocComponent(Docu DataDoc={this.props.DataDoc} />); } render() { + if (!this.props.Document) return (null); let animDims = this.props.Document.animateToDimensions ? Array.from(Cast(this.props.Document.animateToDimensions, listSpec("number"))!) : undefined; const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined; const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined; diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx index 8429382e3..ab3368b94 100644 --- a/src/client/views/nodes/DragBox.tsx +++ b/src/client/views/nodes/DragBox.tsx @@ -51,9 +51,15 @@ export class DragBox extends DocComponent(DragDocu const onDragStart = this.Document.onDragStart; e.stopPropagation(); e.preventDefault(); - let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; - let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); - DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY); + DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([this.props.Document]), e.clientX, e.clientY, { + finishDrag: (dropData) => { + let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; + let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); + dropData.droppedDocuments = [doc]; + }, + handlers: { dragComplete: emptyFunction }, + hideSource: false + }); } e.stopPropagation(); e.preventDefault(); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 02a82e0ed..63b412a23 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -93,7 +93,7 @@ export class PDFBox extends DocAnnotatableComponent if (e.key === "PageUp" || e.key === "ArrowUp" || e.key === "ArrowLeft") { this.backPage(); } - }) + }); @undoBatch @action diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index e1bb91838..7408fd92b 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -127,46 +127,38 @@ export class CurrentUserUtils { Search.targetContainer = doc.sidebarContainer; Search.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.searchBox"); - let createCollection = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Collection", icon: "folder" }); - let createWebPage = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Web Page", icon: "globe-asia" }); + let createCollection = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); + let createWebPage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); - let createCatImage = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Image", icon: "cat" }); + let createCatImage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })'); - let createButton = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Button", icon: "bolt" }); + let createButton = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); - let createPresentation = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Presentation", icon: "tv" }); + let createPresentation = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); createPresentation.onDragStart = ScriptField.MakeFunction('Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })'); - let createFolderImport = Docs.Create.DragboxDocument({ width: 35, height: 35, title: "Import Folder", icon: "cloud-upload-alt" }); + let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); const creators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, height: 50, columnWidth: 35, chromeStatus: "disabled", title: "buttons" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); - const buttons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" }); - buttons.sectionFilter = "title"; - buttons.boxShadow = "0 0"; - buttons.ignoreClick = true; - buttons.hideHeadings = true; - doc.libraryButtons = buttons; + const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" }); + libraryButtons.sectionFilter = "title"; + libraryButtons.boxShadow = "0 0"; + libraryButtons.ignoreClick = true; + libraryButtons.hideHeadings = true; + libraryButtons.backgroundColor = "lightgrey"; + doc.libraryButtons = libraryButtons; doc.Library = Library; doc.Create = Create; doc.Search = Search; - (Library.onClick as ScriptField).script.run({ this: Library }); - //(doc.sidebarContainer as Doc).proto = library; } - PromiseValue(Cast(doc.libraryButtons, Doc)).then(libraryButtons => { - if (libraryButtons) { - libraryButtons.backgroundColor = "lightgrey"; - } - }); - - PromiseValue(Cast(doc.sidebar, Doc)).then(sidebar => { - if (sidebar) { - sidebar.backgroundColor = "lightgrey"; - } - }); + PromiseValue(Cast(doc.libraryButtons, Doc)).then(libraryButtons => { }); + PromiseValue(Cast(doc.Library, Doc)).then(library => library && library.library && library.targetContainer && (library.onClick as ScriptField).script.run({ this: library })); + PromiseValue(Cast(doc.Create, Doc)).then(async create => create && create.creators && create.targetContainer); + PromiseValue(Cast(doc.Search, Doc)).then(async search => search && search.searchBox && search.targetContainer); if (doc.overlays === undefined) { const overlays = Docs.Create.FreeformDocument([], { title: "Overlays" }); @@ -178,8 +170,7 @@ export class CurrentUserUtils { PromiseValue(Cast(doc.overlays, Doc)).then(overlays => overlays && Doc.AddDocToList(overlays, "data", doc.linkFollowBox = Docs.Create.LinkFollowBoxDocument({ x: 250, y: 20, width: 500, height: 370, title: "Link Follower" }))); } - StrCast(doc.title).indexOf("@") !== -1 && (doc.title = (StrCast(doc.title).split("@")[0] + "'s Library").toUpperCase()); - StrCast(doc.title).indexOf("'s Library") !== -1 && (doc.title = StrCast(doc.title).toUpperCase()); + doc.title = "DOCUMENTS"; doc.backgroundColor = "#eeeeee"; doc.width = 100; doc.preventTreeViewOpen = true; -- cgit v1.2.3-70-g09d2 From 34a8b9dd402a247e7ad0a57115935b1e3a04a8d3 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 12:25:02 -0400 Subject: cleaned up notifs and bottom menu icons --- src/client/views/Main.scss | 21 +++----- src/client/views/MainView.tsx | 57 +++++++++------------- src/client/views/MainViewNotifs.scss | 18 +++++++ src/client/views/MainViewNotifs.tsx | 32 ++++++++++++ .../views/collections/CollectionTreeView.tsx | 26 +--------- .../authentication/models/current_user_utils.ts | 1 - 6 files changed, 79 insertions(+), 76 deletions(-) create mode 100644 src/client/views/MainViewNotifs.scss create mode 100644 src/client/views/MainViewNotifs.tsx (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index 705da7b35..debb941c8 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -93,21 +93,6 @@ button:hover { right: 0px; } -.main-notifs-badge { - position: absolute; - top: -10px; - right: -10px; - color: white; - background: #f44b42; - font-weight: 300; - border-radius: 100%; - width: 25px; - height: 25px; - text-align: center; - padding-top: 4px; - font-size: 12px; -} - //toolbar stuff #toolbar { position: absolute; @@ -237,6 +222,12 @@ ul#add-options-list { padding: 0; } } +.mainView-logout { + position: absolute; + right: 0; + bottom: 0; + font-size: 8px; +} .mainView-libraryFlyout { height: 100%; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 1fa231659..e8ffa5987 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -16,7 +16,7 @@ import { ScriptField } from '../../new_fields/ScriptField'; import { BoolCast, Cast, FieldValue, PromiseValue, StrCast, NumCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils, returnFalse } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; @@ -40,6 +40,7 @@ import { OverlayView } from './OverlayView'; import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; +import { MainViewNotifs } from './MainViewNotifs'; @observer export class MainView extends React.Component { @@ -47,6 +48,7 @@ export class MainView extends React.Component { @observable addMenuToggle = React.createRef(); @observable public pwidth: number = 0; @observable public pheight: number = 0; + private _buttonBarHeight = 85; private dropDisposer?: DragManager.DragDropDisposer; @observable private dictationState = DictationManager.placeholder; @@ -138,24 +140,6 @@ export class MainView extends React.Component { firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag); window.removeEventListener("keydown", KeyManager.Instance.handle); window.addEventListener("keydown", KeyManager.Instance.handle); - - if (this.userDoc) { - reaction(() => { - let workspaces = this.userDoc.workspaces; - let recent = this.userDoc.recentlyClosed; - if (!(recent instanceof Doc)) return 0; - if (!(workspaces instanceof Doc)) return 0; - let workspacesDoc = workspaces; - let recentDoc = recent; - let libraryHeight = this.getPHeight() - workspacesDoc[HeightSym]() - recentDoc[HeightSym]() - 20 + this.userDoc[HeightSym]() * 0.00001; - return libraryHeight; - }, (libraryHeight: number) => { - if (libraryHeight && Math.abs(this.userDoc[HeightSym]() - libraryHeight) > 5) { - this.userDoc.height = libraryHeight; - } - (Cast(this.userDoc.recentlyClosed, Doc) as Doc).allowClear = true; - }, { fireImmediately: true }); - } } componentWillUnMount() { @@ -340,7 +324,7 @@ export class MainView extends React.Component { if (this.userDoc && (col = await Cast(this.userDoc.optionalRightCollection, Doc))) { const l = Cast(col.data, listSpec(Doc)); if (l) { - runInAction(() => CollectionTreeView.NotifsCol = col); + runInAction(() => MainViewNotifs.NotifsCol = col); } } }, 100); @@ -349,7 +333,7 @@ export class MainView extends React.Component { drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc)); - }) + }); onDrop = (e: React.DragEvent) => { e.preventDefault(); @@ -368,6 +352,9 @@ export class MainView extends React.Component { getPHeight = () => { return this.pheight; } + getContentsHeight = () => { + return this.pheight - this._buttonBarHeight; + } @observable flyoutWidth: number = 250; @observable flyoutTranslate: boolean = true; @@ -465,12 +452,12 @@ export class MainView extends React.Component { if (!(sidebarContent instanceof Doc)) { return (null); } - (Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc).columnWidth = this.flyoutWidthFunc() / 3 - 30; - let buttonBarHeight = 85; + let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; + libraryButtonDoc.columnWidth = this.flyoutWidthFunc() / 3 - 30; return
    -
    +
    -
    +
    +
    ; } @computed get mainContent() { - if (!this.userDoc) { - return (
    {this.dockingContent}
    ); - } - let sidebar = this.userDoc.sidebarContainer; - if (!(sidebar instanceof Doc)) { + let sidebar = this.userDoc && this.userDoc.sidebarContainer; + if (!this.userDoc || !(sidebar instanceof Doc)) { return (null); } return ( @@ -617,6 +604,7 @@ export class MainView extends React.Component { return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > + @@ -632,7 +620,7 @@ export class MainView extends React.Component { addDocument={undefined} addDocTab={this.addDocTabFunc} pinToPres={emptyFunction} - removeDocument={undefined} + removeDocument={(doc: Doc) => Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc)} ruleProvider={undefined} onClick={undefined} ScreenToLocalTransform={Transform.Identity} @@ -662,7 +650,6 @@ export class MainView extends React.Component { -
    ; } diff --git a/src/client/views/MainViewNotifs.scss b/src/client/views/MainViewNotifs.scss new file mode 100644 index 000000000..25ec95643 --- /dev/null +++ b/src/client/views/MainViewNotifs.scss @@ -0,0 +1,18 @@ +.mainNotifs-container { + position:absolute; + + .mainNotifs-badge { + position: absolute; + top: -10px; + right: -10px; + color: white; + background: #f44b42; + font-weight: 300; + border-radius: 100%; + width: 25px; + height: 25px; + text-align: center; + padding-top: 4px; + font-size: 12px; + } +} \ No newline at end of file diff --git a/src/client/views/MainViewNotifs.tsx b/src/client/views/MainViewNotifs.tsx new file mode 100644 index 000000000..09fa1cb0c --- /dev/null +++ b/src/client/views/MainViewNotifs.tsx @@ -0,0 +1,32 @@ +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import "normalize.css"; +import * as React from 'react'; +import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; +import { emptyFunction } from '../../Utils'; +import { SetupDrag } from '../util/DragManager'; +import "./MainViewNotifs.scss"; +import { CollectionDockingView } from './collections/CollectionDockingView'; + + +@observer +export class MainViewNotifs extends React.Component { + + @observable static NotifsCol: Opt; + openNotifsCol = () => { + if (MainViewNotifs.NotifsCol) { + CollectionDockingView.AddRightSplit(MainViewNotifs.NotifsCol, undefined); + } + } + render() { + const length = MainViewNotifs.NotifsCol ? DocListCast(MainViewNotifs.NotifsCol.data).length : 0; + const notifsRef = React.createRef(); + const dragNotifs = action(() => MainViewNotifs.NotifsCol!); + return
    + +
    ; + } +} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index a325e86c6..abaa9662c 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -517,8 +517,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; - @observable static NotifsCol: Opt; - @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } protected createTreeDropTarget = (ele: HTMLDivElement) => { @@ -557,31 +555,10 @@ export class CollectionTreeView extends CollectionSubView(Document) { } outerXf = () => Utils.GetScreenTransform(this._mainEle!); onTreeDrop = (e: React.DragEvent) => this.onDrop(e, {}); - openNotifsCol = () => { - if (CollectionTreeView.NotifsCol) { - this.props.addDocTab(CollectionTreeView.NotifsCol, undefined, "onRight"); - } - } - @computed get renderNotifsButton() { - const length = CollectionTreeView.NotifsCol ? DocListCast(CollectionTreeView.NotifsCol.data).length : 0; - const notifsRef = React.createRef(); - const dragNotifs = action(() => CollectionTreeView.NotifsCol!); - return
    -
    - -
    0 ? { "display": "initial" } : { "display": "none" }}> - {length} -
    -
    -
    ; - } @computed get renderClearButton() { return
    - @@ -614,7 +591,6 @@ export class CollectionTreeView extends CollectionSubView(Document) { TreeView.loadId = doc[Id]; Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc, this.childDocs.length ? this.childDocs[0] : undefined, true, false, false, false); })} /> - {this.props.Document.workspaceLibrary ? this.renderNotifsButton : (null)} {this.props.Document.allowClear ? this.renderClearButton : (null)}
      { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 7408fd92b..874f49f10 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -115,7 +115,6 @@ export class CurrentUserUtils { library.xMargin = 5; library.yMargin = 5; library.boxShadow = "1 1 3"; - library.workspaceLibrary = true; // flag that this is the document that shows the Notifications button when documents are shared Library.targetContainer = doc.sidebarContainer; Library.library = library; Library.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.library"); -- cgit v1.2.3-70-g09d2 From 8910a2649a1b2edea9843df1b780937ad0e69fb5 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 13:09:53 -0400 Subject: color picker as document in sidebar now. --- src/client/documents/DocumentTypes.ts | 1 + src/client/documents/Documents.ts | 10 ++++++++++ src/client/util/DocumentManager.ts | 6 ++---- src/client/views/GlobalKeyHandler.ts | 4 ++-- src/client/views/MainView.tsx | 7 +------ src/client/views/nodes/ColorBox.scss | 10 ++++++++++ src/client/views/nodes/ColorBox.tsx | 16 ++++++++++++++++ src/client/views/nodes/DocumentContentsView.tsx | 7 ++++++- src/client/views/nodes/QueryBox.tsx | 19 ++----------------- .../authentication/models/current_user_utils.ts | 4 +++- 10 files changed, 53 insertions(+), 31 deletions(-) create mode 100644 src/client/views/nodes/ColorBox.scss create mode 100644 src/client/views/nodes/ColorBox.tsx (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 7abaa4043..dad2de0b5 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -22,4 +22,5 @@ export enum DocumentType { LINKFOLLOW = "linkfollow", PRESELEMENT = "preselement", QUERY = "search", + COLOR = "color", } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6b56fb443..e783848ff 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -46,6 +46,7 @@ import { DocumentType } from "./DocumentTypes"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; import { PresElementBox } from "../views/presentationview/PresElementBox"; import { QueryBox } from "../views/nodes/QueryBox"; +import { ColorBox } from "../views/nodes/ColorBox"; var requestImageSize = require('../util/request-image-size'); var path = require('path'); @@ -69,6 +70,7 @@ export interface DocumentOptions { templates?: List; viewType?: number; backgroundColor?: string; + ignoreClick?: boolean; opacity?: number; defaultBackgroundColor?: string; dropAction?: dropActionType; @@ -127,6 +129,10 @@ export namespace Docs { layout: { view: QueryBox }, options: { width: 400, fitWidth: true } }], + [DocumentType.COLOR, { + layout: { view: ColorBox }, + options: { nativeWidth: 220, nativeHeight: 300 } + }], [DocumentType.IMG, { layout: { view: ImageBox, ext: anno }, options: {} @@ -386,6 +392,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.QUERY), "", options); } + export function ColorDocument(options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options); + } + export function TextDocument(options: DocumentOptions = {}) { return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 24285a70a..00de39671 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,16 +1,14 @@ -import { action, computed, observable, trace } from 'mobx'; +import { action, computed, observable } from 'mobx'; import { Doc, DocListCastAsync } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; +import { List } from '../../new_fields/List'; import { Cast, NumCast, StrCast } from '../../new_fields/Types'; import { CollectionDockingView } from '../views/collections/CollectionDockingView'; import { CollectionView } from '../views/collections/CollectionView'; import { DocumentView } from '../views/nodes/DocumentView'; import { LinkManager } from './LinkManager'; -import { undoBatch, UndoManager } from './UndoManager'; import { Scripting } from './Scripting'; -import { List } from '../../new_fields/List'; import { SelectionManager } from './SelectionManager'; -import { notDeepEqual } from 'assert'; export class DocumentManager { diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 82f5a573c..f3e1933d7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -165,10 +165,10 @@ export default class KeyManager { break; case "c": PromiseValue(Cast(CurrentUserUtils.UserDocument.Create, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); - if (MainView.Instance.flyoutWidth === 75) { + if (MainView.Instance.flyoutWidth === 240) { MainView.Instance.flyoutWidth = 0; } else { - MainView.Instance.flyoutWidth = 75; + MainView.Instance.flyoutWidth = 240; } break; case "l": diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e8ffa5987..cc412a609 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -5,7 +5,6 @@ import { action, computed, configure, observable, reaction, runInAction } from ' import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; -import { SketchPicker } from 'react-color'; import Measure from 'react-measure'; import { Doc, DocListCast, Field, FieldResult, HeightSym, Opt } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; @@ -640,11 +639,7 @@ export class MainView extends React.Component {
    )} {/*
  • */} - + diff --git a/src/client/views/nodes/ColorBox.scss b/src/client/views/nodes/ColorBox.scss new file mode 100644 index 000000000..8df617fca --- /dev/null +++ b/src/client/views/nodes/ColorBox.scss @@ -0,0 +1,10 @@ +.colorBox-container { + width:100%; + height:100%; + position: relative; + pointer-events:all; + + .sketch-picker { + margin:auto; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx new file mode 100644 index 000000000..4aff770f9 --- /dev/null +++ b/src/client/views/nodes/ColorBox.tsx @@ -0,0 +1,16 @@ +import React = require("react"); +import { observer } from "mobx-react"; +import { SketchPicker } from 'react-color'; +import { FieldView, FieldViewProps } from './FieldView'; +import "./ColorBox.scss"; +import { InkingControl } from "../InkingControl"; + +@observer +export class ColorBox extends React.Component { + public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(ColorBox, fieldKey); } + render() { + return
    + +
    ; + } +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index d4e7c6d4e..f2a581c42 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -25,6 +25,7 @@ import { KeyValueBox } from "./KeyValueBox"; import { PDFBox } from "./PDFBox"; import { PresBox } from "./PresBox"; import { QueryBox } from "./QueryBox"; +import { ColorBox } from "./ColorBox"; import { PresElementBox } from "../presentationview/PresElementBox"; import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; @@ -100,7 +101,11 @@ export class DocumentContentsView extends React.Component(), { width: 200, height: 500, title: "a presentation trail" })'); let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); - const creators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, height: 50, columnWidth: 35, chromeStatus: "disabled", title: "buttons" }); + const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); + const color = Docs.Create.ColorDocument({ title: "color picker", width: 400, ignoreClick: true }); + const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }) Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); -- cgit v1.2.3-70-g09d2 From ed89b0fbf26c5bf4263198938dae07e6f32ab436 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 13:43:13 -0400 Subject: a few more tweaks and now the bottom buttons are customizable --- src/client/views/MainView.tsx | 11 ++++++++++- src/client/views/nodes/DragBox.tsx | 5 +++-- src/new_fields/Doc.ts | 1 + src/server/authentication/models/current_user_utils.ts | 4 ++-- 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index cc412a609..18e5052b7 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,6 +40,7 @@ import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; import { MainViewNotifs } from './MainViewNotifs'; +import { DocumentType } from '../documents/DocumentTypes'; @observer export class MainView extends React.Component { @@ -331,7 +332,15 @@ export class MainView extends React.Component { } drop = action((e: Event, de: DragManager.DropEvent) => { - (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc)); + (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { + if (doc.type !== DocumentType.DRAGBOX) { + let dbox = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + dbox.factory = doc; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)'); + doc = dbox; + } + Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); + }); }); onDrop = (e: React.DragEvent) => { diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx index ab3368b94..4fca96382 100644 --- a/src/client/views/nodes/DragBox.tsx +++ b/src/client/views/nodes/DragBox.tsx @@ -44,7 +44,7 @@ export class DragBox extends DocComponent(DragDocu } } - onDragMove = (e: MouseEvent) => { + onDragMove = async (e: MouseEvent) => { if (!e.cancelBubble && (Math.abs(this._downX - e.clientX) > 5 || Math.abs(this._downY - e.clientY) > 5)) { document.removeEventListener("pointermove", this.onDragMove); document.removeEventListener("pointerup", this.onDragUp); @@ -52,7 +52,7 @@ export class DragBox extends DocComponent(DragDocu e.stopPropagation(); e.preventDefault(); DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([this.props.Document]), e.clientX, e.clientY, { - finishDrag: (dropData) => { + finishDrag: async (dropData) => { let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); dropData.droppedDocuments = [doc]; @@ -60,6 +60,7 @@ export class DragBox extends DocComponent(DragDocu handlers: { dragComplete: emptyFunction }, hideSource: false }); + await this.props.Document.factory; // if there's a factory Doc that is being copied, make sure it's not pending. } e.stopPropagation(); e.preventDefault(); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index eb752f8c6..66036f673 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -730,6 +730,7 @@ export namespace Doc { Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); }); Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); }); +Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return Doc.MakeCopy(doc, copyProto); }); Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 09bab959d..9a7b6442b 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -130,7 +130,7 @@ export class CurrentUserUtils { let createWebPage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); let createCatImage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); - createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" })'); + createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })'); let createButton = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); let createPresentation = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); @@ -139,7 +139,7 @@ export class CurrentUserUtils { createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); const color = Docs.Create.ColorDocument({ title: "color picker", width: 400, ignoreClick: true }); - const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }) + const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); -- cgit v1.2.3-70-g09d2 From d7653cab93309717488d51c68c8b1f0db64b949c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 13:59:32 -0400 Subject: fixed dropAction for library --- src/server/authentication/models/current_user_utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 9a7b6442b..08cdee0fd 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -30,7 +30,6 @@ export class CurrentUserUtils { private static createUserDocument(id: string): Doc { let doc = new Doc(id, true); doc.viewType = CollectionViewType.Tree; - doc.dropAction = "alias"; doc.layout = CollectionView.LayoutString(); doc.title = Doc.CurrentUserEmail; this.updateUserDocument(doc); @@ -114,6 +113,7 @@ export class CurrentUserUtils { library.gridGap = 5; library.xMargin = 5; library.yMargin = 5; + library.dropAction = "alias"; library.boxShadow = "1 1 3"; Library.targetContainer = doc.sidebarContainer; Library.library = library; -- cgit v1.2.3-70-g09d2 From f16621ff6bc0ad30cae39872412de80aa9f5e25c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 15:07:28 -0400 Subject: dragbox improvements to control creating aliases/copies --- src/client/util/DragManager.ts | 3 ++- src/client/views/nodes/DocumentView.tsx | 9 ++++++--- src/client/views/nodes/DragBox.tsx | 17 +++++++++++++---- src/server/authentication/models/current_user_utils.ts | 5 ++++- 4 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index ddc8fb62c..7259f66e3 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -10,7 +10,6 @@ import { LinkManager } from "./LinkManager"; import { SelectionManager } from "./SelectionManager"; import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField"; import { Docs } from "../documents/Documents"; -import { CompileScript } from "./Scripting"; import { ScriptField } from "../../new_fields/ScriptField"; import { List } from "../../new_fields/List"; import { PrefetchProxy } from "../../new_fields/Proxy"; @@ -208,6 +207,7 @@ export namespace DragManager { } draggedDocuments: Doc[]; droppedDocuments: Doc[]; + removeDropProperties: string[] = []; offset: number[]; dropAction: dropActionType; userDropAction: dropActionType; @@ -244,6 +244,7 @@ export namespace DragManager { dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : dragData.draggedDocuments ); + dragData.removeDropProperties.map(prop => dropData.droppedDocuments.map((d: Doc) => d[prop] = undefined)); }); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 20920a9b8..b98627c66 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -7,7 +7,7 @@ import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc import { Id } from '../../../new_fields/FieldSymbols'; import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; import { ScriptField } from '../../../new_fields/ScriptField'; -import { BoolCast, Cast, NumCast, PromiseValue, StrCast } from "../../../new_fields/Types"; +import { BoolCast, Cast, NumCast, PromiseValue, StrCast, FieldValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, returnTrue, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; @@ -102,6 +102,8 @@ export const documentSchema = createSchema({ height: "number", // " backgroundColor: "string", // background color of document opacity: "number", // opacity of document + dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy") + removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped (used for dragBox things) onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents @@ -167,9 +169,10 @@ export class DocumentView extends DocComponent(Docu dragData.dropAction = dropAction; dragData.moveDocument = this.props.moveDocument; dragData.applyAsTemplate = applyAsTemplate; + dragData.removeDropProperties = this.Document.removeDropProperties || []; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { handlers: { - dragComplete: action(emptyFunction) + dragComplete: action((emptyFunction)) }, hideSource: !dropAction }); @@ -260,7 +263,7 @@ export class DocumentView extends DocComponent(Docu if (!e.altKey && !this.topMost && e.buttons === 1) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); - this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); + this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); } } e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx index 4fca96382..1fd6cb5a5 100644 --- a/src/client/views/nodes/DragBox.tsx +++ b/src/client/views/nodes/DragBox.tsx @@ -3,7 +3,7 @@ import { faEdit } from '@fortawesome/free-regular-svg-icons'; import { observer } from 'mobx-react'; import * as React from 'react'; import { Doc } from '../../../new_fields/Doc'; -import { createSchema, makeInterface } from '../../../new_fields/Schema'; +import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema'; import { ScriptField } from '../../../new_fields/ScriptField'; import { emptyFunction } from '../../../Utils'; import { CompileScript } from '../../util/Scripting'; @@ -17,6 +17,8 @@ import { FieldView, FieldViewProps } from './FieldView'; import { DragManager } from '../../util/DragManager'; import { Docs } from '../../documents/Documents'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Cast } from '../../../new_fields/Types'; +import { ContextMenuProps } from '../ContextMenuItem'; library.add(faEdit as any); @@ -51,16 +53,19 @@ export class DragBox extends DocComponent(DragDocu const onDragStart = this.Document.onDragStart; e.stopPropagation(); e.preventDefault(); - DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([this.props.Document]), e.clientX, e.clientY, { + let dragData = new DragManager.DocumentDragData([this.props.Document]); + const factory = await Cast(this.props.Document.factory, Doc);// if there's a factory Doc that is being copied, make sure it's not pending. + dragData.removeDropProperties = factory ? Cast(factory.removeDropProperties, listSpec("string"), []) : []; + DragManager.StartDocumentDrag([this._mainCont.current!], dragData, e.clientX, e.clientY, { finishDrag: async (dropData) => { let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); dropData.droppedDocuments = [doc]; + dragData.removeDropProperties.map(prop => dropData.droppedDocuments.map((d: Doc) => d[prop] = undefined)); }, handlers: { dragComplete: emptyFunction }, hideSource: false }); - await this.props.Document.factory; // if there's a factory Doc that is being copied, make sure it's not pending. } e.stopPropagation(); e.preventDefault(); @@ -72,7 +77,10 @@ export class DragBox extends DocComponent(DragDocu } onContextMenu = () => { - ContextMenu.Instance.addItem({ + let funcs: ContextMenuProps[] = []; + funcs.push({ description: "Set Make Aliases", icon: "edit", event: () => this.props.Document.factory && (this.props.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.factory)')) }); + funcs.push({ description: "Set Make Copies", icon: "edit", event: () => this.props.Document.factory && (this.props.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)')) }); + funcs.push({ description: "Edit OnClick script", icon: "edit", event: () => { let overlayDisposer: () => void = emptyFunction; const script = this.Document.onDragStart; @@ -96,6 +104,7 @@ export class DragBox extends DocComponent(DragDocu overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnDragStart` }); } }); + ContextMenu.Instance.addItem({ description: "DragBox Funcs...", subitems: funcs, icon: "asterisk" }); } render() { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 08cdee0fd..74a41d8cf 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -138,7 +138,10 @@ export class CurrentUserUtils { let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); - const color = Docs.Create.ColorDocument({ title: "color picker", width: 400, ignoreClick: true }); + const color = Docs.Create.ColorDocument({ title: "color picker", width: 400 }); + color.dropAction = "alias"; + color.ignoreClick = true; + color.removeDropProperties = new List(["dropAction", "ignoreClick"]); const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; -- cgit v1.2.3-70-g09d2 From 988822bdeeed82b0c1ef611f2f7a3111d029d564 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 12 Oct 2019 19:37:06 -0400 Subject: a bunch of fixes to clean up drag box stuff. --- src/client/documents/DocumentTypes.ts | 2 +- src/client/documents/Documents.ts | 14 +- src/client/util/DragManager.ts | 19 +- src/client/views/GlobalKeyHandler.ts | 1 - src/client/views/Main.scss | 17 +- src/client/views/MainView.tsx | 250 ++++++++------------- src/client/views/nodes/ButtonBox.tsx | 3 +- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/DocumentView.tsx | 27 ++- src/client/views/nodes/DragBox.scss | 13 -- src/client/views/nodes/DragBox.tsx | 115 ---------- src/client/views/nodes/FontIconBox.scss | 13 ++ src/client/views/nodes/FontIconBox.tsx | 21 ++ .../authentication/models/current_user_utils.ts | 29 ++- 14 files changed, 194 insertions(+), 334 deletions(-) delete mode 100644 src/client/views/nodes/DragBox.scss delete mode 100644 src/client/views/nodes/DragBox.tsx create mode 100644 src/client/views/nodes/FontIconBox.scss create mode 100644 src/client/views/nodes/FontIconBox.tsx (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index dad2de0b5..432e53825 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -17,7 +17,7 @@ export enum DocumentType { TEMPLATE = "template", EXTENSION = "extension", YOUTUBE = "youtube", - DRAGBOX = "dragbox", + FONTICONBOX = "fonticonbox", PRES = "presentation", LINKFOLLOW = "linkfollow", PRESELEMENT = "preselement", diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e783848ff..1f89d2993 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -37,7 +37,7 @@ import { DocumentManager } from "../util/DocumentManager"; import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox"; import { Scripting, CompileScript } from "../util/Scripting"; import { ButtonBox } from "../views/nodes/ButtonBox"; -import { DragBox } from "../views/nodes/DragBox"; +import { FontIconBox } from "../views/nodes/FontIconBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; import { PresBox } from "../views/nodes/PresBox"; import { ComputedField } from "../../new_fields/ScriptField"; @@ -71,6 +71,7 @@ export interface DocumentOptions { viewType?: number; backgroundColor?: string; ignoreClick?: boolean; + lockedPosition?: boolean; opacity?: number; defaultBackgroundColor?: string; dropAction?: dropActionType; @@ -82,6 +83,7 @@ export interface DocumentOptions { currentTimecode?: number; documentText?: string; borderRounding?: string; + boxShadow?: string; schemaColumns?: List; dockingConfig?: string; autoHeight?: boolean; @@ -127,7 +129,7 @@ export namespace Docs { }], [DocumentType.QUERY, { layout: { view: QueryBox }, - options: { width: 400, fitWidth: true } + options: { width: 400 } }], [DocumentType.COLOR, { layout: { view: ColorBox }, @@ -183,8 +185,8 @@ export namespace Docs { layout: { view: PresBox }, options: {} }], - [DocumentType.DRAGBOX, { - layout: { view: DragBox }, + [DocumentType.FONTICONBOX, { + layout: { view: FontIconBox }, options: { width: 40, height: 40 }, }], [DocumentType.LINKFOLLOW, { @@ -476,8 +478,8 @@ export namespace Docs { } - export function DragboxDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.DRAGBOX), undefined, { ...(options || {}) }); + export function FontIconDocument(options?: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.FONTICONBOX), undefined, { ...(options || {}) }); } export function LinkFollowBoxDocument(options?: DocumentOptions) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 7259f66e3..2c316ccdf 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,6 +1,6 @@ import { action, runInAction } from "mobx"; import { Doc, Field } from "../../new_fields/Doc"; -import { Cast, StrCast } from "../../new_fields/Types"; +import { Cast, StrCast, ScriptCast } from "../../new_fields/Types"; import { URLField } from "../../new_fields/URLField"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; @@ -13,6 +13,7 @@ import { Docs } from "../documents/Documents"; import { ScriptField } from "../../new_fields/ScriptField"; import { List } from "../../new_fields/List"; import { PrefetchProxy } from "../../new_fields/Proxy"; +import { listSpec } from "../../new_fields/Schema"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -207,7 +208,6 @@ export namespace DragManager { } draggedDocuments: Doc[]; droppedDocuments: Doc[]; - removeDropProperties: string[] = []; offset: number[]; dropAction: dropActionType; userDropAction: dropActionType; @@ -234,17 +234,18 @@ export namespace DragManager { export let StartDragFunctions: (() => void)[] = []; - export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + export async function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { runInAction(() => StartDragFunctions.map(func => func())); + await dragData.draggedDocuments.map(d => d.dragFactory); StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : (dropData: { [id: string]: any }) => { - (dropData.droppedDocuments = dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? - dragData.draggedDocuments.map(d => Doc.MakeAlias(d)) : - dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? - dragData.draggedDocuments.map(d => Doc.MakeCopy(d, true)) : - dragData.draggedDocuments + (dropData.droppedDocuments = + dragData.draggedDocuments.map(d => ScriptCast(d.onDragStart) ? ScriptCast(d.onDragStart).script.run({ this: d }).result : + dragData.userDropAction === "alias" || (!dragData.userDropAction && dragData.dropAction === "alias") ? Doc.MakeAlias(d) : + dragData.userDropAction === "copy" || (!dragData.userDropAction && dragData.dropAction === "copy") ? Doc.MakeCopy(d, true) : d) ); - dragData.removeDropProperties.map(prop => dropData.droppedDocuments.map((d: Doc) => d[prop] = undefined)); + dropData.droppedDocuments.forEach((drop: Doc, i: number) => + Cast(dragData.draggedDocuments[i].removeDropProperties, listSpec("string"), []).map(prop => drop[prop] = undefined)); }); } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index f3e1933d7..38fce4cf7 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -73,7 +73,6 @@ export default class KeyManager { SelectionManager.DeselectAll(); } } - main.toggleColorPicker(true); SelectionManager.DeselectAll(); DictationManager.Controls.stop(); SharingManager.Instance.close(); diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index debb941c8..55195b616 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -185,7 +185,22 @@ button:hover { overflow: auto; z-index: 1; } - +.mainContent { + width:100%; + height:100%; + position:absolute; +} +.mainView-flyoutContainer{ + display:flex; + flex-direction: column; + position: absolute; + width:100%; + height:100%; + border: black 1px solid; + .documentView-node-topmost { + background: lightgrey; + } +} #mainContent-div { width: 100%; height: 100%; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 18e5052b7..aac4af9f6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,4 +1,4 @@ -import { IconName, library } from '@fortawesome/fontawesome-svg-core'; +import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faTv, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; @@ -6,60 +6,74 @@ import { observer } from 'mobx-react'; import "normalize.css"; import * as React from 'react'; import Measure from 'react-measure'; -import { Doc, DocListCast, Field, FieldResult, HeightSym, Opt } from '../../new_fields/Doc'; +import { Doc, DocListCast, Field, FieldResult, Opt } from '../../new_fields/Doc'; import { Id } from '../../new_fields/FieldSymbols'; import { InkTool } from '../../new_fields/InkField'; import { List } from '../../new_fields/List'; +import { ObjectField } from '../../new_fields/ObjectField'; import { listSpec } from '../../new_fields/Schema'; import { ScriptField } from '../../new_fields/ScriptField'; -import { BoolCast, Cast, FieldValue, PromiseValue, StrCast, NumCast } from '../../new_fields/Types'; +import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast } from '../../new_fields/Types'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { RouteStore } from '../../server/RouteStore'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils, returnFalse } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from '../../Utils'; import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocumentOptions } from '../documents/Documents'; import { DictationManager } from '../util/DictationManager'; -import { SetupDrag, DragManager } from '../util/DragManager'; +import { DragManager } from '../util/DragManager'; import { HistoryUtil } from '../util/History'; import SharingManager from '../util/SharingManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; import { CollectionBaseView, CollectionViewType } from './collections/CollectionBaseView'; import { CollectionDockingView } from './collections/CollectionDockingView'; -import { CollectionTreeView } from './collections/CollectionTreeView'; import { ContextMenu } from './ContextMenu'; import { DocumentDecorations } from './DocumentDecorations'; import KeyManager from './GlobalKeyHandler'; import { InkingControl } from './InkingControl'; import "./Main.scss"; import MainViewModal from './MainViewModal'; +import { MainViewNotifs } from './MainViewNotifs'; import { DocumentView } from './nodes/DocumentView'; import { OverlayView } from './OverlayView'; import PDFMenu from './pdf/PDFMenu'; import { PreviewCursor } from './PreviewCursor'; -import { CollectionFreeFormDocumentView } from './nodes/CollectionFreeFormDocumentView'; -import { MainViewNotifs } from './MainViewNotifs'; -import { DocumentType } from '../documents/DocumentTypes'; @observer export class MainView extends React.Component { public static Instance: MainView; - @observable addMenuToggle = React.createRef(); - @observable public pwidth: number = 0; - @observable public pheight: number = 0; - private _buttonBarHeight = 85; - private dropDisposer?: DragManager.DragDropDisposer; - - @observable private dictationState = DictationManager.placeholder; - @observable private dictationSuccessState: boolean | undefined = undefined; - @observable private dictationDisplayState = false; - @observable private dictationListeningState: DictationManager.Controls.ListeningUIStatus = false; + private _buttonBarHeight = 75; + private _flyoutSizeOnDown = 0; + private _urlState: HistoryUtil.DocUrl; + private _dropDisposer?: DragManager.DragDropDisposer; + + @observable private _dictationState = DictationManager.placeholder; + @observable private _dictationSuccessState: boolean | undefined = undefined; + @observable private _dictationDisplayState = false; + @observable private _dictationListeningState: DictationManager.Controls.ListeningUIStatus = false; + + @observable private _panelWidth: number = 0; + @observable private _panelHeight: number = 0; + @observable private _flyoutTranslate: boolean = true; + @observable public addMenuToggle = React.createRef(); + @observable public flyoutWidth: number = 250; public hasActiveModal = false; - + public isPointerDown = false; public overlayTimeout: NodeJS.Timeout | undefined; + private set mainContainer(doc: Opt) { + if (doc) { + !("presentationView" in doc) && (doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })])); + this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); + } + } + + @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; } + @computed private get userDoc() { return CurrentUserUtils.UserDocument; } + @computed public get mainFreeform(): Opt { return (docs => (docs && docs.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); } + public initiateDictationFade = () => { let duration = DictationManager.Commands.dictationFadeDuration; this.overlayTimeout = setTimeout(() => { @@ -69,13 +83,6 @@ export class MainView extends React.Component { setTimeout(() => this.dictatedPhrase = DictationManager.placeholder, 500); }, duration); } - - private urlState: HistoryUtil.DocUrl; - - @computed private get userDoc() { - return CurrentUserUtils.UserDocument; - } - public cancelDictationFade = () => { if (this.overlayTimeout) { clearTimeout(this.overlayTimeout); @@ -83,54 +90,15 @@ export class MainView extends React.Component { } } - @computed private get mainContainer(): Opt { - return this.userDoc ? FieldValue(Cast(this.userDoc.activeWorkspace, Doc)) : CurrentUserUtils.GuestWorkspace; - } - @computed get mainFreeform(): Opt { - let docs = DocListCast(this.mainContainer!.data); - return (docs && docs.length > 1) ? docs[1] : undefined; - } - public isPointerDown = false; - private set mainContainer(doc: Opt) { - if (doc) { - if (!("presentationView" in doc)) { - doc.presentationView = new List([Docs.Create.TreeDocument([], { title: "Presentation" })]); - } - this.userDoc ? (this.userDoc.activeWorkspace = doc) : (CurrentUserUtils.GuestWorkspace = doc); - } - } - - @computed public get dictatedPhrase() { - return this.dictationState; - } - - public set dictatedPhrase(value: string) { - runInAction(() => this.dictationState = value); - } - - @computed public get dictationSuccess() { - return this.dictationSuccessState; - } - - public set dictationSuccess(value: boolean | undefined) { - runInAction(() => this.dictationSuccessState = value); - } - - @computed public get dictationOverlayVisible() { - return this.dictationDisplayState; - } + @computed public get dictatedPhrase() { return this._dictationState; } + @computed public get dictationSuccess() { return this._dictationSuccessState; } + @computed public get dictationOverlayVisible() { return this._dictationDisplayState; } + @computed public get isListening() { return this._dictationListeningState; } - public set dictationOverlayVisible(value: boolean) { - runInAction(() => this.dictationDisplayState = value); - } - - @computed public get isListening() { - return this.dictationListeningState; - } - - public set isListening(value: DictationManager.Controls.ListeningUIStatus) { - runInAction(() => this.dictationListeningState = value); - } + public set dictatedPhrase(value: string) { runInAction(() => this._dictationState = value); } + public set dictationSuccess(value: boolean | undefined) { runInAction(() => this._dictationSuccessState = value); } + public set dictationOverlayVisible(value: boolean) { runInAction(() => this._dictationDisplayState = value); } + public set isListening(value: DictationManager.Controls.ListeningUIStatus) { runInAction(() => this._dictationListeningState = value); } componentWillMount() { var tag = document.createElement('script'); @@ -147,13 +115,13 @@ export class MainView extends React.Component { //close presentation window.removeEventListener("pointerdown", this.globalPointerDown); window.removeEventListener("pointerup", this.globalPointerUp); - this.dropDisposer && this.dropDisposer(); + this._dropDisposer && this._dropDisposer(); } constructor(props: Readonly<{}>) { super(props); MainView.Instance = this; - this.urlState = HistoryUtil.parseUrl(window.location) || {} as any; + this._urlState = HistoryUtil.parseUrl(window.location) || {} as any; // causes errors to be generated when modifying an observable outside of an action configure({ enforceActions: "observed" }); if (window.location.pathname !== RouteStore.home) { @@ -233,7 +201,7 @@ export class MainView extends React.Component { { fireImmediately: true } ); } else { - if (received && this.urlState.sharing) { + if (received && this._urlState.sharing) { reaction( () => { let docking = CollectionDockingView.Instance; @@ -264,8 +232,8 @@ export class MainView extends React.Component { let freeformOptions: DocumentOptions = { x: 0, y: 400, - width: this.pwidth * .7, - height: this.pheight, + width: this._panelWidth * .7, + height: this._panelHeight, title: "My Blank Collection" }; let workspaces: FieldResult; @@ -293,7 +261,7 @@ export class MainView extends React.Component { openWorkspace = async (doc: Doc, fromHistory = false) => { CurrentUserUtils.MainDocId = doc[Id]; this.mainContainer = doc; - let state = this.urlState; + let state = this._urlState; if (state.sharing === true && !this.userDoc) { DocServer.Control.makeReadOnly(); } else { @@ -318,25 +286,21 @@ export class MainView extends React.Component { DocServer.Control.makeEditable(); } } - let col: Opt; // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized) setTimeout(async () => { - if (this.userDoc && (col = await Cast(this.userDoc.optionalRightCollection, Doc))) { - const l = Cast(col.data, listSpec(Doc)); - if (l) { - runInAction(() => MainViewNotifs.NotifsCol = col); - } - } + const col = this.userDoc && await Cast(this.userDoc.optionalRightCollection, Doc); + col && Cast(col.data, listSpec(Doc)) && runInAction(() => MainViewNotifs.NotifsCol = col); }, 100); return true; } drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { - if (doc.type !== DocumentType.DRAGBOX) { - let dbox = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); - dbox.factory = doc; - dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)'); + if (!doc.onDragStart) { + let dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + dbox.dragFactory = doc; + dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); doc = dbox; } Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); @@ -351,30 +315,22 @@ export class MainView extends React.Component { @action onResize = (r: any) => { - this.pwidth = r.offset.width; - this.pheight = r.offset.height; - } - getPWidth = () => { - return this.pwidth; - } - getPHeight = () => { - return this.pheight; - } - getContentsHeight = () => { - return this.pheight - this._buttonBarHeight; + this._panelWidth = r.offset.width; + this._panelHeight = r.offset.height; } + getPWidth = () => this._panelWidth; + getPHeight = () => this._panelHeight; + getContentsHeight = () => this._panelHeight - this._buttonBarHeight; - @observable flyoutWidth: number = 250; - @observable flyoutTranslate: boolean = true; @computed get dockingContent() { - let flyoutWidth = this.flyoutWidth; - let countWidth = this.flyoutTranslate; - let mainCont = this.mainContainer; return {({ measureRef }) => -
    - {!mainCont ? (null) : - + {!this.mainContainer ? (null) : + ; } - _downsize = 0; onPointerDown = (e: React.PointerEvent) => { - this._downsize = e.clientX; + this._flyoutSizeOnDown = e.clientX; document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -417,15 +372,15 @@ export class MainView extends React.Component { pointerOverDragger = () => { if (this.flyoutWidth === 0) { this.flyoutWidth = 250; - this.flyoutTranslate = false; + this._flyoutTranslate = false; } } @action pointerLeaveDragger = () => { - if (!this.flyoutTranslate) { + if (!this._flyoutTranslate) { this.flyoutWidth = 0; - this.flyoutTranslate = true; + this._flyoutTranslate = true; } } @@ -435,7 +390,7 @@ export class MainView extends React.Component { } @action onPointerUp = (e: PointerEvent) => { - if (Math.abs(e.clientX - this._downsize) < 4) { + if (Math.abs(e.clientX - this._flyoutSizeOnDown) < 4) { if (this.flyoutWidth < 5) this.flyoutWidth = 250; else this.flyoutWidth = 0; } @@ -461,8 +416,8 @@ export class MainView extends React.Component { return (null); } let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; - libraryButtonDoc.columnWidth = this.flyoutWidthFunc() / 3 - 30; - return
    + libraryButtonDoc.columnWidth = this.flyoutWidth / 3 - 30; + return
    + const sidebar = this.userDoc && this.userDoc.sidebarContainer; + return !this.userDoc || !(sidebar instanceof Doc) ? (null) : ( +
    {this.flyout} {this.expandButton} @@ -556,10 +508,10 @@ export class MainView extends React.Component { } @computed get expandButton() { - return !this.flyoutTranslate ? (
    { + return !this._flyoutTranslate ? (
    { runInAction(() => { this.flyoutWidth = 250; - this.flyoutTranslate = true; + this._flyoutTranslate = true; }); }}>
    ) : (null); } @@ -572,14 +524,6 @@ export class MainView extends React.Component { return { fontSize: "50%" }; } - onColorClick = (e: React.MouseEvent) => { - let target = (e.nativeEvent as any).path[0]; - let parent = (e.nativeEvent as any).path[1]; - if (target.localName === "input" || parent.localName === "span") { - e.stopPropagation(); - } - } - setWriteMode = (mode: DocServer.WriteMode) => { console.log(DocServer.WriteMode[mode]); const mode1 = mode; @@ -596,13 +540,12 @@ export class MainView extends React.Component { } protected createDropTarget = (ele: HTMLLabelElement) => { //used for stacking and masonry view - this.dropDisposer && this.dropDisposer(); + this._dropDisposer && this._dropDisposer(); if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); } } - @observable private _colorPickerDisplay = false; /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ nodesMenu() { // let youtubeurl = "https://www.youtube.com/embed/TqcApsGRzWw"; @@ -610,14 +553,13 @@ export class MainView extends React.Component { // let googlePhotosSearch = () => GooglePhotosClientUtils.CollectionFromSearch(Docs.Create.MasonryDocument, { included: [GooglePhotosClientUtils.ContentCategories.LANDSCAPES] }); - return < div id="add-nodes-menu" style={{ left: (this.flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > + return < div id="add-nodes-menu" style={{ left: (this._flyoutTranslate ? this.flyoutWidth : 0) + 20, bottom: 20 }} > - +
    - {/*
  • */} @@ -658,18 +600,6 @@ export class MainView extends React.Component {
    ; } - - - @action - toggleColorPicker = (close = false) => { - this._colorPickerDisplay = close ? false : !this._colorPickerDisplay; - } - - @action.bound - toggleSearch = () => { - PromiseValue(Cast(CurrentUserUtils.UserDocument.Search, Doc)).then(pv => pv && (pv.onClick as ScriptField).script.run({ this: pv })); - } - @computed private get dictationOverlay() { let success = this.dictationSuccess; let result = this.isListening && !this.isListening.interim ? DictationManager.placeholder : `"${this.dictatedPhrase}"`; diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index f08ea4891..3cf8c3eb3 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -70,7 +70,8 @@ export class ButtonBox extends DocComponent(Butt let missingParams = params && params.filter(p => this.props.Document[p] === undefined); params && params.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ... return ( -
    +
    {(this.Document.text || this.Document.title)} diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index f2a581c42..19ffdf0cd 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -16,7 +16,7 @@ import { AudioBox } from "./AudioBox"; import { ButtonBox } from "./ButtonBox"; import { DocumentViewProps } from "./DocumentView"; import "./DocumentView.scss"; -import { DragBox } from "./DragBox"; +import { FontIconBox } from "./FontIconBox"; import { FieldView, FieldViewProps } from "./FieldView"; import { FormattedTextBox } from "./FormattedTextBox"; import { IconBox } from "./IconBox"; @@ -102,7 +102,7 @@ export class DocumentContentsView extends React.Component(Docu if (this._mainCont.current) { let dragData = new DragManager.DocumentDragData([this.props.Document]); const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); - dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); + dragData.offset = this.Document.onDragStart ? [0, 0] : this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.dropAction = dropAction; - dragData.moveDocument = this.props.moveDocument; + dragData.moveDocument = this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.applyAsTemplate = applyAsTemplate; - dragData.removeDropProperties = this.Document.removeDropProperties || []; DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { handlers: { dragComplete: action((emptyFunction)) }, - hideSource: !dropAction + hideSource: !dropAction && !this.Document.onDragStart }); } } @@ -246,7 +247,7 @@ export class DocumentView extends DocComponent(Docu this._hitTemplateDrag = true; } } - if (this.active && e.button === 0 && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); + if ((this.active || this.Document.onDragStart) && e.button === 0 && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -258,9 +259,9 @@ export class DocumentView extends DocComponent(Docu if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) } - else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive()) && !this.Document.lockedPosition && !this.Document.inOverlay) { + else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive() || this.Document.onDragStart) && !this.Document.lockedPosition && !this.Document.inOverlay) { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - if (!e.altKey && !this.topMost && e.buttons === 1) { + if (!e.altKey && (!this.topMost || this.Document.onDragStart) && e.buttons === 1) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); @@ -475,6 +476,12 @@ export class DocumentView extends DocComponent(Docu }); !existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" }); + let funcs: ContextMenuProps[] = []; + funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) }); + funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) }); + funcs.push({ description: "Drag Document", icon: "edit", event: () => this.Document.onDragStart = undefined }); + ContextMenu.Instance.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" }); + let existing = ContextMenu.Instance.findByDescription("Layout..."); let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : []; layoutItems.push({ description: this.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.Document.lockedPosition ? "unlock" : "lock" }); @@ -627,8 +634,8 @@ export class DocumentView extends DocComponent(Docu this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) : ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document); - const nativeWidth = this.props.Document.fitWidth ? this.props.PanelWidth() : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%"; - const nativeHeight = this.props.Document.fitWidth ? this.props.PanelHeight() : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; + const nativeWidth = this.props.Document.fitWidth ? this.props.PanelWidth() - 2 : this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%"; + const nativeHeight = this.props.Document.fitWidth ? this.props.PanelHeight() - 2 : this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined; const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.getLayoutPropStr("showTitle"); const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption"); diff --git a/src/client/views/nodes/DragBox.scss b/src/client/views/nodes/DragBox.scss deleted file mode 100644 index fbb9b9c1c..000000000 --- a/src/client/views/nodes/DragBox.scss +++ /dev/null @@ -1,13 +0,0 @@ -.dragBox-outerDiv { - width: 100%; - height: 100%; - pointer-events: all; - border-radius: inherit; - background: black; - border-radius: 100%; - svg { - margin:18%; - width:65% !important; - height:65%; - } -} diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx deleted file mode 100644 index 1fd6cb5a5..000000000 --- a/src/client/views/nodes/DragBox.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faEdit } from '@fortawesome/free-regular-svg-icons'; -import { observer } from 'mobx-react'; -import * as React from 'react'; -import { Doc } from '../../../new_fields/Doc'; -import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema'; -import { ScriptField } from '../../../new_fields/ScriptField'; -import { emptyFunction } from '../../../Utils'; -import { CompileScript } from '../../util/Scripting'; -import { ContextMenu } from '../ContextMenu'; -import { DocComponent } from '../DocComponent'; -import { OverlayView } from '../OverlayView'; -import { ScriptBox } from '../ScriptBox'; -import { DocumentIconContainer } from './DocumentIcon'; -import './DragBox.scss'; -import { FieldView, FieldViewProps } from './FieldView'; -import { DragManager } from '../../util/DragManager'; -import { Docs } from '../../documents/Documents'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Cast } from '../../../new_fields/Types'; -import { ContextMenuProps } from '../ContextMenuItem'; - -library.add(faEdit as any); - -const DragSchema = createSchema({ - onDragStart: ScriptField, - text: "string" -}); - -type DragDocument = makeInterface<[typeof DragSchema]>; -const DragDocument = makeInterface(DragSchema); -@observer -export class DragBox extends DocComponent(DragDocument) { - _downX: number = 0; - _downY: number = 0; - public static LayoutString() { return FieldView.LayoutString(DragBox); } - _mainCont = React.createRef(); - onDragStart = (e: React.PointerEvent) => { - if (!e.ctrlKey && !e.altKey && !e.shiftKey && !this.props.isSelected() && e.button === 0) { - document.removeEventListener("pointermove", this.onDragMove); - document.addEventListener("pointermove", this.onDragMove); - document.removeEventListener("pointerup", this.onDragUp); - document.addEventListener("pointerup", this.onDragUp); - e.stopPropagation(); - e.preventDefault(); - } - } - - onDragMove = async (e: MouseEvent) => { - if (!e.cancelBubble && (Math.abs(this._downX - e.clientX) > 5 || Math.abs(this._downY - e.clientY) > 5)) { - document.removeEventListener("pointermove", this.onDragMove); - document.removeEventListener("pointerup", this.onDragUp); - const onDragStart = this.Document.onDragStart; - e.stopPropagation(); - e.preventDefault(); - let dragData = new DragManager.DocumentDragData([this.props.Document]); - const factory = await Cast(this.props.Document.factory, Doc);// if there's a factory Doc that is being copied, make sure it's not pending. - dragData.removeDropProperties = factory ? Cast(factory.removeDropProperties, listSpec("string"), []) : []; - DragManager.StartDocumentDrag([this._mainCont.current!], dragData, e.clientX, e.clientY, { - finishDrag: async (dropData) => { - let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result; - let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" }); - dropData.droppedDocuments = [doc]; - dragData.removeDropProperties.map(prop => dropData.droppedDocuments.map((d: Doc) => d[prop] = undefined)); - }, - handlers: { dragComplete: emptyFunction }, - hideSource: false - }); - } - e.stopPropagation(); - e.preventDefault(); - } - - onDragUp = (e: MouseEvent) => { - document.removeEventListener("pointermove", this.onDragMove); - document.removeEventListener("pointerup", this.onDragUp); - } - - onContextMenu = () => { - let funcs: ContextMenuProps[] = []; - funcs.push({ description: "Set Make Aliases", icon: "edit", event: () => this.props.Document.factory && (this.props.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.factory)')) }); - funcs.push({ description: "Set Make Copies", icon: "edit", event: () => this.props.Document.factory && (this.props.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.factory, true)')) }); - funcs.push({ - description: "Edit OnClick script", icon: "edit", event: () => { - let overlayDisposer: () => void = emptyFunction; - const script = this.Document.onDragStart; - let originalText: string | undefined = undefined; - if (script) originalText = script.script.originalScript; - // tslint:disable-next-line: no-unnecessary-callback-wrapper - let scriptingBox = overlayDisposer()} onSave={(text, onError) => { - const script = CompileScript(text, { - params: { this: Doc.name }, - typecheck: false, - editable: true, - transformer: DocumentIconContainer.getTransformer() - }); - if (!script.compiled) { - onError(script.errors.map(error => error.messageText).join("\n")); - return; - } - this.Document.onClick = new ScriptField(script); - overlayDisposer(); - }} showDocumentIcons />; - overlayDisposer = OverlayView.Instance.addWindow(scriptingBox, { x: 400, y: 200, width: 500, height: 400, title: `${this.Document.title || ""} OnDragStart` }); - } - }); - ContextMenu.Instance.addItem({ description: "DragBox Funcs...", subitems: funcs, icon: "asterisk" }); - } - - render() { - return (
    - -
    ); - } -} \ No newline at end of file diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss new file mode 100644 index 000000000..75d093fcb --- /dev/null +++ b/src/client/views/nodes/FontIconBox.scss @@ -0,0 +1,13 @@ +.fontIconBox-outerDiv { + width: 100%; + height: 100%; + pointer-events: all; + border-radius: inherit; + background: black; + border-radius: 100%; + svg { + margin:18%; + width:65% !important; + height:65%; + } +} diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx new file mode 100644 index 000000000..3b580d851 --- /dev/null +++ b/src/client/views/nodes/FontIconBox.tsx @@ -0,0 +1,21 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { createSchema, makeInterface } from '../../../new_fields/Schema'; +import { DocComponent } from '../DocComponent'; +import './FontIconBox.scss'; +import { FieldView, FieldViewProps } from './FieldView'; +const FontIconSchema = createSchema({ + icon: "string" +}); + +type FontIconDocument = makeInterface<[typeof FontIconSchema]>; +const FontIconDocument = makeInterface(FontIconSchema); +@observer +export class FontIconBox extends DocComponent(FontIconDocument) { + public static LayoutString() { return FieldView.LayoutString(FontIconBox); } + + render() { + return
    ; + } +} \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 74a41d8cf..9f9f79dc4 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -99,9 +99,9 @@ export class CurrentUserUtils { } if (doc.Library === undefined) { - let Search = Docs.Create.ButtonDocument({ width: 50, height: 35, title: "Search" }); - let Library = Docs.Create.ButtonDocument({ width: 50, height: 35, title: "Library" }); - let Create = Docs.Create.ButtonDocument({ width: 35, height: 35, title: "Create" }); + let Search = Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Search" }); + let Library = Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Library" }); + let Create = Docs.Create.ButtonDocument({ width: 35, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Create" }); if (doc.sidebarContainer === undefined) { doc.sidebarContainer = new Doc(); (doc.sidebarContainer as Doc).chromeStatus = "disabled"; @@ -114,40 +114,39 @@ export class CurrentUserUtils { library.xMargin = 5; library.yMargin = 5; library.dropAction = "alias"; - library.boxShadow = "1 1 3"; Library.targetContainer = doc.sidebarContainer; Library.library = library; Library.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.library"); - const searchBox = Docs.Create.QueryDocument({ title: "Searching" }); - searchBox.boxShadow = "0 0"; + const searchBox = Docs.Create.QueryDocument({ title: "search stack" }); searchBox.ignoreClick = true; Search.searchBox = searchBox; Search.targetContainer = doc.sidebarContainer; Search.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.searchBox"); - let createCollection = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); - let createWebPage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); + let createCollection = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); + createCollection.onDragStart = ScriptField.MakeFunction('Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })'); + let createWebPage = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); - let createCatImage = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); + let createCatImage = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })'); - let createButton = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); + let createButton = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); - let createPresentation = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); + let createPresentation = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); createPresentation.onDragStart = ScriptField.MakeFunction('Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })'); - let createFolderImport = Docs.Create.DragboxDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); + let createFolderImport = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); - const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, chromeStatus: "disabled", title: "buttons" }); + const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons" }); const color = Docs.Create.ColorDocument({ title: "color picker", width: 400 }); color.dropAction = "alias"; color.ignoreClick = true; color.removeDropProperties = new List(["dropAction", "ignoreClick"]); - const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "buttons" }); + const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "creator stack" }); Create.targetContainer = doc.sidebarContainer; Create.creators = creators; Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); - const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "buttons" }); + const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "library stack" }); libraryButtons.sectionFilter = "title"; libraryButtons.boxShadow = "0 0"; libraryButtons.ignoreClick = true; -- cgit v1.2.3-70-g09d2 From baf6ed901d341cade58741d363bbc475519558ae Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 13 Oct 2019 03:10:29 -0400 Subject: made CollectionLinearView out of doc buttons --- src/client/views/CollectionLinearView.scss | 13 ++- src/client/views/CollectionLinearView.tsx | 111 +++++++++++---------- src/client/views/MainView.tsx | 34 ++++++- .../views/collections/CollectionBaseView.tsx | 6 +- src/client/views/collections/CollectionSubView.tsx | 1 + src/client/views/collections/CollectionView.tsx | 2 + .../views/collections/CollectionViewChromes.tsx | 1 + .../authentication/models/current_user_utils.ts | 2 + 8 files changed, 111 insertions(+), 59 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/views/CollectionLinearView.scss b/src/client/views/CollectionLinearView.scss index 30be07a9f..46a226eef 100644 --- a/src/client/views/CollectionLinearView.scss +++ b/src/client/views/CollectionLinearView.scss @@ -1,8 +1,13 @@ @import "globalCssVariables"; @import "nodeModuleOverrides"; +.collectionLinearView-outer{ + overflow: hidden; + height:100%; + padding:5px; +} .collectionLinearView { - + display:flex; >label { background: $dark-color; color: $light-color; @@ -18,6 +23,8 @@ label p { padding-left: 10.5px; + width: 500px; + height: 500px; } label:hover { @@ -41,18 +48,14 @@ .collectionLinearView-content { display: flex; opacity: 1; - margin: 0; padding: 0; position: relative; - float: right; .collectionFreeFormDocumentView-container { position: relative; } .collectionLinearView-docBtn { position:relative; margin-right: 10px; - width: 35px; - height: 35px; } .collectionLinearView-round-button { width: 36px; diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 18e3598a5..692f940f8 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -7,22 +7,23 @@ import { InkTool } from '../../new_fields/InkField'; import { ObjectField } from '../../new_fields/ObjectField'; import { ScriptField } from '../../new_fields/ScriptField'; import { NumCast, StrCast } from '../../new_fields/Types'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse } from '../../Utils'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse, Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; import { InkingControl } from './InkingControl'; -import { DocumentView } from './nodes/DocumentView'; +import { DocumentView, documentSchema } from './nodes/DocumentView'; import "./CollectionLinearView.scss"; +import { makeInterface } from '../../new_fields/Schema'; +import { CollectionSubView } from './collections/CollectionSubView'; -interface CollectionLinearViewProps { - Document: Doc; - fieldKey: string; -} + +type LinearDocument = makeInterface<[typeof documentSchema,]>; +const LinearDocument = makeInterface(documentSchema); @observer -export class CollectionLinearView extends React.Component{ +export class CollectionLinearView extends CollectionSubView(LinearDocument) { @observable public addMenuToggle = React.createRef(); private _dropDisposer?: DragManager.DragDropDisposer; @@ -30,7 +31,7 @@ export class CollectionLinearView extends React.Component { //used for stacking and masonry view + protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { this._dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); @@ -38,16 +39,18 @@ export class CollectionLinearView extends React.Component { - (de.data as DragManager.DocumentDragData).draggedDocuments.map(doc => { - if (!doc.onDragStart) { - let dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); + (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { + let dbox = doc; + if (!doc.onDragStart && this.props.Document.convertToButtons) { + dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); dbox.dragFactory = doc; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); - doc = dbox; } - Doc.AddDocToList(this.props.Document, this.props.fieldKey, doc); + (de.data as DragManager.DocumentDragData).droppedDocuments[i] = dbox; }); + e.stopPropagation(); + return super.drop(e, de); }); selected = (tool: InkTool) => { @@ -58,49 +61,55 @@ export class CollectionLinearView extends React.Component NumCast(this.props.Document.height) - 5; render() { - return
    - - + let guid = Utils.GenerateGuid(); + return
    + +
    - - + {this.props.showHiddenControls ? : (null)} + {this.props.showHiddenControls ? : (null)} - {DocListCast(this.props.Document[this.props.fieldKey]).map(doc =>
    - Doc.RemoveDocFromList(this.props.Document, this.props.fieldKey, doc)} - ruleProvider={undefined} - onClick={undefined} - ScreenToLocalTransform={Transform.Identity} - ContentScaling={() => 35 / NumCast(doc.nativeWidth, 35)} - PanelWidth={() => 35} - PanelHeight={() => 35} - renderDepth={0} - focus={emptyFunction} - backgroundColor={returnEmptyString} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - zoomToScale={emptyFunction} - getScale={returnOne}> - -
    )} + {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => +
    + this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing + PanelWidth={this.dimension} + PanelHeight={this.dimension} + renderDepth={this.props.renderDepth + 1} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} {/*
  • */} - - - - - - + {this.props.showHiddenControls ? <> + + + + + + : (null)}
    -
    ; +
    ; } } \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4367785b6..5756c1510 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -441,10 +441,42 @@ export class MainView extends React.Component { }}>
    ) : (null); } + addButtonDoc = (doc: Doc) => { + Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); + return true; + } + remButtonDoc = (doc: Doc) => { + Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc); + return true; + } @computed get docButtons() { return
    - +
    ; } diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 61919427a..7798964ea 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -23,6 +23,7 @@ export enum CollectionViewType { Stacking, Masonry, Pivot, + Linear, } export namespace CollectionViewType { @@ -35,7 +36,8 @@ export namespace CollectionViewType { ["tree", CollectionViewType.Tree], ["stacking", CollectionViewType.Stacking], ["masonry", CollectionViewType.Masonry], - ["pivot", CollectionViewType.Pivot] + ["pivot", CollectionViewType.Pivot], + ["linear", CollectionViewType.Linear] ]); export const valueOf = (value: string) => { @@ -177,7 +179,7 @@ export class CollectionBaseView extends React.Component {
    diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index fdbe5339d..6e8e4fa12 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -33,6 +33,7 @@ export interface CollectionViewProps extends FieldViewProps { VisibleHeight?: () => number; chromeCollapsed: boolean; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; + showHiddenControls?: boolean; // hack for showing the undo/redo/ink controls in a linear view -- needs to be redone } export interface SubCollectionViewProps extends CollectionViewProps { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 893763840..3d5b4e562 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -19,6 +19,7 @@ import { CollectionStackingView } from './CollectionStackingView'; import { CollectionTreeView } from "./CollectionTreeView"; import { CollectionViewBaseChrome } from './CollectionViewChromes'; import { ImageUtils } from '../../util/Import & Export/ImageUtils'; +import { CollectionLinearView } from '../CollectionLinearView'; export const COLLECTION_BORDER_WIDTH = 2; library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy); @@ -66,6 +67,7 @@ export class CollectionView extends React.Component { case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Pivot: { this.props.Document.freeformLayoutEngine = "pivot"; return (); } + case CollectionViewType.Linear: { return (); } case CollectionViewType.Freeform: default: this.props.Document.freeformLayoutEngine = undefined; diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 72f3514b6..3a66c05f4 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -399,6 +399,7 @@ export class CollectionViewBaseChrome extends React.ComponentStacking View +
    Date: Sun, 13 Oct 2019 19:17:45 -0400 Subject: minor cleanups --- src/client/util/TooltipTextMenu.tsx | 2 +- src/client/util/UndoManager.ts | 4 +- src/client/views/CollectionLinearView.scss | 118 ++++++++++----------- src/client/views/CollectionLinearView.tsx | 103 ++++++++++-------- src/client/views/DocumentDecorations.tsx | 8 +- src/client/views/MainView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FontIconBox.tsx | 2 +- src/new_fields/Doc.ts | 5 +- .../authentication/models/current_user_utils.ts | 21 +++- 10 files changed, 150 insertions(+), 118 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index c82d3bc63..31d98887f 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -850,7 +850,7 @@ export class TooltipTextMenu { } this.view = view; let state = view.state; - DocumentDecorations.Instance.TextBar && DocumentDecorations.Instance.setTextBar(DocumentDecorations.Instance.TextBar); + DocumentDecorations.Instance.showTextBar(); props && (this.editorProps = props); // Don't do anything if the document/selection didn't change if (lastState && lastState.doc.eq(state.doc) && diff --git a/src/client/util/UndoManager.ts b/src/client/util/UndoManager.ts index 7abb9d1ee..472afac1d 100644 --- a/src/client/util/UndoManager.ts +++ b/src/client/util/UndoManager.ts @@ -73,8 +73,8 @@ export namespace UndoManager { } type UndoBatch = UndoEvent[]; - let undoStack: UndoBatch[] = observable([]); - let redoStack: UndoBatch[] = observable([]); + export let undoStack: UndoBatch[] = observable([]); + export let redoStack: UndoBatch[] = observable([]); let currentBatch: UndoBatch | undefined; let batchCounter = 0; let undoing = false; diff --git a/src/client/views/CollectionLinearView.scss b/src/client/views/CollectionLinearView.scss index 46a226eef..1e6bb5922 100644 --- a/src/client/views/CollectionLinearView.scss +++ b/src/client/views/CollectionLinearView.scss @@ -5,73 +5,69 @@ overflow: hidden; height:100%; padding:5px; -} -.collectionLinearView { - display:flex; - >label { - background: $dark-color; - color: $light-color; - display: inline-block; - border-radius: 18px; - font-size: 25px; - width: 36px; - height: 36px; - margin-right: 10px; - cursor: pointer; - transition: transform 0.2s; - } + .collectionLinearView { + display:flex; + >label { + background: $dark-color; + color: $light-color; + display: inline-block; + border-radius: 18px; + font-size: 25px; + width: 36px; + height: 36px; + margin-right: 10px; + cursor: pointer; + transition: transform 0.2s; + } - label p { - padding-left: 10.5px; - width: 500px; - height: 500px; - } + label p { + padding-left: 10.5px; + width: 500px; + height: 500px; + } - label:hover { - background: $main-accent; - transform: scale(1.15); - } + label:hover { + background: $main-accent; + transform: scale(1.15); + } - >input { - display: none; - } - >input:not(:checked)~.collectionLinearView-content { - display: none; - } + >input { + display: none; + } + >input:not(:checked)~.collectionLinearView-content { + display: none; + } - >input:checked~label { - transform: rotate(45deg); - transition: transform 0.5s; - cursor: pointer; - } + >input:checked~label { + transform: rotate(45deg); + transition: transform 0.5s; + cursor: pointer; + } - .collectionLinearView-content { - display: flex; - opacity: 1; - padding: 0; - position: relative; - .collectionFreeFormDocumentView-container { + .collectionLinearView-content { + display: flex; + opacity: 1; + padding: 0; position: relative; - } - .collectionLinearView-docBtn { - position:relative; - margin-right: 10px; - } - .collectionLinearView-round-button { - width: 36px; - height: 36px; - border-radius: 18px; - font-size: 15px; - } - - .collectionLinearView-round-button:hover { - transform: scale(1.15); + + .collectionLinearView-docBtn { + position:relative; + margin-right: 10px; + } + .collectionLinearView-docBtn:hover { + transform: scale(1.15); + } + + .collectionLinearView-round-button { + width: 36px; + height: 36px; + border-radius: 18px; + font-size: 15px; + } + + .collectionLinearView-round-button:hover { + transform: scale(1.15); + } } - - } - - .collectionLinearView-add-button { - position: relative; - margin-right: 10px; } } diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 692f940f8..49c67a448 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -1,8 +1,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, computed } from 'mobx'; +import { action, observable, computed, IReactionDisposer, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, Opt } from '../../new_fields/Doc'; +import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc'; import { InkTool } from '../../new_fields/InkField'; import { ObjectField } from '../../new_fields/ObjectField'; import { ScriptField } from '../../new_fields/ScriptField'; @@ -25,12 +25,26 @@ const LinearDocument = makeInterface(documentSchema); @observer export class CollectionLinearView extends CollectionSubView(LinearDocument) { @observable public addMenuToggle = React.createRef(); + @observable private _checked = false; private _dropDisposer?: DragManager.DragDropDisposer; + private _heightDisposer?: IReactionDisposer; componentWillUnmount() { this._dropDisposer && this._dropDisposer(); + this._heightDisposer && this._heightDisposer(); } + componentDidMount() { + // is there any reason this needs to exist? -syip. yes, it handles autoHeight for stacking views (masonry isn't yet supported). + this._heightDisposer = reaction(() => NumCast(this.props.Document.height, 0) + this.childDocs.length + (this._checked ? 1 : 0), + () => { + if (true || this.props.Document.fitWidth) { + this.props.Document.width = 36 + (this._checked ? this.childDocs.length * (this.props.Document[HeightSym]() + 10) : 10); + } + }, + { fireImmediately: true } + ); + } protected createDropTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view this._dropDisposer && this._dropDisposer(); if (ele) { @@ -66,50 +80,49 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { dimension = () => NumCast(this.props.Document.height) - 5; render() { let guid = Utils.GenerateGuid(); - return
    - - - -
    - {this.props.showHiddenControls ? : (null)} - {this.props.showHiddenControls ? : (null)} + return
    +
    + this._checked = this.addMenuToggle.current!.checked)} /> + - {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => -
    - this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing - PanelWidth={this.dimension} - PanelHeight={this.dimension} - renderDepth={this.props.renderDepth + 1} - focus={emptyFunction} - backgroundColor={returnEmptyString} - parentActive={returnTrue} - whenActiveChanged={emptyFunction} - bringToFront={emptyFunction} - ContainingCollectionView={undefined} - ContainingCollectionDoc={undefined} - zoomToScale={emptyFunction} - getScale={returnOne}> - -
    )} - {/*
  • */} - {this.props.showHiddenControls ? <> - - - - - - : (null)} +
    + {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => +
    + this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing + PanelWidth={this.dimension} + PanelHeight={this.dimension} + renderDepth={this.props.renderDepth + 1} + focus={emptyFunction} + backgroundColor={returnEmptyString} + parentActive={returnTrue} + whenActiveChanged={emptyFunction} + bringToFront={emptyFunction} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} + zoomToScale={emptyFunction} + getScale={returnOne}> + +
    )} + {/*
  • */} + {this.props.showHiddenControls ? <> + + + + + + : (null)} +
    -
    ; +
    ; } } \ No newline at end of file diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 1d9f0c74b..3d73f048d 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -547,10 +547,14 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> } TextBar: HTMLDivElement | undefined; - setTextBar = (ele: HTMLDivElement) => { + private setTextBar = (ele: HTMLDivElement) => { if (ele) { this.TextBar = ele; - TooltipTextMenu.Toolbar && Array.from(ele.childNodes).indexOf(TooltipTextMenu.Toolbar) === -1 && ele.appendChild(TooltipTextMenu.Toolbar); + } + } + public showTextBar = () => { + if (this.TextBar) { + TooltipTextMenu.Toolbar && Array.from(this.TextBar.childNodes).indexOf(TooltipTextMenu.Toolbar) === -1 && this.TextBar.appendChild(TooltipTextMenu.Toolbar); } } render() { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5756c1510..39585113b 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -334,6 +334,7 @@ export class MainView extends React.Component { return CollectionDockingView.AddRightSplit(doc, undefined); } } + mainContainerXf = () => new Transform(0, -this._buttonBarHeight, 1); @computed get flyout() { let sidebarContent = this.userDoc && this.userDoc.sidebarContainer; @@ -379,7 +380,7 @@ export class MainView extends React.Component { removeDocument={returnFalse} ruleProvider={undefined} onClick={undefined} - ScreenToLocalTransform={Transform.Identity} + ScreenToLocalTransform={this.mainContainerXf} ContentScaling={returnOne} PanelWidth={this.flyoutWidthFunc} PanelHeight={this.getContentsHeight} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7334de92c..188c18ba7 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -185,7 +185,7 @@ export class DocumentView extends DocComponent(Docu (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { e.stopPropagation(); let preventDefault = true; - if (this._doubleTap && this.props.renderDepth) { + if (this._doubleTap && this.props.renderDepth && (!this.onClickHandler || !this.onClickHandler.script)) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click let fullScreenAlias = Doc.MakeAlias(this.props.Document); let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc)); if (layoutNative && fullScreenAlias.layout === layoutNative.layout) { diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 3b580d851..3f5afb6d1 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -16,6 +16,6 @@ export class FontIconBox extends DocComponent( public static LayoutString() { return FieldView.LayoutString(FontIconBox); } render() { - return
    ; + return ; } } \ No newline at end of file diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 66036f673..4bed113e3 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -14,6 +14,7 @@ import { ComputedField } from "./ScriptField"; import { BoolCast, Cast, FieldValue, NumCast, PromiseValue, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction } from "./util"; import { intersectRect } from "../Utils"; +import { UndoManager } from "../client/util/UndoManager"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -733,4 +734,6 @@ Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); }); Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return Doc.MakeCopy(doc, copyProto); }); Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); -Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); \ No newline at end of file +Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); +Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); +Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 3858907ba..73cac879e 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,4 +1,4 @@ -import { action, computed, observable, runInAction } from "mobx"; +import { action, computed, observable, runInAction, reaction } from "mobx"; import * as rp from 'request-promise'; import { DocServer } from "../../../client/DocServer"; import { Docs } from "../../../client/documents/Documents"; @@ -13,6 +13,8 @@ import { Cast, StrCast, PromiseValue } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { RouteStore } from "../../RouteStore"; import { ScriptField } from "../../../new_fields/ScriptField"; +import { ButtonBox } from "../../../client/views/nodes/ButtonBox"; +import { UndoManager } from "../../../client/util/UndoManager"; export class CurrentUserUtils { private static curr_id: string; @@ -32,7 +34,6 @@ export class CurrentUserUtils { doc.viewType = CollectionViewType.Tree; doc.layout = CollectionView.LayoutString(); doc.title = Doc.CurrentUserEmail; - this.updateUserDocument(doc); doc.data = new List(); doc.gridGap = 5; doc.xMargin = 5; @@ -41,11 +42,21 @@ export class CurrentUserUtils { doc.boxShadow = "0 0"; doc.convertToButtons = true; // for CollectionLinearView used as the docButton layout doc.optionalRightCollection = Docs.Create.StackingDocument([], { title: "New mobile uploads" }); - return doc; + return this.updateUserDocument(doc);// this should be the last } static updateUserDocument(doc: Doc) { + if (doc.undoBtn === undefined) { + doc.undoBtn = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "undo-alt" }); + (doc.undoBtn as Doc).onClick = ScriptField.MakeScript('undo()'); + Doc.AddDocToList(doc, "docButtons", doc.undoBtn as Doc); + } + if (doc.redoBtn === undefined) { + doc.redoBtn = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "redo-alt" }); + (doc.redoBtn as Doc).onClick = ScriptField.MakeScript('redo()'); + Doc.AddDocToList(doc, "docButtons", doc.redoBtn as Doc); + } // setup workspaces library item if (doc.workspaces === undefined) { const workspaces = Docs.Create.TreeDocument([], { title: "WORKSPACES", height: 100 }); @@ -181,6 +192,10 @@ export class CurrentUserUtils { doc.preventTreeViewOpen = true; doc.forceActive = true; doc.lockedPosition = true; + doc.undoBtn && reaction(() => UndoManager.undoStack.slice(), () => (doc.undoBtn as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true }); + doc.redoBtn && reaction(() => UndoManager.redoStack.slice(), () => (doc.redoBtn as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); + + return doc; } public static loadCurrentUser() { -- cgit v1.2.3-70-g09d2 From 26e215b0cddbb4c14cfd8eb7a720a373e797c615 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 15 Oct 2019 00:23:00 -0400 Subject: cleaned up current_user_utils. cleaned up some interactions with colorBox, textbox height --- src/client/documents/Documents.ts | 19 +- src/client/views/DocComponent.tsx | 34 ++- src/client/views/InkingControl.tsx | 8 + src/client/views/MainView.tsx | 16 +- src/client/views/nodes/ColorBox.scss | 7 +- src/client/views/nodes/ColorBox.tsx | 12 +- src/client/views/nodes/FormattedTextBox.tsx | 13 +- src/client/views/nodes/PDFBox.tsx | 3 +- .../authentication/models/current_user_utils.ts | 295 ++++++++++----------- 9 files changed, 229 insertions(+), 178 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1f89d2993..13cc7815c 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -40,7 +40,7 @@ import { ButtonBox } from "../views/nodes/ButtonBox"; import { FontIconBox } from "../views/nodes/FontIconBox"; import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField"; import { PresBox } from "../views/nodes/PresBox"; -import { ComputedField } from "../../new_fields/ScriptField"; +import { ComputedField, ScriptField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; import { LinkFollowBox } from "../views/linking/LinkFollowBox"; @@ -65,7 +65,10 @@ export interface DocumentOptions { page?: number; scale?: number; fitWidth?: boolean; + forceActive?: boolean; + preventTreeViewOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expande/collapse state to be independent of other views of the same document in the tree view layout?: string | Doc; + hideHeadings?: boolean; // whether stacking view column headings should be hidden isTemplate?: boolean; templates?: List; viewType?: number; @@ -84,11 +87,21 @@ export interface DocumentOptions { documentText?: string; borderRounding?: string; boxShadow?: string; + sectionFilter?: string; // field key used to determine headings for sections in stacking and masonry views schemaColumns?: List; dockingConfig?: string; autoHeight?: boolean; + removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document dbDoc?: Doc; + onClick?: ScriptField; + onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop icon?: string; + gridGap?: number; // gap between items in masonry view + xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts + yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts + panel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script + targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script + convertToButtons?: boolean; // whether documents dropped onto a collection should be converted to buttons that will construct the dropped document // [key: string]: Opt; } @@ -457,6 +470,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Freeform }, id); } + export function LinearDocument(documents: Array, options: DocumentOptions, id?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Linear }, id); + } + export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 2c5992259..b05966bb5 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,10 +1,17 @@ import * as React from 'react'; import { Doc } from '../../new_fields/Doc'; import { computed, action } from 'mobx'; -import { Cast } from '../../new_fields/Types'; +import { Cast, BoolCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; +import { InkingControl } from './InkingControl'; +import { InkTool } from '../../new_fields/InkField'; -export function DocComponent

    (schemaCtor: (doc: Doc) => T) { + +/// DocComponents returns a generic base class for React views of document fields that are not interactive +interface DocComponentProps { + Document: Doc; +} +export function DocComponent

    (schemaCtor: (doc: Doc) => T) { class Component extends React.Component

    { //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then @computed @@ -15,6 +22,27 @@ export function DocComponent

    (schemaCtor: (doc: D return Component; } + +/// DocStaticProps return a base class for React views of document fields that are interactive only when selected (e.g. ColorBox) +interface DocStaticProps { + Document: Doc; + isSelected: () => boolean; + renderDepth: number; +} +export function DocStaticComponent

    (schemaCtor: (doc: Doc) => T) { + class Component extends React.Component

    { + //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then + @computed + get Document(): T { + return schemaCtor(this.props.Document); + } + active = () => (this.props.Document.forceActive || this.props.isSelected() || this.props.renderDepth === 0) && !InkingControl.Instance.selectedTool; + } + return Component; +} + + +/// DocAnnotatbleComponent return a base class for React views of document fields that are annotatable *and* interactive when selected (e.g., pdf, image) interface DocAnnotatableProps { Document: Doc; DataDoc?: Doc; @@ -57,7 +85,7 @@ export function DocAnnotatableComponent

    (schema return Doc.AddDocToList(this.extensionDoc, this.props.fieldExt, doc); } whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); - active = () => this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; + active = () => (InkingControl.Instance.selectedTool === InkTool.None) && (BoolCast(this.props.Document.forceActive) || this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0); } return Component; } \ No newline at end of file diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 38734a03d..d42d8d2d9 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -48,6 +48,14 @@ export class InkingControl extends React.Component { let selected = SelectionManager.SelectedDocuments(); let oldColors = selected.map(view => { let targetDoc = view.props.Document.layout instanceof Doc ? view.props.Document.layout : view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); + let sel = window.getSelection(); + if (StrCast(targetDoc.layout).indexOf("FormattedTextBox") !== -1 && (!sel || sel.toString() !== "")) { + targetDoc.color = this._selectedColor; + return { + target: targetDoc, + previous: StrCast(targetDoc.color) + }; + } let oldColor = StrCast(targetDoc.backgroundColor); let matchedColor = this._selectedColor; const cvd = view.props.ContainingCollectionDoc; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index ddea3e223..701f094e2 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -343,12 +343,12 @@ export class MainView extends React.Component { if (!(sidebarContent instanceof Doc)) { return (null); } - let libraryButtonDoc = Cast(CurrentUserUtils.UserDocument.libraryButtons, Doc) as Doc; - libraryButtonDoc.columnWidth = this.flyoutWidth / 3 - 30; + let sidebarButtonsDoc = Cast(CurrentUserUtils.UserDocument.sidebarButtons, Doc) as Doc; + sidebarButtonsDoc.columnWidth = this.flyoutWidth / 3 - 30; return

    { - Doc.AddDocToList(CurrentUserUtils.UserDocument, "docButtons", doc); + Doc.AddDocToList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); return true; } remButtonDoc = (doc: Doc) => { - Doc.RemoveDocFromList(CurrentUserUtils.UserDocument, "docButtons", doc); + Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); return true; } @computed get docButtons() { return
    - ; +const ColorDocument = makeInterface(documentSchema); @observer -export class ColorBox extends React.Component { +export class ColorBox extends DocStaticComponent(ColorDocument) { public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(ColorBox, fieldKey); } render() { - return
    + return
    e.button === 0 && !e.ctrlKey && e.stopPropagation()}>
    ; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index b05d0046c..181f37d36 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -43,7 +43,6 @@ import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './Format import React = require("react"); import { ContextMenuProps } from '../ContextMenuItem'; import { ContextMenu } from '../ContextMenu'; -import { TextShadowProperty } from 'csstype'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -490,7 +489,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe ); this._heightReactionDisposer = reaction( - () => this.props.Document[WidthSym](), + () => [this.props.Document[WidthSym](), this.props.Document.autoHeight], () => this.tryUpdateHeight() ); @@ -984,13 +983,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe @action tryUpdateHeight() { - const ChromeHeight = this.props.ChromeHeight; - let sh = this._ref.current ? this._ref.current.scrollHeight : 0; - if (!this.props.Document.isAnimating && this.props.Document.autoHeight && sh !== 0 && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { + let scrollHeight = this._ref.current ? this._ref.current.scrollHeight : 0; + if (!this.props.Document.isAnimating && this.props.Document.autoHeight && scrollHeight !== 0 && + getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation let nh = this.props.Document.isTemplate ? 0 : NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.props.Document.height, 0); - this.props.Document.height = Math.max(10, (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0)); - this.dataDoc.nativeHeight = nh ? sh : undefined; + this.props.Document.height = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0)); + this.dataDoc.nativeHeight = nh ? scrollHeight : undefined; } } diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 63b412a23..19797400f 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -115,7 +115,6 @@ export class PDFBox extends DocAnnotatableComponent private newScriptChange = (e: React.ChangeEvent) => this._scriptValue = e.currentTarget.value; whenActiveChanged = (isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive); - active = () => this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0; setPdfViewer = (pdfViewer: PDFViewer) => { this._pdfViewer = pdfViewer; }; searchStringChanged = (e: React.ChangeEvent) => this._searchString = e.currentTarget.value; @@ -205,7 +204,7 @@ export class PDFBox extends DocAnnotatableComponent _initialScale: number | undefined; // the initial scale of the PDF when first rendered which determines whether the document will be live on startup or not. Getting bigger after startup won't make it automatically be live.... render() { const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField); - let classname = "pdfBox-cont" + (InkingControl.Instance.selectedTool || !this.active ? "" : "-interactive"); + let classname = "pdfBox-cont" + (this.active() ? "-interactive" : ""); let noPdf = !(pdfUrl instanceof PdfField) || !this._pdf; if (this._initialScale === undefined) this._initialScale = this.props.ScreenToLocalTransform().Scale; if (this.props.isSelected() || this.props.Document.scrollY !== undefined) this._everActive = true; diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 73cac879e..8af6bbfd5 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,20 +1,17 @@ -import { action, computed, observable, runInAction, reaction } from "mobx"; +import { action, computed, observable, reaction, runInAction } from "mobx"; import * as rp from 'request-promise'; import { DocServer } from "../../../client/DocServer"; import { Docs } from "../../../client/documents/Documents"; import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea"; import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; -import { CollectionViewType } from "../../../client/views/collections/CollectionBaseView"; -import { CollectionView } from "../../../client/views/collections/CollectionView"; +import { UndoManager } from "../../../client/util/UndoManager"; import { Doc, DocListCast } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; -import { Cast, StrCast, PromiseValue } from "../../../new_fields/Types"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import { Cast, PromiseValue } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { RouteStore } from "../../RouteStore"; -import { ScriptField } from "../../../new_fields/ScriptField"; -import { ButtonBox } from "../../../client/views/nodes/ButtonBox"; -import { UndoManager } from "../../../client/util/UndoManager"; export class CurrentUserUtils { private static curr_id: string; @@ -22,176 +19,172 @@ export class CurrentUserUtils { private static mainDocId: string | undefined; public static get id() { return this.curr_id; } - @computed public static get UserDocument() { return Doc.UserDoc(); } public static get MainDocId() { return this.mainDocId; } public static set MainDocId(id: string | undefined) { this.mainDocId = id; } + @computed public static get UserDocument() { return Doc.UserDoc(); } @observable public static GuestTarget: Doc | undefined; @observable public static GuestWorkspace: Doc | undefined; private static createUserDocument(id: string): Doc { let doc = new Doc(id, true); - doc.viewType = CollectionViewType.Tree; - doc.layout = CollectionView.LayoutString(); doc.title = Doc.CurrentUserEmail; - doc.data = new List(); - doc.gridGap = 5; - doc.xMargin = 5; - doc.yMargin = 5; - doc.height = 42; - doc.boxShadow = "0 0"; - doc.convertToButtons = true; // for CollectionLinearView used as the docButton layout - doc.optionalRightCollection = Docs.Create.StackingDocument([], { title: "New mobile uploads" }); return this.updateUserDocument(doc);// this should be the last } - static updateUserDocument(doc: Doc) { + // a default set of note types .. not being used yet... + static setupNoteTypes(doc: Doc) { + let notes = [ + Docs.Create.TextDocument({ title: "Note", backgroundColor: "yellow", isTemplate: true }), + Docs.Create.TextDocument({ title: "Idea", backgroundColor: "pink", isTemplate: true }), + Docs.Create.TextDocument({ title: "Topic", backgroundColor: "lightBlue", isTemplate: true }), + Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplate: true }) + ]; + doc.noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", height: 75 }); + } - if (doc.undoBtn === undefined) { - doc.undoBtn = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "undo-alt" }); - (doc.undoBtn as Doc).onClick = ScriptField.MakeScript('undo()'); - Doc.AddDocToList(doc, "docButtons", doc.undoBtn as Doc); - } - if (doc.redoBtn === undefined) { - doc.redoBtn = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "redo-alt" }); - (doc.redoBtn as Doc).onClick = ScriptField.MakeScript('redo()'); - Doc.AddDocToList(doc, "docButtons", doc.redoBtn as Doc); - } + // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools + static setupCreatorButtons() { + let docProtoData = [ + { title: "collection", icon: "folder", script: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, + { title: "web page", icon: "globe-asia", script: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, + { title: "image", icon: "cat", script: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, + { title: "button", icon: "bolt", script: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, + { title: "presentation", icon: "tv", script: 'Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })' }, + { title: "import folder", icon: "cloud-upload-alt", script: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })' }, + ]; + return docProtoData.map(data => Docs.Create.FontIconDocument({ + nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, + title: data.title, icon: data.icon, onDragStart: ScriptField.MakeFunction(data.script) + })); + } + + // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. when clicked, this panel will be displayed in the target container (ie, sidebarContainer) + static setupCreatePanel(sidebarContainer: Doc) { + // setup a masonry view of all he creators + const dragCreators = Docs.Create.MasonryDocument(CurrentUserUtils.setupCreatorButtons(), { + width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons" + }); + // setup a color picker + const color = Docs.Create.ColorDocument({ + title: "color picker", width: 400, removeDropProperties: new List(["dropAction", "forceActive"]) + }); + color.dropAction = "alias"; // these must be set on the view document so they can't be part of the creator above. + color.forceActive = true; + + return Docs.Create.ButtonDocument({ + width: 35, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Create", targetContainer: sidebarContainer, + panel: Docs.Create.StackingDocument([dragCreators, color], { + width: 500, height: 800, chromeStatus: "disabled", title: "creator stack" + }), + onClick: ScriptField.MakeScript("this.targetContainer.proto = this.panel") + }); + } + + // setup the Library button which will display the library panel. This panel includes a collection of workspaces, documents, and recently closed views + static setupLibraryPanel(sidebarContainer: Doc, doc: Doc) { // setup workspaces library item - if (doc.workspaces === undefined) { - const workspaces = Docs.Create.TreeDocument([], { title: "WORKSPACES", height: 100 }); - workspaces.boxShadow = "0 0"; - doc.workspaces = workspaces; - } - PromiseValue(Cast(doc.workspaces, Doc)).then(workspaces => { - if (workspaces) { - workspaces.backgroundColor = "#eeeeee"; - workspaces.preventTreeViewOpen = true; - workspaces.forceActive = true; - workspaces.lockedPosition = true; - if (StrCast(workspaces.title) === "Workspaces") { - workspaces.title = "WORKSPACES"; - } - } + doc.workspaces = Docs.Create.TreeDocument([], { + title: "WORKSPACES", height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, backgroundColor: "#eeeeee" }); - // setup notes list - if (doc.noteTypes === undefined) { - let notes = [Docs.Create.TextDocument({ title: "Note", backgroundColor: "yellow", isTemplate: true }), - Docs.Create.TextDocument({ title: "Idea", backgroundColor: "pink", isTemplate: true }), - Docs.Create.TextDocument({ title: "Topic", backgroundColor: "lightBlue", isTemplate: true }), - Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplate: true })]; - const noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", height: 75 }); - doc.noteTypes = noteTypes; - } - PromiseValue(Cast(doc.noteTypes, Doc)).then(noteTypes => noteTypes && PromiseValue(noteTypes.data).then(DocListCast)); + doc.documents = Docs.Create.TreeDocument([], { + title: "DOCUMENTS", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", backgroundColor: "#eeeeee", preventTreeViewOpen: true, forceActive: true, lockedPosition: true + }); // setup Recently Closed library item - if (doc.recentlyClosed === undefined) { - const recentlyClosed = Docs.Create.TreeDocument([], { title: "Recently Closed".toUpperCase(), height: 75 }); - recentlyClosed.boxShadow = "0 0"; - doc.recentlyClosed = recentlyClosed; - } - PromiseValue(Cast(doc.recentlyClosed, Doc)).then(recent => { - if (recent) { - recent.backgroundColor = "#eeeeee"; - recent.preventTreeViewOpen = true; - recent.forceActive = true; - recent.lockedPosition = true; - if (StrCast(recent.title) === "Recently Closed") { - recent.title = "RECENTLY CLOSED"; - } - } + doc.recentlyClosed = Docs.Create.TreeDocument([], { + title: "Recently Closed".toUpperCase(), height: 75, boxShadow: "0 0", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, backgroundColor: "#eeeeee" }); + return Docs.Create.ButtonDocument({ + width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Library", + panel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { + title: "Library", xMargin: 5, yMargin: 5, gridGap: 5, forceActive: true, dropAction: "alias", lockedPosition: true + }), + targetContainer: sidebarContainer, + onClick: ScriptField.MakeScript("this.targetContainer.proto = this.panel") + }); + } - if (doc.curPresentation === undefined) { - const curPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation" }); - curPresentation.boxShadow = "0 0"; - doc.curPresentation = curPresentation; - } + // setup the Search button which will display the search panel. + static setupSearchPanel(sidebarContainer: Doc) { + return Docs.Create.ButtonDocument({ + width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Search", + panel: Docs.Create.QueryDocument({ + title: "search stack", ignoreClick: true + }), + targetContainer: sidebarContainer, + onClick: ScriptField.MakeScript("this.targetContainer.proto = this.panel") + }); + } - if (doc.Library === undefined) { - let Search = Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Search" }); - let Library = Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Library" }); - let Create = Docs.Create.ButtonDocument({ width: 35, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Create" }); - if (doc.sidebarContainer === undefined) { - doc.sidebarContainer = new Doc(); - (doc.sidebarContainer as Doc).chromeStatus = "disabled"; - } + // setup the list of sidebar mode buttons which determine what is displayed in the sidebar + static setupSidebarButtons(doc: Doc) { + doc.sidebarContainer = new Doc(); + (doc.sidebarContainer as Doc).chromeStatus = "disabled"; - const library = Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { title: "Library" }); - library.forceActive = true; - library.lockedPosition = true; - library.gridGap = 5; - library.xMargin = 5; - library.yMargin = 5; - library.dropAction = "alias"; - Library.targetContainer = doc.sidebarContainer; - Library.library = library; - Library.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.library"); + doc.CreateBtn = this.setupCreatePanel(doc.sidebarContainer as Doc); + doc.LibraryBtn = this.setupLibraryPanel(doc.sidebarContainer as Doc, doc); + doc.SearchBtn = this.setupSearchPanel(doc.sidebarContainer as Doc); - const searchBox = Docs.Create.QueryDocument({ title: "search stack" }); - searchBox.ignoreClick = true; - Search.searchBox = searchBox; - Search.targetContainer = doc.sidebarContainer; - Search.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.searchBox"); + // Finally, setup the list of buttons to display in the sidebar + doc.sidebarButtons = Docs.Create.StackingDocument([doc.SearchBtn as Doc, doc.LibraryBtn as Doc, doc.CreateBtn as Doc], { + width: 500, height: 80, boxShadow: "0 0", sectionFilter: "title", hideHeadings: true, ignoreClick: true, + backgroundColor: "lightgrey", chromeStatus: "disabled", title: "library stack" + }); + } - let createCollection = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Collection", icon: "folder" }); - createCollection.onDragStart = ScriptField.MakeFunction('Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })'); - let createWebPage = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Web Page", icon: "globe-asia" }); - createWebPage.onDragStart = ScriptField.MakeFunction('Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })'); - let createCatImage = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Image", icon: "cat" }); - createCatImage.onDragStart = ScriptField.MakeFunction('Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })'); - let createButton = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Button", icon: "bolt" }); - createButton.onDragStart = ScriptField.MakeFunction('Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })'); - let createPresentation = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Presentation", icon: "tv" }); - createPresentation.onDragStart = ScriptField.MakeFunction('Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })'); - let createFolderImport = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, title: "Import Folder", icon: "cloud-upload-alt" }); - createFolderImport.onDragStart = ScriptField.MakeFunction('Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })'); - const dragCreators = Docs.Create.MasonryDocument([createCollection, createWebPage, createCatImage, createButton, createPresentation, createFolderImport], { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons" }); - const color = Docs.Create.ColorDocument({ title: "color picker", width: 400 }); - color.dropAction = "alias"; - color.ignoreClick = true; - color.removeDropProperties = new List(["dropAction", "ignoreClick"]); - const creators = Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "creator stack" }); - Create.targetContainer = doc.sidebarContainer; - Create.creators = creators; - Create.onClick = ScriptField.MakeScript("this.targetContainer.proto = this.creators"); + /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window + static setupExpandingButtons(doc: Doc) { + doc.undoBtn = Docs.Create.FontIconDocument( + { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" }); + doc.redoBtn = Docs.Create.FontIconDocument( + { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" }); - const libraryButtons = Docs.Create.StackingDocument([Search, Library, Create], { width: 500, height: 80, chromeStatus: "disabled", title: "library stack" }); - libraryButtons.sectionFilter = "title"; - libraryButtons.boxShadow = "0 0"; - libraryButtons.ignoreClick = true; - libraryButtons.hideHeadings = true; - libraryButtons.backgroundColor = "lightgrey"; + doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { + title: "expanding buttons", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", + backgroundColor: "#eeeeee", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, convertToButtons: true + }); + } - doc.libraryButtons = libraryButtons; - doc.Library = Library; - doc.Create = Create; - doc.Search = Search; - } - PromiseValue(Cast(doc.libraryButtons, Doc)).then(libraryButtons => { }); - PromiseValue(Cast(doc.Library, Doc)).then(library => library && library.library && library.targetContainer && (library.onClick as ScriptField).script.run({ this: library })); - PromiseValue(Cast(doc.Create, Doc)).then(async create => create && create.creators && create.targetContainer); - PromiseValue(Cast(doc.Search, Doc)).then(async search => search && search.searchBox && search.targetContainer); + // sets up the default set of documents to be shown in the Overlay layer + static setupOverlays(doc: Doc) { + doc.overlays = Docs.Create.FreeformDocument([], { title: "Overlays", backgroundColor: "#aca3a6" }); + doc.linkFollowBox = Docs.Create.LinkFollowBoxDocument({ x: 250, y: 20, width: 500, height: 370, title: "Link Follower" }); + Doc.AddDocToList(doc.overlays as Doc, "data", doc.linkFollowBox as Doc); + } - if (doc.overlays === undefined) { - const overlays = Docs.Create.FreeformDocument([], { title: "Overlays" }); - Doc.GetProto(overlays).backgroundColor = "#aca3a6"; - doc.overlays = overlays; - } + // the initial presentation Doc to use + static setupDefaultPresentation(doc: Doc) { + doc.curPresentation = Docs.Create.PresDocument(new List(), { title: "Presentation", boxShadow: "0 0" }); + } - if (doc.linkFollowBox === undefined) { - PromiseValue(Cast(doc.overlays, Doc)).then(overlays => overlays && Doc.AddDocToList(overlays, "data", doc.linkFollowBox = Docs.Create.LinkFollowBoxDocument({ x: 250, y: 20, width: 500, height: 370, title: "Link Follower" }))); - } + static setupMobileUploads(doc: Doc) { + doc.optionalRightCollection = Docs.Create.StackingDocument([], { title: "New mobile uploads" }); + } + + static updateUserDocument(doc: Doc) { + (doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc); + (doc.noteTypes === undefined) && CurrentUserUtils.setupNoteTypes(doc); + (doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc); + (doc.expandingButtons === undefined) && CurrentUserUtils.setupExpandingButtons(doc); + (doc.curPresentation === undefined) && CurrentUserUtils.setupDefaultPresentation(doc); + (doc.sidebarButtons === undefined) && CurrentUserUtils.setupSidebarButtons(doc); + + // this is equivalent to using PrefetchProxies to make sure all the sidebarButtons and noteType internal Doc's have been retrieved. + PromiseValue(Cast(doc.noteTypes, Doc)).then(noteTypes => noteTypes && PromiseValue(noteTypes.data).then(DocListCast)); + PromiseValue(Cast(doc.sidebarButtons, Doc)).then(stackingDoc => { + stackingDoc && PromiseValue(Cast(stackingDoc.data, listSpec(Doc))).then(sidebarButtons => { + sidebarButtons && sidebarButtons.map((sidebarBtn, i) => { + sidebarBtn && PromiseValue(Cast(sidebarBtn, Doc)).then(async btn => { + btn && btn.panel && btn.targetContainer && i === 1 && (btn.onClick as ScriptField).script.run({ this: btn }); + }); + }); + }); + }); - doc.title = "DOCUMENTS"; - doc.backgroundColor = "#eeeeee"; - doc.width = 100; - doc.preventTreeViewOpen = true; - doc.forceActive = true; - doc.lockedPosition = true; + // setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet doc.undoBtn && reaction(() => UndoManager.undoStack.slice(), () => (doc.undoBtn as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true }); doc.redoBtn && reaction(() => UndoManager.redoStack.slice(), () => (doc.redoBtn as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); @@ -215,12 +208,8 @@ export class CurrentUserUtils { await rp.get(Utils.prepend(RouteStore.getUserDocumentId)).then(id => { if (id && id !== "guest") { return DocServer.GetRefField(id).then(async field => { - if (field instanceof Doc) { - await this.updateUserDocument(field); - runInAction(() => Doc.SetUserDoc(field)); - } else { - runInAction(() => Doc.SetUserDoc(this.createUserDocument(id))); - } + let userDoc = field instanceof Doc ? await this.updateUserDocument(field) : this.createUserDocument(id); + runInAction(() => Doc.SetUserDoc(userDoc)); }); } else { throw new Error("There should be a user id! Why does Dash think there isn't one?"); -- cgit v1.2.3-70-g09d2 From 03f86e3b7b450699073c47aa43af23d31e0765d4 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 15 Oct 2019 13:42:13 -0400 Subject: extensions for linearViews or nesting. --- src/client/documents/Documents.ts | 2 +- src/client/views/CollectionLinearView.scss | 24 +++--- src/client/views/CollectionLinearView.tsx | 88 +++++++++++----------- src/client/views/DocComponent.tsx | 2 +- src/client/views/InkingControl.tsx | 58 +++++--------- src/client/views/MainView.tsx | 80 ++++++++++++-------- src/client/views/collections/CollectionSubView.tsx | 1 - src/client/views/nodes/DocumentView.tsx | 15 ++-- src/client/views/nodes/FontIconBox.tsx | 5 +- .../authentication/models/current_user_utils.ts | 26 ++++--- 10 files changed, 154 insertions(+), 147 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 5794a6bee..6df172f46 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -471,7 +471,7 @@ export namespace Docs { } export function LinearDocument(documents: Array, options: DocumentOptions, id?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Linear }, id); + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Linear }, id); } export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { diff --git a/src/client/views/CollectionLinearView.scss b/src/client/views/CollectionLinearView.scss index 4bfd88b69..4423a7020 100644 --- a/src/client/views/CollectionLinearView.scss +++ b/src/client/views/CollectionLinearView.scss @@ -4,26 +4,25 @@ .collectionLinearView-outer{ overflow: hidden; height:100%; - padding:5px; .collectionLinearView { display:flex; + height: 100%; >label { background: $dark-color; color: $light-color; display: inline-block; border-radius: 18px; - font-size: 25px; - width: 36px; - height: 36px; - margin-right: 10px; + font-size: 12.5px; + width: 18px; + height: 18px; + margin-top:auto; + margin-bottom:auto; cursor: pointer; transition: transform 0.2s; } label p { - padding-left: 10.5px; - width: 500px; - height: 500px; + padding-left:5px; } label:hover { @@ -47,20 +46,21 @@ .collectionLinearView-content { display: flex; opacity: 1; - padding: 0; position: relative; + margin-top: auto; .collectionLinearView-docBtn, .collectionLinearView-docBtn-scalable { position:relative; - margin-right: 10px; + margin-top: auto; + margin-bottom: auto; } .collectionLinearView-docBtn-scalable:hover { transform: scale(1.15); } .collectionLinearView-round-button { - width: 36px; - height: 36px; + width: 18px; + height: 18px; border-radius: 18px; font-size: 15px; } diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 5c793f784..9d1dd7749 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -1,23 +1,20 @@ -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable, computed, IReactionDisposer, reaction } from 'mobx'; +import { action, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, DocListCast, Opt, HeightSym } from '../../new_fields/Doc'; -import { InkTool } from '../../new_fields/InkField'; +import { Doc, HeightSym, WidthSym } from '../../new_fields/Doc'; import { ObjectField } from '../../new_fields/ObjectField'; +import { makeInterface } from '../../new_fields/Schema'; import { ScriptField } from '../../new_fields/ScriptField'; -import { NumCast, StrCast } from '../../new_fields/Types'; -import { emptyFunction, returnEmptyString, returnOne, returnTrue, returnFalse, Utils } from '../../Utils'; +import { BoolCast, NumCast, StrCast } from '../../new_fields/Types'; +import { emptyFunction, returnEmptyString, returnOne, returnTrue, Utils } from '../../Utils'; import { Docs } from '../documents/Documents'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; -import { UndoManager } from '../util/UndoManager'; -import { InkingControl } from './InkingControl'; -import { DocumentView, documentSchema } from './nodes/DocumentView'; import "./CollectionLinearView.scss"; -import { makeInterface } from '../../new_fields/Schema'; +import { CollectionViewType } from './collections/CollectionBaseView'; import { CollectionSubView } from './collections/CollectionSubView'; -import { DocumentType } from '../documents/DocumentTypes'; +import { documentSchema, DocumentView } from './nodes/DocumentView'; +import { translate } from 'googleapis/build/src/apis/translate'; type LinearDocument = makeInterface<[typeof documentSchema,]>; @@ -26,7 +23,6 @@ const LinearDocument = makeInterface(documentSchema); @observer export class CollectionLinearView extends CollectionSubView(LinearDocument) { @observable public addMenuToggle = React.createRef(); - @observable private _checked = false; private _dropDisposer?: DragManager.DragDropDisposer; private _heightDisposer?: IReactionDisposer; @@ -37,12 +33,8 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { componentDidMount() { // is there any reason this needs to exist? -syip. yes, it handles autoHeight for stacking views (masonry isn't yet supported). - this._heightDisposer = reaction(() => NumCast(this.props.Document.height, 0) + this.childDocs.length + (this._checked ? 1 : 0), - () => { - if (true || this.props.Document.fitWidth) { - this.props.Document.width = 36 + (this._checked ? this.childDocs.length * (this.props.Document[HeightSym]() + 10) : 10); - } - }, + this._heightDisposer = reaction(() => NumCast(this.props.Document.height, 0) + this.childDocs.length + (this.props.Document.isExpanded ? 1 : 0), + () => this.props.Document.width = 18 + (this.props.Document.isExpanded ? this.childDocs.length * (this.props.Document[HeightSym]()) : 10), { fireImmediately: true } ); } @@ -56,11 +48,13 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { let dbox = doc; - if (!doc.onDragStart && this.props.Document.convertToButtons) { + if (!doc.onDragStart && this.props.Document.convertToButtons && doc.viewType !== CollectionViewType.Linear) { dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); dbox.dragFactory = doc; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); + } else if (doc.viewType === CollectionViewType.Linear) { + dbox.ignoreClick = true; } (de.data as DragManager.DocumentDragData).droppedDocuments[i] = dbox; }); @@ -68,40 +62,51 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { return super.drop(e, de); }); - selected = (tool: InkTool) => { - if (!InkingControl.Instance || InkingControl.Instance.selectedTool === InkTool.None) return { display: "none" }; - if (InkingControl.Instance.selectedTool === tool) { - return { color: "#61aaa3", fontSize: "50%" }; - } - return { fontSize: "50%" }; - } - public isCurrent(doc: Doc) { return !doc.isMinimized && (Math.abs(NumCast(doc.displayTimecode, -1) - NumCast(this.Document.currentTimecode, -1)) < 1.5 || NumCast(doc.displayTimecode, -1) === -1); } - dimension = () => NumCast(this.props.Document.height) - 5; + dimension = () => NumCast(this.props.Document.height); // 2 * the padding + getTransform = (ele: React.RefObject) => () => { + if (!ele.current) return Transform.Identity(); + let { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current); + return new Transform(-translateX, -translateY, 1 / scale); + }; + _spacing = 20; render() { let guid = Utils.GenerateGuid(); return
    - this._checked = this.addMenuToggle.current!.checked)} /> - + this.props.Document.isExpanded = this.addMenuToggle.current!.checked)} /> +
    - {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => -
    + {this.childLayoutPairs.filter(pair => this.isCurrent(pair.layout)).map(pair => { + let nested = pair.layout.viewType === CollectionViewType.Linear; + let dref = React.createRef(); + let nativeWidth = NumCast(pair.layout.nativeWidth, this.dimension()); + let scalingContent = nested ? 1 : this.dimension() / (this._spacing + nativeWidth); + let scalingBox = nested ? 1 : this.dimension() / nativeWidth; + let deltaSize = nativeWidth * scalingBox - nativeWidth * scalingContent; + return
    this.dimension() / (10 + NumCast(pair.layout.nativeWidth, this.dimension()))} // ugh - need to get rid of this inline function to avoid recomputing - PanelWidth={this.dimension} - PanelHeight={this.dimension} + ScreenToLocalTransform={this.getTransform(dref)} + ContentScaling={() => scalingContent} // ugh - need to get rid of this inline function to avoid recomputing + PanelWidth={() => nested ? pair.layout[WidthSym]() : this.dimension()} + PanelHeight={() => nested ? pair.layout[HeightSym]() : this.dimension()} renderDepth={this.props.renderDepth + 1} focus={emptyFunction} backgroundColor={returnEmptyString} @@ -113,15 +118,10 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { zoomToScale={emptyFunction} getScale={returnOne}> -
    )} +
    + })} {/*
  • */} - {this.props.showHiddenControls ? <> - - - - - - : (null)} +
    ; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index b05966bb5..fbc27192c 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -36,7 +36,7 @@ export function DocStaticComponent

    (schemaCtor: (doc get Document(): T { return schemaCtor(this.props.Document); } - active = () => (this.props.Document.forceActive || this.props.isSelected() || this.props.renderDepth === 0) && !InkingControl.Instance.selectedTool; + active = () => (this.props.Document.forceActive || this.props.isSelected() || this.props.renderDepth === 0);// && !InkingControl.Instance.selectedTool; // bcz: inking state shouldn't affect static tools } return Component; } diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index d42d8d2d9..41dec9f83 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -1,38 +1,30 @@ -import { observable, action, computed, runInAction } from "mobx"; +import { action, computed, observable } from "mobx"; import { ColorResult } from 'react-color'; -import React = require("react"); -import { observer } from "mobx-react"; -import "./InkingControl.scss"; -import { library } from '@fortawesome/fontawesome-svg-core'; -import { faPen, faHighlighter, faEraser, faBan } from '@fortawesome/free-solid-svg-icons'; -import { SelectionManager } from "../util/SelectionManager"; -import { InkTool } from "../../new_fields/InkField"; import { Doc } from "../../new_fields/Doc"; -import { undoBatch, UndoManager } from "../util/UndoManager"; -import { StrCast, NumCast, Cast } from "../../new_fields/Types"; -import { listSpec } from "../../new_fields/Schema"; +import { InkTool } from "../../new_fields/InkField"; import { List } from "../../new_fields/List"; +import { listSpec } from "../../new_fields/Schema"; +import { Cast, NumCast, StrCast } from "../../new_fields/Types"; import { Utils } from "../../Utils"; +import { Scripting } from "../util/Scripting"; +import { SelectionManager } from "../util/SelectionManager"; +import { undoBatch, UndoManager } from "../util/UndoManager"; -library.add(faPen, faHighlighter, faEraser, faBan); -@observer -export class InkingControl extends React.Component { +export class InkingControl { @observable static Instance: InkingControl; @observable private _selectedTool: InkTool = InkTool.None; @observable private _selectedColor: string = "rgb(244, 67, 54)"; @observable private _selectedWidth: string = "5"; @observable public _open: boolean = false; - constructor(props: Readonly<{}>) { - super(props); - runInAction(() => InkingControl.Instance = this); + constructor() { + InkingControl.Instance = this; } - @action - switchTool = (tool: InkTool): void => { + switchTool = action((tool: InkTool): void => { this._selectedTool = tool; - } + }) decimalToHexString(number: number) { if (number < 0) { number = 0xFFFFFFFF + number + 1; @@ -124,22 +116,10 @@ export class InkingControl extends React.Component { return this._selectedWidth; } - @action - toggleDisplay = () => { - this._open = !this._open; - this.switchTool(this._open ? InkTool.Pen : InkTool.None); - } - render() { - return ( -

      -
    • - - ) => this.switchWidth(e.target.value)} /> - ) => this.switchWidth(e.target.value)} /> -
    • -
    - ); - } -} \ No newline at end of file +} +Scripting.addGlobal(function activatePen() { return InkingControl.Instance.switchTool(InkTool.Pen); }); +Scripting.addGlobal(function activateBrush() { return InkingControl.Instance.switchTool(InkTool.Highlighter); }); +Scripting.addGlobal(function activateEraser() { return InkingControl.Instance.switchTool(InkTool.Eraser); }); +Scripting.addGlobal(function deactivateInk() { return InkingControl.Instance.switchTool(InkTool.None); }); +Scripting.addGlobal(function setInkWidth(width: any) { return InkingControl.Instance.switchWidth(width); }); +Scripting.addGlobal(function setInkColor(color: any) { return InkingControl.Instance.updateSelectedColor(color); }); \ No newline at end of file diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 701f094e2..4e06763a4 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,8 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, faMusic, faObjectGroup, faPause, faPenNib, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faTv, faUndoAlt } from '@fortawesome/free-solid-svg-icons'; +import { + faArrowDown, faArrowUp, faBolt, faCaretUp, faCat, faCheck, faChevronRight, faClone, faCloudUploadAlt, faCommentAlt, faCut, faEllipsisV, faExclamation, faFilePdf, faFilm, faFont, faGlobeAsia, faLongArrowAltRight, + faMusic, faObjectGroup, faPause, faPenNib, faPen, faEraser, faPlay, faPortrait, faRedoAlt, faThumbtack, faTree, faTv, faUndoAlt +} from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, reaction, runInAction } from 'mobx'; import { observer } from 'mobx-react'; @@ -99,6 +102,8 @@ export class MainView extends React.Component { library.add(faGlobeAsia); library.add(faUndoAlt); library.add(faRedoAlt); + library.add(faPen); + library.add(faEraser); library.add(faPenNib); library.add(faFilm); library.add(faMusic); @@ -450,37 +455,50 @@ export class MainView extends React.Component { Doc.RemoveDocFromList(CurrentUserUtils.UserDocument.expandingButtons as Doc, "data", doc); return true; } + @action + moveButtonDoc = (doc: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean): boolean => { + return this.remButtonDoc(doc) && addDocument(doc); + } + buttonBarXf = () => { + if (!this._docBtnRef.current) return Transform.Identity(); + let { scale, translateX, translateY } = Utils.GetScreenTransform(this._docBtnRef.current); + return new Transform(-translateX, -translateY, 1 / scale); + } + _docBtnRef = React.createRef(); @computed get docButtons() { - return
    - - -
    ; + console.log("stuff = " + this.flyoutWidthFunc() + " " + this.getContentsHeight()); + if (CurrentUserUtils.UserDocument.expandingButtons instanceof Doc) { + return
    + + +
    ; + } + return (null); } render() { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 6e8e4fa12..fdbe5339d 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -33,7 +33,6 @@ export interface CollectionViewProps extends FieldViewProps { VisibleHeight?: () => number; chromeCollapsed: boolean; setPreviewCursor?: (func: (x: number, y: number, drag: boolean) => void) => void; - showHiddenControls?: boolean; // hack for showing the undo/redo/ink controls in a linear view -- needs to be redone } export interface SubCollectionViewProps extends CollectionViewProps { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 62264ea38..c0e5185c1 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -39,6 +39,7 @@ import { ImageField } from '../../../new_fields/URLField'; import SharingManager from '../../util/SharingManager'; import { Scripting } from '../../util/Scripting'; import { DictationOverlay } from '../DictationOverlay'; +import { CollectionViewType } from '../collections/CollectionBaseView'; library.add(fa.faEdit); library.add(fa.faTrash); @@ -105,7 +106,7 @@ export const documentSchema = createSchema({ dropAction: "string", // override specifying what should happen when this document is dropped (can be "alias" or "copy") removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) - onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return an Doc to drag. + onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped. dragFactory: Doc, // the document that serves as the "template" for the onDragStart script ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents @@ -167,7 +168,7 @@ export class DocumentView extends DocComponent(Docu if (this._mainCont.current) { let dragData = new DragManager.DocumentDragData([this.props.Document]); const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); - dragData.offset = this.Document.onDragStart ? [0, 0] : this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); + dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); dragData.dropAction = dropAction; dragData.moveDocument = this.Document.onDragStart ? undefined : this.props.moveDocument; dragData.applyAsTemplate = applyAsTemplate; @@ -175,7 +176,7 @@ export class DocumentView extends DocComponent(Docu handlers: { dragComplete: action((emptyFunction)) }, - hideSource: !dropAction && !this.Document.onDragStart + hideSource: !dropAction && !this.Document.onDragStart && !this.Document.onClick }); } } @@ -249,7 +250,7 @@ export class DocumentView extends DocComponent(Docu this._hitTemplateDrag = true; } } - if ((this.active || this.Document.onDragStart) && e.button === 0 && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); + if ((this.active || this.Document.onDragStart || this.Document.onClick) && e.button === 0 && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation(); // events stop at the lowest document that is active. if right dragging, we let it go through though to allow for context menu clicks. PointerMove callbacks should remove themselves if the move event gets stopPropagated by a lower-level handler (e.g, marquee drag); document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointermove", this.onPointerMove); @@ -261,9 +262,9 @@ export class DocumentView extends DocComponent(Docu if (e.cancelBubble && this.active) { document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView) } - else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive() || this.Document.onDragStart) && !this.Document.lockedPosition && !this.Document.inOverlay) { + else if (!e.cancelBubble && (SelectionManager.IsSelected(this) || this.props.parentActive() || this.Document.onDragStart || this.Document.onClick) && !this.Document.lockedPosition && !this.Document.inOverlay) { if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) { - if (!e.altKey && (!this.topMost || this.Document.onDragStart) && e.buttons === 1) { + if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick) && e.buttons === 1) { document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined, this._hitTemplateDrag); @@ -684,7 +685,7 @@ export class DocumentView extends DocComponent(Docu color: StrCast(this.Document.color), outline: fullDegree && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", border: fullDegree && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, - background: backgroundColor, + background: this.props.Document.type === DocumentType.FONTICON || this.props.Document.viewType === CollectionViewType.Linear ? undefined : backgroundColor, width: animwidth, height: animheight, transform: `scale(${this.props.Document.fitWidth ? 1 : this.props.ContentScaling()})`, diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 3f5afb6d1..aa442cd92 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -5,6 +5,7 @@ import { createSchema, makeInterface } from '../../../new_fields/Schema'; import { DocComponent } from '../DocComponent'; import './FontIconBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; +import { StrCast } from '../../../new_fields/Types'; const FontIconSchema = createSchema({ icon: "string" }); @@ -16,6 +17,8 @@ export class FontIconBox extends DocComponent( public static LayoutString() { return FieldView.LayoutString(FontIconBox); } render() { - return ; + return ; } } \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 8af6bbfd5..c4b91dadd 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -12,6 +12,7 @@ import { ScriptField } from "../../../new_fields/ScriptField"; import { Cast, PromiseValue } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { RouteStore } from "../../RouteStore"; +import { InkingControl } from "../../../client/views/InkingControl"; export class CurrentUserUtils { private static curr_id: string; @@ -45,17 +46,21 @@ export class CurrentUserUtils { // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons() { - let docProtoData = [ - { title: "collection", icon: "folder", script: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, - { title: "web page", icon: "globe-asia", script: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, - { title: "image", icon: "cat", script: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, - { title: "button", icon: "bolt", script: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, - { title: "presentation", icon: "tv", script: 'Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })' }, - { title: "import folder", icon: "cloud-upload-alt", script: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })' }, + let docProtoData: { title: string, icon: string, drag?: string, click?: string }[] = [ + { title: "collection", icon: "folder", drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, + { title: "web page", icon: "globe-asia", drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, + { title: "image", icon: "cat", drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, + { title: "button", icon: "bolt", drag: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, + { title: "presentation", icon: "tv", drag: 'Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })' }, + { title: "import folder", icon: "cloud-upload-alt", drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })' }, + { title: "pen", icon: "pen-nib", click: 'activatePen(); setInkWidth(2);' }, + { title: "highlighter", icon: "pen", click: 'activateBrush(); setInkWidth(20);' }, + { title: "eraser", icon: "eraser", click: 'activateEraser();' }, + { title: "none", icon: "pause", click: 'deactivateInk();' }, ]; return docProtoData.map(data => Docs.Create.FontIconDocument({ - nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, - title: data.title, icon: data.icon, onDragStart: ScriptField.MakeFunction(data.script) + nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "alias" : undefined, + title: data.title, icon: data.icon, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined })); } @@ -144,7 +149,7 @@ export class CurrentUserUtils { doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { title: "expanding buttons", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", - backgroundColor: "#eeeeee", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, convertToButtons: true + backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, convertToButtons: true }); } @@ -165,6 +170,7 @@ export class CurrentUserUtils { } static updateUserDocument(doc: Doc) { + new InkingControl(); (doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc); (doc.noteTypes === undefined) && CurrentUserUtils.setupNoteTypes(doc); (doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc); -- cgit v1.2.3-70-g09d2 From 33811c112c7e479813908ba10f72813954a3e289 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 15 Oct 2019 16:25:10 -0400 Subject: working version of inking buttons --- src/client/documents/Documents.ts | 2 ++ src/client/util/DragManager.ts | 4 +-- src/client/util/SelectionManager.ts | 11 -------- src/client/views/CollectionLinearView.tsx | 4 +-- src/client/views/InkingControl.tsx | 6 ++-- src/client/views/MainView.tsx | 6 ++-- src/client/views/nodes/ColorBox.tsx | 33 ++++++++++++++++++++-- src/client/views/nodes/DocumentView.tsx | 7 +++-- src/client/views/nodes/FontIconBox.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 16 ++++++----- src/new_fields/Doc.ts | 4 +++ .../authentication/models/current_user_utils.ts | 31 +++++++++++--------- 12 files changed, 78 insertions(+), 48 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 6df172f46..f4fce34ac 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -93,6 +93,8 @@ export interface DocumentOptions { autoHeight?: boolean; removeDropProperties?: List; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document dbDoc?: Doc; + unchecked?: ScriptField; // returns whether a check box is unchecked + activePen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts) onClick?: ScriptField; onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop icon?: string; diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 169f2edec..92666c03c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -234,9 +234,9 @@ export namespace DragManager { export let StartDragFunctions: (() => void)[] = []; - export async function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { + export function StartDocumentDrag(eles: HTMLElement[], dragData: DocumentDragData, downX: number, downY: number, options?: DragOptions) { runInAction(() => StartDragFunctions.map(func => func())); - await dragData.draggedDocuments.map(d => d.dragFactory); + dragData.draggedDocuments.map(d => d.dragFactory); // does this help? trying to make sure the dragFactory Doc is loaded StartDrag(eles, dragData, downX, downY, options, options && options.finishDrag ? options.finishDrag : (dropData: { [id: string]: any }) => { (dropData.droppedDocuments = diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index df1b46b33..2d717ca57 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -45,17 +45,6 @@ export namespace SelectionManager { } const manager = new Manager(); - reaction(() => manager.SelectedDocuments, sel => { - let targetColor = "#FFFFFF"; - if (sel.length > 0) { - let firstView = sel[0]; - let doc = firstView.props.Document; - let targetDoc = doc.isTemplate ? doc : Doc.GetProto(doc); - let stored = StrCast(targetDoc.backgroundColor); - stored.length > 0 && (targetColor = stored); - } - InkingControl.Instance.updateSelectedColor(targetColor); - }, { fireImmediately: true }); export function DeselectDoc(docView: DocumentView): void { manager.DeselectDoc(docView); diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 9d1dd7749..eb3c768d0 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -48,7 +48,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { let dbox = doc; - if (!doc.onDragStart && this.props.Document.convertToButtons && doc.viewType !== CollectionViewType.Linear) { + if (!doc.onDragStart && !doc.onClick && this.props.Document.convertToButtons && doc.viewType !== CollectionViewType.Linear) { dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: "bolt" }); dbox.dragFactory = doc; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; @@ -90,7 +90,7 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { return
    (); @computed get docButtons() { - console.log("stuff = " + this.flyoutWidthFunc() + " " + this.getContentsHeight()); if (CurrentUserUtils.UserDocument.expandingButtons instanceof Doc) { - return
    + return
    ; const ColorDocument = makeInterface(documentSchema); @@ -14,9 +17,35 @@ const ColorDocument = makeInterface(documentSchema); @observer export class ColorBox extends DocStaticComponent(ColorDocument) { public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(ColorBox, fieldKey); } + _selectedDisposer: IReactionDisposer | undefined; + componentDidMount() { + this._selectedDisposer = reaction(() => SelectionManager.SelectedDocuments(), + action(() => this._startupColor = SelectionManager.SelectedDocuments().length ? StrCast(SelectionManager.SelectedDocuments()[0].Document.backgroundColor, "black") : "black"), + { fireImmediately: true }); + + // compare to this reaction that used to be in Selection Manager + // reaction(() => manager.SelectedDocuments, sel => { + // let targetColor = "#FFFFFF"; + // if (sel.length > 0) { + // let firstView = sel[0]; + // let doc = firstView.props.Document; + // let targetDoc = doc.isTemplate ? doc : Doc.GetProto(doc); + // let stored = StrCast(targetDoc.backgroundColor); + // stored.length > 0 && (targetColor = stored); + // } + // InkingControl.Instance.updateSelectedColor(targetColor); + // }, { fireImmediately: true }); + } + componentWillUnmount() { + this._selectedDisposer && this._selectedDisposer(); + } + + @observable _startupColor = "black"; + render() { - return
    e.button === 0 && !e.ctrlKey && e.stopPropagation()}> - + return
    e.button === 0 && !e.ctrlKey && e.stopPropagation()}> +
    ; } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c0e5185c1..6f99c541f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -107,7 +107,7 @@ export const documentSchema = createSchema({ removeDropProperties: listSpec("string"), // properties that should be removed from the alias/copy/etc of this document when it is dropped onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped. - dragFactory: Doc, // the document that serves as the "template" for the onDragStart script + dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents isTemplate: "boolean", // whether this document acts as a template layout for describing how other documents should be displayed @@ -676,6 +676,7 @@ export class DocumentView extends DocComponent(Docu const highlightColors = ["transparent", "maroon", "maroon", "yellow", "magenta", "cyan", "orange"]; const highlightStyles = ["solid", "dashed", "solid", "solid", "solid", "solid", "solid", "solid"]; + let highlighting = fullDegree && this.props.Document.type !== DocumentType.FONTICON && this.props.Document.viewType !== CollectionViewType.Linear return (
    (Docu transition: this.props.Document.isAnimating !== undefined ? ".5s linear" : StrCast(this.Document.transition), pointerEvents: this.Document.isBackground && !this.isSelected() ? "none" : "all", color: StrCast(this.Document.color), - outline: fullDegree && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", - border: fullDegree && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, + outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px", + border: highlighting && borderRounding ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined, background: this.props.Document.type === DocumentType.FONTICON || this.props.Document.viewType === CollectionViewType.Linear ? undefined : backgroundColor, width: animwidth, height: animheight, diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index aa442cd92..efe47d8a8 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -18,7 +18,7 @@ export class FontIconBox extends DocComponent( render() { return ; } } \ No newline at end of file diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 181f37d36..1bdff3ec7 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -927,16 +927,18 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onMouseUp = (e: React.MouseEvent): void => { e.stopPropagation(); - // this interposes on prosemirror's upHandler to prevent prosemirror's up from invoked multiple times when there are nested prosemirrors. We only want the lowest level prosemirror to be invoked. - if ((this._editorView as any).mouseDown) { - let originalUpHandler = (this._editorView as any).mouseDown.up; - (this._editorView as any).root.removeEventListener("mouseup", originalUpHandler); - (this._editorView as any).mouseDown.up = (e: MouseEvent) => { + let view = this._editorView as any; + // this interposes on prosemirror's upHandler to prevent prosemirror's up from invoked multiple times when there + // are nested prosemirrors. We only want the lowest level prosemirror to be invoked. + if (view.mouseDown) { + let originalUpHandler = view.mouseDown.up; + view.root.removeEventListener("mouseup", originalUpHandler); + view.mouseDown.up = (e: MouseEvent) => { !(e as any).formattedHandled && originalUpHandler(e); - e.stopPropagation(); + // e.stopPropagation(); (e as any).formattedHandled = true; }; - (this._editorView as any).root.addEventListener("mouseup", (this._editorView as any).mouseDown.up); + view.root.addEventListener("mouseup", view.mouseDown.up); } } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 4bed113e3..276596fb8 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -525,6 +525,7 @@ export namespace Doc { export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc { const copy = new Doc(copyProtoId, true); Object.keys(doc).forEach(key => { + let cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const field = ProxyField.WithoutProxy(() => doc[key]); if (key === "proto" && copyProto) { if (doc[key] instanceof Doc) { @@ -533,6 +534,8 @@ export namespace Doc { } else { if (field instanceof RefField) { copy[key] = field; + } else if (cfield instanceof ComputedField) { + copy[key] = ComputedField.MakeFunction(cfield.script.originalScript); } else if (field instanceof ObjectField) { copy[key] = ObjectField.MakeCopy(field); } else if (field instanceof Promise) { @@ -735,5 +738,6 @@ Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return Doc.Make Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); Scripting.addGlobal(function aliasDocs(field: any) { return new List(field.map((d: any) => Doc.MakeAlias(d))); }); Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); +Scripting.addGlobal(function sameDocs(doc1: any, doc2: any) { return Doc.AreProtosEqual(doc1, doc2) }); Scripting.addGlobal(function undo() { return UndoManager.Undo(); }); Scripting.addGlobal(function redo() { return UndoManager.Redo(); }); \ No newline at end of file diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index c4b91dadd..3c4a46ed8 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -8,7 +8,7 @@ import { UndoManager } from "../../../client/util/UndoManager"; import { Doc, DocListCast } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; -import { ScriptField } from "../../../new_fields/ScriptField"; +import { ScriptField, ComputedField } from "../../../new_fields/ScriptField"; import { Cast, PromiseValue } from "../../../new_fields/Types"; import { Utils } from "../../../Utils"; import { RouteStore } from "../../RouteStore"; @@ -45,29 +45,32 @@ export class CurrentUserUtils { } // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools - static setupCreatorButtons() { - let docProtoData: { title: string, icon: string, drag?: string, click?: string }[] = [ + static setupCreatorButtons(doc: Doc) { + doc.activePen = doc; + let docProtoData: { title: string, icon: string, drag?: string, click?: string, unchecked?: string, activePen?: Doc, backgroundColor?: string }[] = [ { title: "collection", icon: "folder", drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, { title: "web page", icon: "globe-asia", drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, { title: "image", icon: "cat", drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, { title: "button", icon: "bolt", drag: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, { title: "presentation", icon: "tv", drag: 'Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })' }, { title: "import folder", icon: "cloud-upload-alt", drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })' }, - { title: "pen", icon: "pen-nib", click: 'activatePen(); setInkWidth(2);' }, - { title: "highlighter", icon: "pen", click: 'activateBrush(); setInkWidth(20);' }, - { title: "eraser", icon: "eraser", click: 'activateEraser();' }, - { title: "none", icon: "pause", click: 'deactivateInk();' }, + { title: "pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "highlighter", icon: "pen", click: 'activateBrush(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "none", icon: "pause", click: 'deactivateInk();this.activePen.pen = this;', unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, ]; return docProtoData.map(data => Docs.Create.FontIconDocument({ - nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "alias" : undefined, - title: data.title, icon: data.icon, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined + nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, + onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, + unchecked: data.unchecked ? ComputedField.MakeFunction(data.unchecked) : undefined, activePen: data.activePen, + backgroundColor: data.backgroundColor })); } // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. when clicked, this panel will be displayed in the target container (ie, sidebarContainer) - static setupCreatePanel(sidebarContainer: Doc) { + static setupCreatePanel(sidebarContainer: Doc, doc: Doc) { // setup a masonry view of all he creators - const dragCreators = Docs.Create.MasonryDocument(CurrentUserUtils.setupCreatorButtons(), { + const dragCreators = Docs.Create.MasonryDocument(CurrentUserUtils.setupCreatorButtons(doc), { width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons" }); // setup a color picker @@ -129,7 +132,7 @@ export class CurrentUserUtils { doc.sidebarContainer = new Doc(); (doc.sidebarContainer as Doc).chromeStatus = "disabled"; - doc.CreateBtn = this.setupCreatePanel(doc.sidebarContainer as Doc); + doc.CreateBtn = this.setupCreatePanel(doc.sidebarContainer as Doc, doc); doc.LibraryBtn = this.setupLibraryPanel(doc.sidebarContainer as Doc, doc); doc.SearchBtn = this.setupSearchPanel(doc.sidebarContainer as Doc); @@ -143,9 +146,9 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupExpandingButtons(doc: Doc) { doc.undoBtn = Docs.Create.FontIconDocument( - { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" }); + { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" }); doc.redoBtn = Docs.Create.FontIconDocument( - { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" }); + { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" }); doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { title: "expanding buttons", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", -- cgit v1.2.3-70-g09d2 From fc0473d0322c9d00ab339c5058dac5863a63ae41 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 15 Oct 2019 21:36:09 -0400 Subject: fixes for dropAction and buttons --- src/client/documents/Documents.ts | 2 +- src/server/authentication/models/current_user_utils.ts | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f4fce34ac..a5a9087c2 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -306,7 +306,7 @@ export namespace Docs { */ export namespace Create { - const delegateKeys = ["x", "y", "width", "height", "panX", "panY"]; + const delegateKeys = ["x", "y", "width", "height", "panX", "panY", "dropAction", "forceActive"]; /** * This function receives the relevant document prototype and uses diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 3c4a46ed8..0c9f09112 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -63,7 +63,7 @@ export class CurrentUserUtils { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, unchecked: data.unchecked ? ComputedField.MakeFunction(data.unchecked) : undefined, activePen: data.activePen, - backgroundColor: data.backgroundColor + backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]) })); } @@ -75,10 +75,8 @@ export class CurrentUserUtils { }); // setup a color picker const color = Docs.Create.ColorDocument({ - title: "color picker", width: 400, removeDropProperties: new List(["dropAction", "forceActive"]) + title: "color picker", width: 400, dropAction: "alias", forceActive: true, removeDropProperties: new List(["dropAction", "forceActive"]) }); - color.dropAction = "alias"; // these must be set on the view document so they can't be part of the creator above. - color.forceActive = true; return Docs.Create.ButtonDocument({ width: 35, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Create", targetContainer: sidebarContainer, @@ -152,7 +150,7 @@ export class CurrentUserUtils { doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { title: "expanding buttons", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", - backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, convertToButtons: true + backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, convertToButtons: true, }); } -- cgit v1.2.3-70-g09d2 From 50fb344cd7c93539f00b3aebc8fa5be4aefc73fd Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 16 Oct 2019 11:07:36 -0400 Subject: small fixes: cursors, pdf, dragging buttons --- src/client/views/nodes/ColorBox.scss | 9 +++++++++ src/client/views/nodes/DocumentView.scss | 1 + src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.scss | 1 + src/client/views/nodes/KeyValueBox.scss | 1 + src/client/views/nodes/PDFBox.scss | 2 +- src/client/views/nodes/PDFBox.tsx | 6 +++--- src/server/authentication/models/current_user_utils.ts | 2 +- 8 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/views/nodes/ColorBox.scss b/src/client/views/nodes/ColorBox.scss index 32a7891c6..bf334c939 100644 --- a/src/client/views/nodes/ColorBox.scss +++ b/src/client/views/nodes/ColorBox.scss @@ -6,6 +6,15 @@ .sketch-picker { margin:auto; + div { + cursor: crosshair; + } + .flexbox-fix { + cursor: pointer; + div { + cursor:pointer; + } + } } } .colorBox-container-interactive { diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index b3e7898c1..69eb1a843 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -6,6 +6,7 @@ left:0; border-radius: inherit; transition : outline .3s linear; + cursor: grab; // background: $light-color; //overflow: hidden; transform-origin: left top; diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 8a320d39b..ebd0ca549 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -176,7 +176,7 @@ export class DocumentView extends DocComponent(Docu handlers: { dragComplete: action((emptyFunction)) }, - hideSource: !dropAction && !this.Document.onDragStart && !this.Document.onClick + hideSource: !dropAction && !this.Document.onDragStart }); } } diff --git a/src/client/views/nodes/FormattedTextBox.scss b/src/client/views/nodes/FormattedTextBox.scss index 29e8b14a8..0550f9708 100644 --- a/src/client/views/nodes/FormattedTextBox.scss +++ b/src/client/views/nodes/FormattedTextBox.scss @@ -12,6 +12,7 @@ .formattedTextBox-cont-scroll, .formattedTextBox-cont-hidden { + cursor: text; background: inherit; padding: 0; border-width: 0px; diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss index 87a9565e8..6e8a36c6a 100644 --- a/src/client/views/nodes/KeyValueBox.scss +++ b/src/client/views/nodes/KeyValueBox.scss @@ -9,6 +9,7 @@ box-sizing: border-box; display: inline-block; pointer-events: all; + cursor: default; .imageBox-cont img { width: auto; } diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 1c1d6ec95..dd909e09f 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -15,7 +15,7 @@ width: 100%; height: 100%; background: lightslategray; - .pdfBox-title-cont, .pdfBox-cont-interactive{ + .pdfBox-cont, .pdfBox-cont-interactive{ width: 150%; height: 100%; position: relative; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 19797400f..f31128356 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -16,7 +16,6 @@ import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeF import { ContextMenu } from '../ContextMenu'; import { ContextMenuProps } from '../ContextMenuItem'; import { DocAnnotatableComponent } from "../DocComponent"; -import { InkingControl } from "../InkingControl"; import { PDFViewer } from "../pdf/PDFViewer"; import { documentSchema } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; @@ -65,6 +64,7 @@ export class PDFBox extends DocAnnotatableComponent } }, { fireImmediately: true }); } + loaded = (nw: number, nh: number, np: number) => { this.dataDoc.numPages = np; this.Document.nativeWidth = nw * 96 / 72; @@ -133,12 +133,12 @@ export class PDFBox extends DocAnnotatableComponent ; - return !this.props.active() ? (null) : + return !this.active() ? (null) : (
    e.keyCode === KeyCodes.BACKSPACE || e.keyCode === KeyCodes.DELETE ? e.stopPropagation() : true} onPointerDown={e => e.stopPropagation()} style={{ display: this.active() ? "flex" : "none", position: "absolute", width: "100%", height: "100%", zIndex: 1, pointerEvents: "none" }}>
    e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}> ; diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index dd909e09f..deb98dc8d 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -7,6 +7,7 @@ overflow: hidden; position:absolute; z-index: -1; + cursor:auto; } .pdfBox-title-outer { diff --git a/src/client/views/pdf/PDFMenu.scss b/src/client/views/pdf/PDFMenu.scss index b06d19c53..44e075153 100644 --- a/src/client/views/pdf/PDFMenu.scss +++ b/src/client/views/pdf/PDFMenu.scss @@ -15,7 +15,7 @@ } .pdfMenu-button:hover { - background-color: #121212; + background-color: #d4d4d4; } .pdfMenu-dragger { diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 4abf85381..0fe8d996f 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -47,20 +47,20 @@ export class CurrentUserUtils { // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc) { doc.activePen = doc; - let docProtoData: { title: string, icon: string, drag?: string, click?: string, unchecked?: string, activePen?: Doc, backgroundColor?: string }[] = [ - { title: "collection", icon: "folder", drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, - { title: "web page", icon: "globe-asia", drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, - { title: "image", icon: "cat", drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, - { title: "button", icon: "bolt", drag: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, - { title: "presentation", icon: "tv", drag: 'Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })' }, - { title: "import folder", icon: "cloud-upload-alt", drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })' }, - { title: "pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, - { title: "highlighter", icon: "pen", click: 'activateBrush(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, - { title: "eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', unchecked: `!sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, - { title: "none", icon: "pause", click: 'deactivateInk();this.activePen.pen = this;', unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, + let docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, unchecked?: string, activePen?: Doc, backgroundColor?: string }[] = [ + { title: "collection", icon: "folder", ignoreClick: true, drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, + { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, + { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, + { title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, + { title: "presentation", icon: "tv", ignoreClick: true, drag: 'Doc.UserDoc().curPresentation = Docs.Create.PresDocument(new List(), { width: 200, height: 500, title: "a presentation trail" })' }, + { title: "import folder", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", width: 400, height: 400 })' }, + { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,2, this.backgroundColor)', backgroundColor: "blue", unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "use highlighter", icon: "highlighter", click: 'activateBrush(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this,20,this.backgroundColor)', backgroundColor: "yellow", unchecked: `!sameDocs(this.activePen.pen, this)`, activePen: doc }, + { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activePen.pen = sameDocs(this.activePen.pen, this) ? undefined : this);', unchecked: `!sameDocs(this.activePen.pen, this)`, backgroundColor: "pink", activePen: doc }, + { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activePen.pen = this;', unchecked: `!sameDocs(this.activePen.pen, this) && this.activePen.pen !== undefined`, backgroundColor: "white", activePen: doc }, ]; return docProtoData.map(data => Docs.Create.FontIconDocument({ - nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, + nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, unchecked: data.unchecked ? ComputedField.MakeFunction(data.unchecked) : undefined, activePen: data.activePen, backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]) @@ -144,9 +144,9 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupExpandingButtons(doc: Doc) { doc.undoBtn = Docs.Create.FontIconDocument( - { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" }); + { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("undo()"), removeDropProperties: new List(["dropAction"]), title: "undo button", icon: "undo-alt" }); doc.redoBtn = Docs.Create.FontIconDocument( - { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), title: "redo button", icon: "redo-alt" }); + { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: "alias", onClick: ScriptField.MakeScript("redo()"), removeDropProperties: new List(["dropAction"]), title: "redo button", icon: "redo-alt" }); doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { title: "expanding buttons", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", @@ -192,8 +192,8 @@ export class CurrentUserUtils { }); // setup reactions to change the highlights on the undo/redo buttons -- would be better to encode this in the undo/redo buttons, but the undo/redo stacks are not wired up that way yet - doc.undoBtn && reaction(() => UndoManager.undoStack.slice(), () => (doc.undoBtn as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true }); - doc.redoBtn && reaction(() => UndoManager.redoStack.slice(), () => (doc.redoBtn as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); + doc.undoBtn && reaction(() => UndoManager.undoStack.slice(), () => Doc.GetProto(doc.undoBtn as Doc).opacity = UndoManager.CanUndo() ? 1 : 0.4, { fireImmediately: true }); + doc.redoBtn && reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(doc.redoBtn as Doc).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true }); return doc; } -- cgit v1.2.3-70-g09d2 From 789b4925dff316ed9151bf9d327ab6223f09ec4a Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 16 Oct 2019 17:07:42 -0400 Subject: added a default note template --- src/client/documents/Documents.ts | 1 + src/server/authentication/models/current_user_utils.ts | 14 ++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a5a9087c2..ccb08f4cd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -96,6 +96,7 @@ export interface DocumentOptions { unchecked?: ScriptField; // returns whether a check box is unchecked activePen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts) onClick?: ScriptField; + dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop icon?: string; gridGap?: number; // gap between items in masonry view diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 0fe8d996f..ef977c89a 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -35,20 +35,23 @@ export class CurrentUserUtils { // a default set of note types .. not being used yet... static setupNoteTypes(doc: Doc) { - let notes = [ + return [ Docs.Create.TextDocument({ title: "Note", backgroundColor: "yellow", isTemplate: true }), Docs.Create.TextDocument({ title: "Idea", backgroundColor: "pink", isTemplate: true }), Docs.Create.TextDocument({ title: "Topic", backgroundColor: "lightBlue", isTemplate: true }), - Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplate: true }) + Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplate: true }), + Docs.Create.TextDocument({ title: "Todo", backgroundColor: "orange", isTemplate: true }) ]; - doc.noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", height: 75 }); } // setup the "creator" buttons for the sidebar-- eg. the default set of draggable document creation tools static setupCreatorButtons(doc: Doc) { + let notes = CurrentUserUtils.setupNoteTypes(doc); + doc.noteTypes = Docs.Create.TreeDocument(notes, { title: "Note Types", height: 75 }); doc.activePen = doc; - let docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, unchecked?: string, activePen?: Doc, backgroundColor?: string }[] = [ + let docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, unchecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [ { title: "collection", icon: "folder", ignoreClick: true, drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' }, + { title: "todo item", icon: "check", ignoreClick: true, drag: 'getCopy(this.dragFactory, true)', dragFactory: notes[notes.length - 1] }, { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' }, { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' }, { title: "clickable button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ width: 150, height: 50, title: "Button" })' }, @@ -63,7 +66,7 @@ export class CurrentUserUtils { nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, dropAction: data.click ? "copy" : undefined, title: data.title, icon: data.icon, ignoreClick: data.ignoreClick, onDragStart: data.drag ? ScriptField.MakeFunction(data.drag) : undefined, onClick: data.click ? ScriptField.MakeScript(data.click) : undefined, unchecked: data.unchecked ? ComputedField.MakeFunction(data.unchecked) : undefined, activePen: data.activePen, - backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]) + backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory: data.dragFactory })); } @@ -173,7 +176,6 @@ export class CurrentUserUtils { static updateUserDocument(doc: Doc) { new InkingControl(); (doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc); - (doc.noteTypes === undefined) && CurrentUserUtils.setupNoteTypes(doc); (doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc); (doc.expandingButtons === undefined) && CurrentUserUtils.setupExpandingButtons(doc); (doc.curPresentation === undefined) && CurrentUserUtils.setupDefaultPresentation(doc); -- cgit v1.2.3-70-g09d2 From 7763a08eb5ed931dbf854e2b72d07b7613791e2b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 16 Oct 2019 21:27:25 -0400 Subject: some fixes to linearView for handling templates. fixed DOCUMENTS on library view. renaming a bunch of template stuff... still in progress. --- src/client/documents/Documents.ts | 1 + src/client/views/CollectionLinearView.tsx | 18 ++++++++++++++---- src/client/views/DocComponent.tsx | 2 +- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/InkingControl.tsx | 7 ++----- src/client/views/TemplateMenu.tsx | 2 +- src/client/views/collections/CollectionBaseView.tsx | 10 +++++----- .../views/collections/CollectionStackingView.tsx | 4 +++- src/client/views/collections/CollectionSubView.tsx | 11 ++++++++--- src/client/views/collections/CollectionTreeView.tsx | 3 ++- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/ButtonBox.tsx | 6 +++++- src/client/views/nodes/DocumentView.tsx | 6 +++--- src/client/views/nodes/FormattedTextBox.tsx | 2 +- src/client/views/nodes/VideoBox.tsx | 2 +- src/new_fields/Doc.ts | 6 +++--- src/server/authentication/models/current_user_utils.ts | 16 ++++++++-------- 17 files changed, 61 insertions(+), 41 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index ccb08f4cd..2ffbc8394 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -70,6 +70,7 @@ export interface DocumentOptions { layout?: string | Doc; hideHeadings?: boolean; // whether stacking view column headings should be hidden isTemplate?: boolean; + isTemplateDoc?: boolean; templates?: List; viewType?: number; backgroundColor?: string; diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 44d9b042e..3e2ab1459 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -1,7 +1,7 @@ import { action, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { Doc, HeightSym, WidthSym } from '../../new_fields/Doc'; +import { Doc, HeightSym, WidthSym, DocListCast } from '../../new_fields/Doc'; import { ObjectField } from '../../new_fields/ObjectField'; import { makeInterface } from '../../new_fields/Schema'; import { ScriptField } from '../../new_fields/ScriptField'; @@ -51,9 +51,19 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { let dbox = doc; if (!doc.onDragStart && !doc.onClick && this.props.Document.convertToButtons && doc.viewType !== CollectionViewType.Linear) { - let template = doc.layout instanceof Doc && doc.layout.isTemplate ? doc.layout : doc; - template.isTemplate = (template.type === DocumentType.TEXT || template.layout instanceof Doc) && de.data instanceof DragManager.DocumentDragData && !de.data.userDropAction; - dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: template.isTemplate ? "font" : "bolt" }); + let template = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + if (template.type === DocumentType.COL) { + let layout = StrCast(template.layout).match(/fieldKey={"[^"]*"}/)![0]; + let fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); + let docs = DocListCast(template[fieldKey]); + docs.map(d => { + Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(template)); + }); + template.isTemplateDoc = true; + } else { + template.isTemplateDoc = (template.type === DocumentType.TEXT || template.layout instanceof Doc) && de.data instanceof DragManager.DocumentDragData && !de.data.userDropAction; + } + dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: template.isTemplateDoc ? "font" : "bolt" }); dbox.dragFactory = template; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index fbc27192c..b6b717be0 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -68,7 +68,7 @@ export function DocAnnotatableComponent

    (schema return index !== -1 && value.splice(index, 1) ? true : false; } - @computed get dataDoc() { return (this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } + @computed get dataDoc() { return (this.props.DataDoc && this.props.Document.isTemplateField ? this.props.DataDoc : Doc.GetProto(this.props.Document)) as Doc; } @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2f40ea746..6e8ba2d3d 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -380,7 +380,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> ruleProvider && heading && (Doc.GetProto(ruleProvider)["ruleRounding_" + heading] = `${Math.min(100, dist)}%`); usingRule = usingRule || (ruleProvider && heading ? true : false); }); - !usingRule && 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)). + !usingRule && SelectionManager.SelectedDocuments().map(dv => dv.props.Document.layout instanceof Doc ? dv.props.Document.layout : dv.props.Document.isTemplateField ? dv.props.Document : Doc.GetProto(dv.props.Document)). map(d => d.borderRounding = `${Math.min(100, dist)}%`); e.stopPropagation(); e.preventDefault(); @@ -481,7 +481,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let actualdH = Math.max(height + (dH * scale), 20); layoutDoc.x = (layoutDoc.x || 0) + dX * (actualdW - width); layoutDoc.y = (layoutDoc.y || 0) + dY * (actualdH - height); - let proto = doc.isTemplate ? doc : Doc.GetProto(element.props.Document); // bcz: 'doc' didn't work here... + let proto = doc.isTemplateField ? doc : Doc.GetProto(element.props.Document); // bcz: 'doc' didn't work here... let fixedAspect = e.ctrlKey || (!layoutDoc.ignoreAspect && nwidth && nheight); if (fixedAspect && e.ctrlKey && layoutDoc.ignoreAspect) { layoutDoc.ignoreAspect = false; diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index 46c6fae1c..bc5249acd 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -43,7 +43,7 @@ export class InkingControl { let oldColors = selected.map(view => { let targetDoc = view.props.Document.dragFactory instanceof Doc ? view.props.Document.dragFactory : view.props.Document.layout instanceof Doc ? view.props.Document.layout : - view.props.Document.isTemplate ? view.props.Document : Doc.GetProto(view.props.Document); + view.props.Document.isTemplateField ? view.props.Document : Doc.GetProto(view.props.Document); let sel = window.getSelection(); if (StrCast(targetDoc.layout).indexOf("FormattedTextBox") !== -1 && (!sel || sel.toString() !== "")) { targetDoc.color = this._selectedColor; @@ -81,10 +81,7 @@ export class InkingControl { ruleProvider = (view.props.Document.heading && ruleProvider) ? ruleProvider : undefined; ruleProvider && ((Doc.GetProto(ruleProvider)["ruleColor_" + NumCast(view.props.Document.heading)] = Utils.toRGBAstr(color.rgb))); } - if (!ruleProvider) { - if (targetDoc) - targetDoc.backgroundColor = matchedColor; - } + (!ruleProvider && targetDoc) && (targetDoc.backgroundColor = matchedColor); return { target: targetDoc, diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 9e5e62e03..da776f887 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -100,7 +100,7 @@ export class TemplateMenu extends React.Component { clearTemplates = (event: React.MouseEvent) => { Templates.TemplateList.forEach(template => this.props.docs.forEach(d => d.Document["show" + template.Name] = undefined)); ["backgroundColor", "borderRounding", "width", "height"].forEach(field => this.props.docs.forEach(d => { - if (d.Document.isTemplate && d.props.DataDoc) { + if (d.Document.isTemplateDoc && d.props.DataDoc) { d.Document[field] = undefined; } else if (d.Document["default" + field[0].toUpperCase() + field.slice(1)] !== undefined) { d.Document[field] = Doc.GetProto(d.Document)[field] = undefined; diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 7798964ea..15853fcae 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -84,7 +84,7 @@ export class CollectionBaseView extends React.Component { } } - @computed get dataDoc() { return Doc.fieldExtensionDoc(this.props.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); } + @computed get dataDoc() { return Doc.fieldExtensionDoc(this.props.Document.isTemplateField && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt); } @computed get dataField() { return this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; } active = (): boolean => { @@ -106,8 +106,8 @@ export class CollectionBaseView extends React.Component { if (this.props.fieldExt) { // bcz: fieldExt !== undefined means this is an overlay layer Doc.GetProto(doc).annotationOn = this.props.Document; } - let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document; - let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; + let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplateField ? this.extensionDoc : this.props.Document; + let targetField = (this.props.fieldExt || this.props.Document.isTemplateField) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; Doc.AddDocToList(targetDataDoc, targetField, doc); Doc.GetProto(doc).lastOpened = new DateField; return true; @@ -118,8 +118,8 @@ export class CollectionBaseView extends React.Component { let docView = DocumentManager.Instance.getDocumentView(doc, this.props.ContainingCollectionView); docView && SelectionManager.DeselectDoc(docView); //TODO This won't create the field if it doesn't already exist - let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplate ? this.extensionDoc : this.props.Document; - let targetField = (this.props.fieldExt || this.props.Document.isTemplate) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; + let targetDataDoc = this.props.fieldExt || this.props.Document.isTemplateField ? this.extensionDoc : this.props.Document; + let targetField = (this.props.fieldExt || this.props.Document.isTemplateField) && this.props.fieldExt ? this.props.fieldExt : this.props.fieldKey; let value = Cast(targetDataDoc[targetField], listSpec(Doc), []); let index = value.reduce((p, v, i) => (v instanceof Doc && v === doc) ? i : p, -1); index = index !== -1 ? index : value.reduce((p, v, i) => (v instanceof Doc && Doc.AreProtosEqual(v, doc)) ? i : p, -1); diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index cde1a5036..e54374ad7 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -110,6 +110,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { } componentDidMount() { + super.componentDidMount(); this._heightDisposer = reaction(() => { if (this.props.Document.autoHeight) { let sectionsList = Array.from(this.Sections.size ? this.Sections.values() : [this.filteredChildren]); @@ -137,6 +138,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { ); } componentWillUnmount() { + super.componentWillUnmount(); this._heightDisposer && this._heightDisposer(); this._sectionFilterDisposer && this._sectionFilterDisposer(); } @@ -167,7 +169,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { renderDepth={this.props.renderDepth} ruleProvider={this.props.Document.isRuleProvider && layoutDoc.type !== DocumentType.TEXT ? this.props.Document : this.props.ruleProvider} fitToBox={this.props.fitToBox} - onClick={layoutDoc.isTemplate ? this.onClickHandler : this.onChildClickHandler} + onClick={layoutDoc.isTemplateDoc ? this.onClickHandler : this.onChildClickHandler} PanelWidth={width} PanelHeight={height} getTransform={finalDxf} diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 9919a9dc3..46fbb5910 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -57,8 +57,13 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { componentDidMount() { this._childLayoutDisposer = reaction(() => [this.childDocs, Cast(this.props.Document.childLayout, Doc)], - async (args) => args[1] instanceof Doc && - this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc)))); + async (args) => { + if (args[1] instanceof Doc) { + this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc))); + } else { + this.childDocs.map(async doc => doc.layout = undefined); + } + }); } componentWillUnmount() { @@ -70,7 +75,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { // to its children which may be templates. // The name of the data field comes from fieldExt if it's an extension, or fieldKey otherwise. @computed get dataField() { - return Doc.fieldExtensionDoc(this.props.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt)[this.props.fieldExt || this.props.fieldKey]; + return Doc.fieldExtensionDoc(this.props.Document.isTemplateField && this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, this.props.fieldExt)[this.props.fieldExt || this.props.fieldKey]; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 403da0e54..0e9c38fb4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -520,7 +520,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { private treedropDisposer?: DragManager.DragDropDisposer; private _mainEle?: HTMLDivElement; - @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } + @computed get resolvedDataDoc() { return BoolCast(this.props.Document.isTemplateField) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } protected createTreeDropTarget = (ele: HTMLDivElement) => { this.treedropDisposer && this.treedropDisposer(); @@ -530,6 +530,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { } componentWillUnmount() { + super.componentWillUnmount(); this.treedropDisposer && this.treedropDisposer(); } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 229e7fffc..2b0ef8ada 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -627,7 +627,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { onContextMenu = (e: React.MouseEvent) => { let layoutItems: ContextMenuProps[] = []; - if (this.childDocs.some(d => BoolCast(d.isTemplate))) { + if (this.childDocs.some(d => BoolCast(d.isTemplateDoc))) { layoutItems.push({ description: "Template Layout Instance", event: () => this.props.addDocTab(Doc.ApplyTemplate(this.props.Document)!, undefined, "onRight"), icon: "project-diagram" }); } layoutItems.push({ description: "reset view", event: () => { this.props.Document.panX = this.props.Document.panY = 0; this.props.Document.scale = 1; }, icon: "compress-arrows-alt" }); diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index 3cf8c3eb3..b4d33fb0f 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -32,7 +32,11 @@ export class ButtonBox extends DocComponent(Butt public static LayoutString() { return FieldView.LayoutString(ButtonBox); } private dropDisposer?: DragManager.DragDropDisposer; - @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); } + @computed get dataDoc() { + return this.props.DataDoc && + (BoolCast(this.props.Document.isTemplateField) || BoolCast(this.props.DataDoc.isTemplateField) || + this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); + } protected createDropTarget = (ele: HTMLDivElement) => { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index a071f782a..a7e78a7e8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -110,7 +110,7 @@ export const documentSchema = createSchema({ dragFactory: Doc, // the document that serves as the "template" for the onDragStart script. ie, to drag out copies of the dragFactory document. ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents - isTemplate: "boolean", // whether this document acts as a template layout for describing how other documents should be displayed + isTemplateField: "boolean", // whether this document acts as a template layout for describing how other documents should be displayed isBackground: "boolean", // whether document is a background element and ignores input events (can only selet with marquee) type: "string", // enumerated type of document maximizeLocation: "string", // flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab) @@ -196,7 +196,7 @@ export class DocumentView extends DocComponent(Docu SelectionManager.DeselectAll(); Doc.UnBrushDoc(this.props.Document); } else if (this.onClickHandler && this.onClickHandler.script) { - this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); + this.onClickHandler.script.run({ this: this.Document.isTemplateField && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log); } else if (this.props.Document.type === DocumentType.BUTTON) { ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY); } else if (this.Document.isButton) { @@ -376,7 +376,7 @@ export class DocumentView extends DocComponent(Docu @undoBatch @action freezeNativeDimensions = (): void => { - let proto = this.Document.isTemplate ? this.props.Document : Doc.GetProto(this.props.Document); + let proto = this.Document.isTemplateDoc ? this.props.Document : Doc.GetProto(this.props.Document); proto.autoHeight = this.Document.autoHeight = false; proto.ignoreAspect = !proto.ignoreAspect; if (!proto.ignoreAspect && !proto.nativeWidth) { diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f157a953e..ea82b1161 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -993,7 +993,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let scrollHeight = this._ref.current ? this._ref.current.scrollHeight : 0; if (!this.layoutDoc.isAnimating && this.layoutDoc.autoHeight && scrollHeight !== 0 && getComputedStyle(this._ref.current!.parentElement!).top === "0px") { // if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation - let nh = this.props.Document.isTemplate ? 0 : NumCast(this.dataDoc.nativeHeight, 0); + let nh = this.props.Document.isTemplateField ? 0 : NumCast(this.dataDoc.nativeHeight, 0); let dh = NumCast(this.layoutDoc.height, 0); this.layoutDoc.height = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0)); this.dataDoc.nativeHeight = nh ? scrollHeight : undefined; diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index aa9b28118..19968e6e1 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -323,7 +323,7 @@ export class VideoBox extends DocAnnotatableComponent(field.map((d: any) => Doc.MakeAlias(d))); }); Scripting.addGlobal(function docList(field: any) { return DocListCast(field); }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index ef977c89a..5ce707011 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -36,11 +36,11 @@ export class CurrentUserUtils { // a default set of note types .. not being used yet... static setupNoteTypes(doc: Doc) { return [ - Docs.Create.TextDocument({ title: "Note", backgroundColor: "yellow", isTemplate: true }), - Docs.Create.TextDocument({ title: "Idea", backgroundColor: "pink", isTemplate: true }), - Docs.Create.TextDocument({ title: "Topic", backgroundColor: "lightBlue", isTemplate: true }), - Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplate: true }), - Docs.Create.TextDocument({ title: "Todo", backgroundColor: "orange", isTemplate: true }) + Docs.Create.TextDocument({ title: "Note", backgroundColor: "yellow", isTemplateDoc: true }), + Docs.Create.TextDocument({ title: "Idea", backgroundColor: "pink", isTemplateDoc: true }), + Docs.Create.TextDocument({ title: "Topic", backgroundColor: "lightBlue", isTemplateDoc: true }), + Docs.Create.TextDocument({ title: "Person", backgroundColor: "lightGreen", isTemplateDoc: true }), + Docs.Create.TextDocument({ title: "Todo", backgroundColor: "orange", isTemplateDoc: true }) ]; } @@ -98,17 +98,17 @@ export class CurrentUserUtils { }); doc.documents = Docs.Create.TreeDocument([], { - title: "DOCUMENTS", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", backgroundColor: "#eeeeee", preventTreeViewOpen: true, forceActive: true, lockedPosition: true + title: "DOCUMENTS", height: 42, forceActive: true, boxShadow: "0 0", preventTreeViewOpen: true, lockedPosition: true, backgroundColor: "#eeeeee" }); // setup Recently Closed library item doc.recentlyClosed = Docs.Create.TreeDocument([], { - title: "Recently Closed".toUpperCase(), height: 75, boxShadow: "0 0", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, backgroundColor: "#eeeeee" + title: "RECENTLY CLOSED", height: 75, forceActive: true, boxShadow: "0 0", preventTreeViewOpen: true, lockedPosition: true, backgroundColor: "#eeeeee" }); return Docs.Create.ButtonDocument({ width: 50, height: 35, borderRounding: "50%", boxShadow: "2px 2px 1px", title: "Library", - panel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc, doc.recentlyClosed as Doc], { + panel: Docs.Create.TreeDocument([doc.workspaces as Doc, doc.documents as Doc, doc.recentlyClosed as Doc], { title: "Library", xMargin: 5, yMargin: 5, gridGap: 5, forceActive: true, dropAction: "alias", lockedPosition: true }), targetContainer: sidebarContainer, -- cgit v1.2.3-70-g09d2 From caebaeca6993ff48609ab16dcc390d4d0458b03a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 16 Oct 2019 23:50:27 -0400 Subject: fixed applying templates to collections. fixed templates containing collections --- src/client/documents/Documents.ts | 2 +- src/client/views/CollectionLinearView.tsx | 35 ++++++++++++++-------- src/client/views/InkingCanvas.tsx | 3 +- src/client/views/InkingControl.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/collections/CollectionViewChromes.tsx | 4 +-- src/client/views/nodes/ColorBox.tsx | 7 ++--- src/client/views/nodes/FormattedTextBox.tsx | 4 +-- src/new_fields/Doc.ts | 14 +++++++-- .../authentication/models/current_user_utils.ts | 14 +++------ 10 files changed, 51 insertions(+), 36 deletions(-) (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 2ffbc8394..62175cbe3 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -69,7 +69,7 @@ export interface DocumentOptions { preventTreeViewOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expande/collapse state to be independent of other views of the same document in the tree view layout?: string | Doc; hideHeadings?: boolean; // whether stacking view column headings should be hidden - isTemplate?: boolean; + isTemplateField?: boolean; isTemplateDoc?: boolean; templates?: List; viewType?: number; diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 3e2ab1459..04e131135 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -47,24 +47,35 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { } } + makeTemplate = (doc: Doc): boolean => { + let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + let layout = StrCast(layoutDoc.layout).match(/fieldKey={"[^"]*"}/)![0]; + let fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); + let docs = DocListCast(layoutDoc[fieldKey]); + let any = false; + docs.map(d => { + if (!StrCast(d.title).startsWith("-")) { + any = true; + return Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)); + } + if (d.type === DocumentType.COL) return this.makeTemplate(d); + return false; + }); + return any; + } + drop = action((e: Event, de: DragManager.DropEvent) => { (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { let dbox = doc; if (!doc.onDragStart && !doc.onClick && this.props.Document.convertToButtons && doc.viewType !== CollectionViewType.Linear) { - let template = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; - if (template.type === DocumentType.COL) { - let layout = StrCast(template.layout).match(/fieldKey={"[^"]*"}/)![0]; - let fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); - let docs = DocListCast(template[fieldKey]); - docs.map(d => { - Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(template)); - }); - template.isTemplateDoc = true; + let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + if (layoutDoc.type === DocumentType.COL) { + layoutDoc.isTemplateDoc = this.makeTemplate(layoutDoc); } else { - template.isTemplateDoc = (template.type === DocumentType.TEXT || template.layout instanceof Doc) && de.data instanceof DragManager.DocumentDragData && !de.data.userDropAction; + layoutDoc.isTemplateDoc = (layoutDoc.type === DocumentType.TEXT || layoutDoc.layout instanceof Doc) && de.data instanceof DragManager.DocumentDragData && !de.data.userDropAction; } - dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: template.isTemplateDoc ? "font" : "bolt" }); - dbox.dragFactory = template; + dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: layoutDoc.isTemplateDoc ? "font" : "bolt" }); + dbox.dragFactory = layoutDoc; dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); } else if (doc.viewType === CollectionViewType.Linear) { diff --git a/src/client/views/InkingCanvas.tsx b/src/client/views/InkingCanvas.tsx index 9ab320eab..920ebaedd 100644 --- a/src/client/views/InkingCanvas.tsx +++ b/src/client/views/InkingCanvas.tsx @@ -181,9 +181,10 @@ export class InkingCanvas extends React.Component { render() { let svgCanvasStyle = InkingControl.Instance.selectedTool !== InkTool.None && !this.props.Document.isBackground ? "canSelect" : "noSelect"; + let cursor = svgCanvasStyle === "canSelect" ? (InkingControl.Instance.selectedTool === InkTool.Eraser ? "pointer" : "default") : undefined; return (

    -
    +
    {this.props.children()} {this.drawnPaths}
    diff --git a/src/client/views/InkingControl.tsx b/src/client/views/InkingControl.tsx index bc5249acd..b8f3c2875 100644 --- a/src/client/views/InkingControl.tsx +++ b/src/client/views/InkingControl.tsx @@ -94,7 +94,7 @@ export class InkingControl { redo: () => oldColors.forEach(pair => pair.target.backgroundColor = captured) }); } else { - CurrentUserUtils.UserDocument.activePen instanceof Doc && CurrentUserUtils.UserDocument.activePen.pen instanceof Doc && (CurrentUserUtils.UserDocument.activePen.pen.backgroundColor = this._selectedColor); + CurrentUserUtils.ActivePen && (CurrentUserUtils.ActivePen.backgroundColor = this._selectedColor); } }); @action diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 46fbb5910..1f8c0b18f 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -61,7 +61,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { if (args[1] instanceof Doc) { this.childDocs.map(async doc => !Doc.AreProtosEqual(args[1] as Doc, (await doc).layout as Doc) && Doc.ApplyTemplateTo(args[1] as Doc, (await doc))); } else { - this.childDocs.map(async doc => doc.layout = undefined); + this.childDocs.filter(d => !d.isTemplateField).map(async doc => doc.layout = undefined); } }); diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 3a66c05f4..a5b7f0181 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -40,9 +40,9 @@ export class CollectionViewBaseChrome extends React.Component this.props.CollectionView.props.Document.childLayout = draggedDocs.length ? draggedDocs[0] : undefined + immediate: (draggedDocs: Doc[]) => Doc.setChildLayout(this.props.CollectionView.props.Document, draggedDocs.length ? draggedDocs[0] : undefined) }; _contentCommand = { // title: "set content", script: "getProto(this.target).data = aliasDocs(this.source.map(async p => await p));", params: ["target", "source"], // bcz: doesn't look like we can do async stuff in scripting... diff --git a/src/client/views/nodes/ColorBox.tsx b/src/client/views/nodes/ColorBox.tsx index e4fef0922..30554ea36 100644 --- a/src/client/views/nodes/ColorBox.tsx +++ b/src/client/views/nodes/ColorBox.tsx @@ -25,9 +25,8 @@ export class ColorBox extends DocStaticComponent( this._selectedDisposer = reaction(() => SelectionManager.SelectedDocuments(), action(() => this._startupColor = SelectionManager.SelectedDocuments().length ? StrCast(SelectionManager.SelectedDocuments()[0].Document.backgroundColor, "black") : "black"), { fireImmediately: true }); - this._penDisposer = reaction(() => CurrentUserUtils.UserDocument.activePen instanceof Doc && CurrentUserUtils.UserDocument.activePen.pen, - action(() => this._startupColor = CurrentUserUtils.UserDocument.activePen instanceof Doc && CurrentUserUtils.UserDocument.activePen.pen instanceof Doc ? - StrCast(CurrentUserUtils.UserDocument.activePen.pen.backgroundColor, "black") : "black"), + this._penDisposer = reaction(() => CurrentUserUtils.ActivePen, + action(() => this._startupColor = CurrentUserUtils.ActivePen ? StrCast(CurrentUserUtils.ActivePen.backgroundColor, "black") : "black"), { fireImmediately: true }); // compare to this reaction that used to be in Selection Manager @@ -36,7 +35,7 @@ export class ColorBox extends DocStaticComponent( // if (sel.length > 0) { // let firstView = sel[0]; // let doc = firstView.props.Document; - // let targetDoc = doc.isTemplate ? doc : Doc.GetProto(doc); + // let targetDoc = doc.isTemplateField ? doc : Doc.GetProto(doc); // let stored = StrCast(targetDoc.backgroundColor); // stored.length > 0 && (targetColor = stored); // } diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index ea82b1161..045eee3f7 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -143,7 +143,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); } - @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); } + @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplateField ? Doc.GetProto(this.props.DataDoc) : Doc.GetProto(this.props.Document); } // the document containing the view layout information - will be the Document itself unless the Document has // a layout field. In that case, all layout information comes from there unless overriden by Document @@ -265,7 +265,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } // apply as template when dragging with Meta } else if (draggedDoc && draggedDoc.type === DocumentType.TEXT && !Doc.AreProtosEqual(draggedDoc, this.props.Document) && de.mods === "MetaKey") { - draggedDoc.isTemplate = true; + draggedDoc.isTemplateDoc = true; let newLayout = draggedDoc.layout instanceof Doc ? draggedDoc.layout : draggedDoc; if (typeof (draggedDoc.layout) === "string") { newLayout = Doc.MakeDelegate(draggedDoc); diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 51fcb818a..04f310785 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -599,7 +599,7 @@ export namespace Doc { return target; } - export function MakeMetadataFieldTemplate(fieldTemplate: Doc, templateDataDoc: Doc, suppressTitle: boolean = false) { + export function MakeMetadataFieldTemplate(fieldTemplate: Doc, templateDataDoc: Doc, suppressTitle: boolean = false): boolean { // move data doc fields to layout doc as needed (nativeWidth/nativeHeight, data, ??) let metadataFieldName = StrCast(fieldTemplate.title).replace(/^-/, ""); let backgroundLayout = StrCast(fieldTemplate.backgroundLayout); @@ -613,7 +613,7 @@ export namespace Doc { fieldTemplate.templateField = metadataFieldName; fieldTemplate.title = metadataFieldName; - fieldTemplate.isTemplate = true; + fieldTemplate.isTemplateField = true; fieldTemplate.backgroundLayout = backgroundLayout; /* move certain layout properties from the original data doc to the template layout to avoid inheriting them from the template's data doc which may also define these fields for its own use. @@ -636,6 +636,7 @@ export namespace Doc { if (fieldTemplate.backgroundColor !== templateDataDoc.defaultBackgroundColor) fieldTemplate.defaultBackgroundColor = fieldTemplate.backgroundColor; fieldTemplate.proto = templateDataDoc; }), 0); + return true; } export function overlapping(doc: Doc, doc2: Doc, clusterDistance: number) { @@ -735,9 +736,18 @@ export namespace Doc { export function UnBrushAllDocs() { manager.BrushedDoc.clear(); } + + export function setChildLayout(target: Doc, source?: Doc) { + target.childLayout = source && source.isTemplateDoc ? source : source && + source.dragFactory instanceof Doc && source.dragFactory.isTemplateDoc ? source.dragFactory : + source && source.layout instanceof Doc && source.layout.isTemplateDoc ? source.layout : undefined; + } } + + Scripting.addGlobal(function renameAlias(doc: any, n: any) { return StrCast(Doc.GetProto(doc).title).replace(/\([0-9]*\)/, "") + `(${n})`; }); Scripting.addGlobal(function getProto(doc: any) { return Doc.GetProto(doc); }); +Scripting.addGlobal(function setChildLayout(target: any, source: any) { Doc.setChildLayout(target, source); }); Scripting.addGlobal(function getAlias(doc: any) { return Doc.MakeAlias(doc); }); Scripting.addGlobal(function getCopy(doc: any, copyProto: any) { return doc.isTemplateDoc ? Doc.ApplyTemplate(doc) : Doc.MakeCopy(doc, copyProto); }); Scripting.addGlobal(function copyField(field: any) { return ObjectField.MakeCopy(field); }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 5ce707011..e6f202685 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -23,16 +23,11 @@ export class CurrentUserUtils { public static get MainDocId() { return this.mainDocId; } public static set MainDocId(id: string | undefined) { this.mainDocId = id; } @computed public static get UserDocument() { return Doc.UserDoc(); } + @computed public static get ActivePen() { return Doc.UserDoc().activePen instanceof Doc && (Doc.UserDoc().activePen as Doc).pen as Doc; } @observable public static GuestTarget: Doc | undefined; @observable public static GuestWorkspace: Doc | undefined; - private static createUserDocument(id: string): Doc { - let doc = new Doc(id, true); - doc.title = Doc.CurrentUserEmail; - return this.updateUserDocument(doc);// this should be the last - } - // a default set of note types .. not being used yet... static setupNoteTypes(doc: Doc) { return [ @@ -174,6 +169,7 @@ export class CurrentUserUtils { } static updateUserDocument(doc: Doc) { + doc.title = Doc.CurrentUserEmail; new InkingControl(); (doc.optionalRightCollection === undefined) && CurrentUserUtils.setupMobileUploads(doc); (doc.overlays === undefined) && CurrentUserUtils.setupOverlays(doc); @@ -216,10 +212,8 @@ export class CurrentUserUtils { Doc.CurrentUserEmail = email; await rp.get(Utils.prepend(RouteStore.getUserDocumentId)).then(id => { if (id && id !== "guest") { - return DocServer.GetRefField(id).then(async field => { - let userDoc = field instanceof Doc ? await this.updateUserDocument(field) : this.createUserDocument(id); - runInAction(() => Doc.SetUserDoc(userDoc)); - }); + return DocServer.GetRefField(id).then(async field => + Doc.SetUserDoc(await this.updateUserDocument(field instanceof Doc ? field : new Doc(id, true)))); } else { throw new Error("There should be a user id! Why does Dash think there isn't one?"); } -- cgit v1.2.3-70-g09d2 From 1f3576a69a6a0396d07e965c700bb7d69d77a0a3 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 18 Oct 2019 17:06:41 -0400 Subject: fixed up creator buttons - factored out convert to buttons code into a dropConverter script. fixed issues with template loading for images. --- src/client/documents/Documents.ts | 2 +- src/client/util/DragManager.ts | 3 ++ src/client/util/DropConverter.ts | 46 ++++++++++++++++++++++ src/client/views/CollectionLinearView.tsx | 40 ------------------- .../views/collections/CollectionStackingView.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 6 ++- .../views/collections/CollectionTreeView.scss | 1 - .../views/collections/CollectionTreeView.tsx | 2 +- .../CollectionFreeFormLinkView.tsx | 2 +- .../authentication/models/current_user_utils.ts | 11 ++++-- 10 files changed, 65 insertions(+), 50 deletions(-) create mode 100644 src/client/util/DropConverter.ts (limited to 'src/server/authentication/models/current_user_utils.ts') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 651662ded..32fda1954 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -105,7 +105,7 @@ export interface DocumentOptions { yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts panel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script - convertToButtons?: boolean; // whether documents dropped onto a collection should be converted to buttons that will construct the dropped document + dropConverter?: ScriptField; // script to run when documents are dropped on this Document. // [key: string]: Opt; } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 576b16bc8..bbc29585c 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -14,6 +14,8 @@ import { ScriptField } from "../../new_fields/ScriptField"; import { List } from "../../new_fields/List"; import { PrefetchProxy } from "../../new_fields/Proxy"; import { listSpec } from "../../new_fields/Schema"; +import { Scripting } from "./Scripting"; +import { convertDropDataToButtons } from "./DropConverter"; export type dropActionType = "alias" | "copy" | undefined; export function SetupDrag( @@ -497,3 +499,4 @@ export namespace DragManager { } } } +Scripting.addGlobal(function convertToButtons(dragData: any) { convertDropDataToButtons(dragData as DragManager.DocumentDragData); }); diff --git a/src/client/util/DropConverter.ts b/src/client/util/DropConverter.ts new file mode 100644 index 000000000..eea3da1bc --- /dev/null +++ b/src/client/util/DropConverter.ts @@ -0,0 +1,46 @@ +import { DragManager } from "./DragManager"; +import { CollectionViewType } from "../views/collections/CollectionBaseView"; +import { Doc, DocListCast } from "../../new_fields/Doc"; +import { DocumentType } from "../documents/DocumentTypes"; +import { ObjectField } from "../../new_fields/ObjectField"; +import { StrCast } from "../../new_fields/Types"; +import { Docs } from "../documents/Documents"; +import { ScriptField } from "../../new_fields/ScriptField"; + + +function makeTemplate(doc: Doc): boolean { + let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + let layout = StrCast(layoutDoc.layout).match(/fieldKey={"[^"]*"}/)![0]; + let fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); + let docs = DocListCast(layoutDoc[fieldKey]); + let any = false; + docs.map(d => { + if (!StrCast(d.title).startsWith("-")) { + any = true; + return Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)); + } + if (d.type === DocumentType.COL) return makeTemplate(d); + return false; + }); + return any; +} +export function convertDropDataToButtons(data: DragManager.DocumentDragData) { + data && data.draggedDocuments.map((doc, i) => { + let dbox = doc; + if (!doc.onDragStart && !doc.onClick && doc.viewType !== CollectionViewType.Linear) { + let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; + if (layoutDoc.type === DocumentType.COL) { + layoutDoc.isTemplateDoc = makeTemplate(layoutDoc); + } else { + layoutDoc.isTemplateDoc = (layoutDoc.type === DocumentType.TEXT || layoutDoc.layout instanceof Doc) && !data.userDropAction; + } + dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: layoutDoc.isTemplateDoc ? "font" : "bolt" }); + dbox.dragFactory = layoutDoc; + dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; + dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); + } else if (doc.viewType === CollectionViewType.Linear) { + dbox.ignoreClick = true; + } + data.droppedDocuments[i] = dbox; + }); +} diff --git a/src/client/views/CollectionLinearView.tsx b/src/client/views/CollectionLinearView.tsx index 04e131135..e8ef20899 100644 --- a/src/client/views/CollectionLinearView.tsx +++ b/src/client/views/CollectionLinearView.tsx @@ -47,46 +47,6 @@ export class CollectionLinearView extends CollectionSubView(LinearDocument) { } } - makeTemplate = (doc: Doc): boolean => { - let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; - let layout = StrCast(layoutDoc.layout).match(/fieldKey={"[^"]*"}/)![0]; - let fieldKey = layout.replace('fieldKey={"', "").replace(/"}$/, ""); - let docs = DocListCast(layoutDoc[fieldKey]); - let any = false; - docs.map(d => { - if (!StrCast(d.title).startsWith("-")) { - any = true; - return Doc.MakeMetadataFieldTemplate(d, Doc.GetProto(layoutDoc)); - } - if (d.type === DocumentType.COL) return this.makeTemplate(d); - return false; - }); - return any; - } - - drop = action((e: Event, de: DragManager.DropEvent) => { - (de.data as DragManager.DocumentDragData).draggedDocuments.map((doc, i) => { - let dbox = doc; - if (!doc.onDragStart && !doc.onClick && this.props.Document.convertToButtons && doc.viewType !== CollectionViewType.Linear) { - let layoutDoc = doc.layout instanceof Doc && doc.layout.isTemplateField ? doc.layout : doc; - if (layoutDoc.type === DocumentType.COL) { - layoutDoc.isTemplateDoc = this.makeTemplate(layoutDoc); - } else { - layoutDoc.isTemplateDoc = (layoutDoc.type === DocumentType.TEXT || layoutDoc.layout instanceof Doc) && de.data instanceof DragManager.DocumentDragData && !de.data.userDropAction; - } - dbox = Docs.Create.FontIconDocument({ nativeWidth: 100, nativeHeight: 100, width: 100, height: 100, backgroundColor: StrCast(doc.backgroundColor), title: "Custom", icon: layoutDoc.isTemplateDoc ? "font" : "bolt" }); - dbox.dragFactory = layoutDoc; - dbox.removeDropProperties = doc.removeDropProperties instanceof ObjectField ? ObjectField.MakeCopy(doc.removeDropProperties) : undefined; - dbox.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)'); - } else if (doc.viewType === CollectionViewType.Linear) { - dbox.ignoreClick = true; - } - (de.data as DragManager.DocumentDragData).droppedDocuments[i] = dbox; - }); - e.stopPropagation(); - return super.drop(e, de); - }); - public isCurrent(doc: Doc) { return !doc.isMinimized && (Math.abs(NumCast(doc.displayTimecode, -1) - NumCast(this.Document.currentTimecode, -1)) < 1.5 || NumCast(doc.displayTimecode, -1) === -1); } dimension = () => NumCast(this.props.Document.height); // 2 * the padding diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index e54374ad7..f9f040c6b 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -65,7 +65,7 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) { let rowSpan = Math.ceil((height() + this.gridGap) / this.gridGap); let style = this.isStackingView ? { width: width(), margin: "auto", marginTop: i === 0 ? 0 : this.gridGap, height: height() } : { gridRowEnd: `span ${rowSpan}` }; return
    - {this.getDisplayDoc(pair.layout as Doc, pair.data, dxf, width)} + {pair.layout instanceof Doc && this.getDisplayDoc(pair.layout, pair.data, dxf, width)}
    ; }); } diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 1f8c0b18f..bc61492d0 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -6,7 +6,7 @@ import { Id } from "../../../new_fields/FieldSymbols"; import { List } from "../../../new_fields/List"; import { listSpec } from "../../../new_fields/Schema"; import { ScriptField } from "../../../new_fields/ScriptField"; -import { Cast } from "../../../new_fields/Types"; +import { Cast, StrCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { RouteStore } from "../../../server/RouteStore"; import { Utils } from "../../../Utils"; @@ -23,6 +23,8 @@ import React = require("react"); var path = require('path'); import { GooglePhotos } from "../../apis/google_docs/GooglePhotosClientUtils"; import { ImageUtils } from "../../util/Import & Export/ImageUtils"; +import { CollectionViewType } from "./CollectionBaseView"; +import { ObjectField } from "../../../new_fields/ObjectField"; export interface CollectionViewProps extends FieldViewProps { addDocument: (document: Doc) => boolean; @@ -126,6 +128,8 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { @undoBatch @action protected drop(e: Event, de: DragManager.DropEvent): boolean { + (this.props.Document.dropConverter instanceof ScriptField) && + this.props.Document.dropConverter.script.run({ dragData: de.data }); if (de.data instanceof DragManager.DocumentDragData && !de.data.applyAsTemplate) { if (de.mods === "AltKey" && de.data.draggedDocuments.length) { this.childDocs.map(doc => diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index bff8ce5c1..7d0c900a6 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -10,7 +10,6 @@ width:100%; position: relative; top:0; - padding-top: 20px; padding-left: 10px; padding-right: 10px; background: $light-color-secondary; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2c77c4b5b..5d88e6290 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -576,7 +576,7 @@ export class CollectionTreeView extends CollectionSubView(Document) { let moveDoc = (d: Doc, target: Doc, addDoc: (doc: Doc) => boolean) => this.props.moveDocument(d, target, addDoc); return !this.childDocs ? (null) : (
    this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx index c5bc2e7fb..962fe2a1c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinkView.tsx @@ -31,7 +31,7 @@ export class CollectionFreeFormLinkView extends React.Component(["dropAction"]), dragFactory: data.dragFactory + backgroundColor: data.backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory: data.dragFactory, })); } @@ -69,7 +70,8 @@ export class CurrentUserUtils { static setupCreatePanel(sidebarContainer: Doc, doc: Doc) { // setup a masonry view of all he creators const dragCreators = Docs.Create.MasonryDocument(CurrentUserUtils.setupCreatorButtons(doc), { - width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons" + width: 500, autoHeight: true, columnWidth: 35, ignoreClick: true, lockedPosition: true, chromeStatus: "disabled", title: "buttons", + dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), yMargin: 0 }); // setup a color picker const color = Docs.Create.ColorDocument({ @@ -81,7 +83,7 @@ export class CurrentUserUtils { panel: Docs.Create.StackingDocument([dragCreators, color], { width: 500, height: 800, chromeStatus: "disabled", title: "creator stack" }), - onClick: ScriptField.MakeScript("this.targetContainer.proto = this.panel") + onClick: ScriptField.MakeScript("this.targetContainer.proto = this.panel"), }); } @@ -148,7 +150,8 @@ export class CurrentUserUtils { doc.expandingButtons = Docs.Create.LinearDocument([doc.undoBtn as Doc, doc.redoBtn as Doc], { title: "expanding buttons", gridGap: 5, xMargin: 5, yMargin: 5, height: 42, width: 100, boxShadow: "0 0", - backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, convertToButtons: true, + backgroundColor: "black", preventTreeViewOpen: true, forceActive: true, lockedPosition: true, + dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }) }); } -- cgit v1.2.3-70-g09d2