diff options
author | bob <bcz@cs.brown.edu> | 2020-02-06 10:38:18 -0500 |
---|---|---|
committer | bob <bcz@cs.brown.edu> | 2020-02-06 10:38:18 -0500 |
commit | 0817d947b98b1b8e7f05df6b1d3db8eef4996ec9 (patch) | |
tree | a9337a5c5459efb1eec21aec1513eecdaf9c1e8a /src | |
parent | e11d5ccc1974b1d0b9b66ddfe11df00c8fd45ccb (diff) |
added synching of timelines with presentations
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/collections/CollectionTimeView.tsx | 23 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.tsx | 45 | ||||
-rw-r--r-- | src/new_fields/ScriptField.ts | 4 |
3 files changed, 52 insertions, 20 deletions
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index ae5a3c7dc..1c4bfa4e8 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -19,6 +19,7 @@ import React = require("react"); import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import { RichTextField } from "../../../new_fields/RichTextField"; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; @observer export class CollectionTimeView extends CollectionSubView(doc => doc) { @@ -225,6 +226,21 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { </div>; } + specificMenu = (e: React.MouseEvent) => { + const layoutItems: ContextMenuProps[] = []; + + layoutItems.push({ description: "Force Timeline", event: () => { this.props.Document._forceRenderEngine = "timeline" }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Force Pivot", event: () => { this.props.Document._forceRenderEngine = "pivot" }, icon: "compress-arrows-alt" }); + layoutItems.push({ description: "Auto Time/Pivot layout", event: () => { this.props.Document._forceRenderEngine = undefined }, icon: "compress-arrows-alt" }); + layoutItems.push({ + description: "Sync with presentation", event: () => { + this.props.Document[this.props.fieldKey + "-timelineCur"] = ComputedField.MakeFunction("mainPres.curPresentation.data[mainPres.curPresentation._itemIndex].year || 0", { mainPres: Doc.name }, { mainPres: CurrentUserUtils.UserDocument }); + }, icon: "compress-arrows-alt" + }); + + ContextMenu.Instance.addItem({ description: "Pivot/Time Options ...", subitems: layoutItems, icon: "eye" }); + } + render() { const newEditableViewProps = { GetValue: () => "", @@ -248,7 +264,8 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { nonNumbers++; } }); - const doTimeline = nonNumbers / this.childDocs.length < 0.1 && this.props.PanelWidth() / this.props.PanelHeight() > 6; + const forceLayout = StrCast(this.props.Document._forceRenderEngine); + const doTimeline = forceLayout ? (forceLayout === "timeline") : nonNumbers / this.childDocs.length < 0.1 && this.props.PanelWidth() / this.props.PanelHeight() > 6; if (doTimeline !== (this._layoutEngine === "timeline")) { if (!this._changing) { this._changing = true; @@ -259,9 +276,11 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { } } + const facetCollection = Cast(this.props.Document?._facetCollection, Doc, null); return !facetCollection ? (null) : - <div className={"collectionTimeView" + (doTimeline ? "" : "-pivot")} style={{ height: `calc(100% - ${this.props.Document._chromeStatus === "enabled" ? 51 : 0}px)` }}> + <div className={"collectionTimeView" + (doTimeline ? "" : "-pivot")} onContextMenu={this.specificMenu} + style={{ height: `calc(100% - ${this.props.Document._chromeStatus === "enabled" ? 51 : 0}px)` }}> <div className={"pivotKeyEntry"}> <EditableView {...newEditableViewProps} menuCallback={this.menuCallback} /> </div> diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 44405c413..be5d414a5 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -2,10 +2,10 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faArrowLeft, faArrowRight, faEdit, faMinus, faPlay, faPlus, faStop, faTimes } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, IReactionDisposer, reaction, observable } from "mobx"; +import { action, computed, IReactionDisposer, reaction, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; -import { listSpec } from "../../../new_fields/Schema"; +import { listSpec, makeInterface } from "../../../new_fields/Schema"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { Docs } from "../../documents/Documents"; @@ -20,6 +20,9 @@ import { CollectionCarouselView } from "../collections/CollectionCarouselView"; import { returnFalse } from "../../../Utils"; import { ContextMenuProps } from "../ContextMenuItem"; import { CollectionTimeView } from "../collections/CollectionTimeView"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import { InkingControl } from "../InkingControl"; +import { InkTool } from "../../../new_fields/InkField"; library.add(faArrowLeft); library.add(faArrowRight); @@ -35,6 +38,8 @@ export class PresBox extends React.Component<FieldViewProps> { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } _childReaction: IReactionDisposer | undefined; _slideshowReaction: IReactionDisposer | undefined; + @observable _isChildActive = false; + componentDidMount() { const userDoc = CurrentUserUtils.UserDocument; this._slideshowReaction = reaction(() => this.props.Document._slideshow, @@ -54,16 +59,17 @@ export class PresBox extends React.Component<FieldViewProps> { this.props.Document.childLayout = undefined; } }, { fireImmediately: true }); - this._childReaction = reaction(() => this.childDocs.slice(), - (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); + this._childReaction = reaction(() => this.childDocs.slice(), (children) => children.forEach((child, i) => child.presentationIndex = i), { fireImmediately: true }); } componentWillUnmount() { this._childReaction?.(); + this._slideshowReaction?.(); } @computed get childDocs() { return DocListCast(this.props.Document[this.props.fieldKey]); } next = async () => { + runInAction(() => Doc.UserDoc().curPresentation = this.props.Document); const current = NumCast(this.props.Document._itemIndex); //asking to get document at current index const docAtCurrentNext = await this.getDocAtIndex(current + 1); @@ -81,6 +87,7 @@ export class PresBox extends React.Component<FieldViewProps> { } } back = async () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); const current = NumCast(this.props.Document._itemIndex); //requesting for the doc at current index const docAtCurrent = await this.getDocAtIndex(current); @@ -120,12 +127,17 @@ export class PresBox extends React.Component<FieldViewProps> { } } + whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); + active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) && + (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) + /** * This is the method that checks for the actions that need to be performed * after the document has been presented, which involves 3 button options: * Hide Until Presented, Hide After Presented, Fade After Presented */ showAfterPresented = (index: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((doc, ind) => { //the order of cases is aligned based on priority if (doc.hideTillShownButton && ind <= index) { @@ -146,6 +158,7 @@ export class PresBox extends React.Component<FieldViewProps> { * Hide Until Presented, Hide After Presented, Fade After Presented */ hideIfNotPresented = (index: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((key, ind) => { //the order of cases is aligned based on priority @@ -167,6 +180,7 @@ export class PresBox extends React.Component<FieldViewProps> { * te option open, navigates to that element. */ navigateToElement = async (curDoc: Doc, fromDocIndex: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); const fromDoc = this.childDocs[fromDocIndex].presentationTargetDoc as Doc; let docToJump = curDoc; let willZoom = false; @@ -257,8 +271,8 @@ export class PresBox extends React.Component<FieldViewProps> { //The function that is called when a document is clicked or reached through next or back. //it'll also execute the necessary actions if presentation is playing. - @action public gotoDocument = async (index: number, fromDoc: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); Doc.UnBrushAllDocs(); const list = FieldValue(Cast(this.props.Document[this.props.fieldKey], listSpec(Doc))); if (list && index >= 0 && index < list.length) { @@ -279,8 +293,8 @@ export class PresBox extends React.Component<FieldViewProps> { } //The function that starts or resets presentaton functionally, depending on status flag. - @action startOrResetPres = () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); if (this.props.Document.presStatus) { this.resetPresentation(); } else { @@ -299,8 +313,8 @@ export class PresBox extends React.Component<FieldViewProps> { //The function that resets the presentation by removing every action done by it. It also //stops the presentaton. - @action resetPresentation = () => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.forEach((doc: Doc) => { doc.opacity = 1; doc.viewScale = 1; @@ -315,6 +329,7 @@ export class PresBox extends React.Component<FieldViewProps> { //The function that starts the presentation, also checking if actions should be applied //directly at start. startPresentation = (startIndex: number) => { + action(() => Doc.UserDoc().curPresentation = this.props.Document); this.childDocs.map(doc => { if (doc.hideTillShownButton && this.childDocs.indexOf(doc) > startIndex) { doc.opacity = 0; @@ -343,18 +358,16 @@ export class PresBox extends React.Component<FieldViewProps> { specificContextMenu = (e: React.MouseEvent): void => { const funcs: ContextMenuProps[] = []; - funcs.push({ description: "Make Current Presentation", event: action(() => Doc.UserDoc().curPresentation = this.props.Document), icon: "asterisk" }); - funcs.push({ description: "Make slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); - funcs.push({ description: "Make timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); - funcs.push({ description: "Make list", event: action(() => this.props.Document._slideshow = "list"), icon: "asterisk" }); - ContextMenu.Instance.addItem({ description: "Presentatoin Funcs...", subitems: funcs, icon: "asterisk" }); + funcs.push({ description: "Show as Slideshow", event: action(() => this.props.Document._slideshow = "slideshow"), icon: "asterisk" }); + funcs.push({ description: "Show as Timeline", event: action(() => this.props.Document._slideshow = "timeline"), icon: "asterisk" }); + funcs.push({ description: "Show as List", event: action(() => this.props.Document._slideshow = "list"), icon: "asterisk" }); + ContextMenu.Instance.addItem({ description: "Presentation Funcs...", subitems: funcs, icon: "asterisk" }); } /** * Initially every document starts with a viewScale 1, which means * that they will be displayed in a canvas with scale 1. */ - @action initializeScaleViews = (docList: Doc[], viewtype: number) => { this.props.Document._chromeStatus = "disabled"; const hgt = (viewtype === CollectionViewType.Tree) ? 50 : 46; @@ -384,7 +397,7 @@ export class PresBox extends React.Component<FieldViewProps> { render() { this.initializeScaleViews(this.childDocs, NumCast(this.props.Document._viewType)); return (this.props.Document._slideshow ? - <div className="presBox-cont" onContextMenu={this.specificContextMenu}> + <div className="presBox-cont" onContextMenu={this.specificContextMenu} style={{ pointerEvents: this.active() ? "all" : "none" }} > {this.props.Document.inOverlay ? (null) : <div className="presBox-listCont" > {this.props.Document._slideshow === "slideshow" ? @@ -409,8 +422,8 @@ export class PresBox extends React.Component<FieldViewProps> { <button className="presBox-button" title="Next" onClick={this.next}><FontAwesomeIcon icon={"arrow-right"} /></button> <button className="presBox-button" title={this.props.Document.inOverlay ? "Expand" : "Minimize"} onClick={this.toggleMinimize}><FontAwesomeIcon icon={"eye"} /></button> {this.props.Document.inOverlay ? (null) : - <div className="presBox-listCont" > - <CollectionView {...this.props} PanelHeight={this.panelHeight} addDocument={this.addDocument} focus={this.selectElement} ScreenToLocalTransform={this.getTransform} /> + <div className="presBox-listCont"> + <CollectionView {...this.props} whenActiveChanged={this.whenActiveChanged} PanelHeight={this.panelHeight} addDocument={this.addDocument} focus={this.selectElement} ScreenToLocalTransform={this.getTransform} /> </div>} </div></div>); } diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts index f8a8d1226..4c78ea3aa 100644 --- a/src/new_fields/ScriptField.ts +++ b/src/new_fields/ScriptField.ts @@ -114,8 +114,8 @@ export class ScriptField extends ObjectField { }); return compiled; } - public static MakeFunction(script: string, params: object = {}) { - const compiled = ScriptField.CompileScript(script, params, true); + public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Field }) { + const compiled = ScriptField.CompileScript(script, params, true, capturedVariables); return compiled.compiled ? new ScriptField(compiled) : undefined; } |