diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client/util/BranchingTrailManager.tsx | 112 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 12 | ||||
-rw-r--r-- | src/client/util/RTFMarkup.tsx | 3 | ||||
-rw-r--r-- | src/client/util/SettingsManager.tsx | 30 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 2 | ||||
-rw-r--r-- | src/client/views/PropertiesView.scss | 7 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 30 | ||||
-rw-r--r-- | src/client/views/StyleProvider.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.scss | 19 | ||||
-rw-r--r-- | src/client/views/collections/TreeView.tsx | 65 | ||||
-rw-r--r-- | src/client/views/newlightbox/components/Recommendation/Recommendation.tsx | 4 | ||||
-rw-r--r-- | src/client/views/nodes/ComparisonBox.tsx | 2 | ||||
-rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 23 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresElementBox.scss | 4 | ||||
-rw-r--r-- | src/client/views/nodes/trails/PresElementBox.tsx | 45 | ||||
-rw-r--r-- | src/server/server_Initialization.ts | 4 |
17 files changed, 332 insertions, 35 deletions
diff --git a/src/client/util/BranchingTrailManager.tsx b/src/client/util/BranchingTrailManager.tsx new file mode 100644 index 000000000..44cec6922 --- /dev/null +++ b/src/client/util/BranchingTrailManager.tsx @@ -0,0 +1,112 @@ +import { action, computed, observable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { Doc } from '../../fields/Doc'; +import { Id } from '../../fields/FieldSymbols'; +import { PresBox } from '../views/nodes/trails'; +import { OverlayView } from '../views/OverlayView'; +import { DocumentManager } from './DocumentManager'; + +@observer +export class BranchingTrailManager extends React.Component { + public static Instance: BranchingTrailManager; + + constructor(props: any) { + super(props); + if (!BranchingTrailManager.Instance) { + BranchingTrailManager.Instance = this; + } + } + + setupUi = () => { + OverlayView.Instance.addWindow(<BranchingTrailManager></BranchingTrailManager>, { x: 100, y: 150, width: 1000, title: 'Branching Trail' }); + }; + + // stack of the history + @observable private slideHistoryStack: String[] = []; + @action setSlideHistoryStack = action((newArr: String[]) => { + this.slideHistoryStack = newArr; + }); + + @observable private containsSet: Set<String> = new Set<String>(); + + // prev pres to copmare with + @observable private prevPresId: String | null = null; + @action setPrevPres = action((newId: String | null) => { + this.prevPresId = newId; + }); + + // docId to Doc map + @observable private docIdToDocMap: Map<String, Doc> = new Map<String, Doc>(); + + observeDocumentChange = (targetDoc: Doc, pres: PresBox) => { + const presId = pres.props.Document[Id]; + if (this.prevPresId === presId) { + return; + } + + const targetDocId = targetDoc[Id]; + this.docIdToDocMap.set(targetDocId, targetDoc); + + if (this.prevPresId === null) { + this.setupUi(); + } + + if (this.prevPresId === null || this.prevPresId !== presId) { + this.setPrevPres(presId); + // REVERT THE SET + const stringified = [presId, targetDocId].toString(); + if (this.containsSet.has([presId, targetDocId].toString())) { + // remove all the elements after the targetDocId + const newStack = this.slideHistoryStack.slice(0, this.slideHistoryStack.indexOf(stringified)); + const removed = this.slideHistoryStack.slice(this.slideHistoryStack.indexOf(stringified)); + this.setSlideHistoryStack(newStack); + + removed.forEach(info => this.containsSet.delete(info.toString())); + } else { + this.setSlideHistoryStack([...this.slideHistoryStack, stringified]); + this.containsSet.add(stringified); + } + } + }; + + clickHandler = (e: React.PointerEvent<HTMLButtonElement>, targetDocId: string, removeIndex: number) => { + const targetDoc = this.docIdToDocMap.get(targetDocId); + if (!targetDoc) { + return; + } + const newStack = this.slideHistoryStack.slice(0, removeIndex); + const removed = this.slideHistoryStack.slice(removeIndex); + this.setSlideHistoryStack(newStack); + + removed.forEach(info => this.containsSet.delete(info.toString())); + DocumentManager.Instance.showDocument(targetDoc, { willZoomCentered: true }); + //PresBox.NavigateToTarget(targetDoc, targetDoc); + }; + + @computed get trailBreadcrumbs() { + return ( + <div style={{ border: '.5rem solid green', padding: '5px', backgroundColor: 'white', minHeight: '50px' }}> + {this.slideHistoryStack.map((info, index) => { + const [presId, targetDocId] = info.split(','); + const doc = this.docIdToDocMap.get(targetDocId); + if (!doc) { + return <></>; + } + return ( + <span key={targetDocId}> + <button key={index} onPointerDown={e => this.clickHandler(e, targetDocId, index)}> + {presId.slice(0, 3) + ':' + doc.title} + </button> + -{'>'} + </span> + ); + })} + </div> + ); + } + + render() { + return <div>{BranchingTrailManager.Instance.trailBreadcrumbs}</div>; + } +} diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 54828867e..2e83a1655 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -294,7 +294,7 @@ export class CurrentUserUtils { { toolTip: "Tap or drag to create a note", title: "Note", icon: "sticky-note", dragFactory: doc.emptyNote as Doc, clickFactory: DocCast(doc.emptyNote)}, { toolTip: "Tap or drag to create a flashcard", title: "Flashcard", icon: "id-card", dragFactory: doc.emptyFlashcard as Doc, clickFactory: DocCast(doc.emptyFlashcard)}, { toolTip: "Tap or drag to create an equation", title: "Math", icon: "calculator", dragFactory: doc.emptyEquation as Doc, clickFactory: DocCast(doc.emptyEquation)}, - { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation)}, + { toolTip: "Tap or drag to create a physics simulation",title: "Simulation", icon: "rocket",dragFactory: doc.emptySimulation as Doc, clickFactory: DocCast(doc.emptySimulation), funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a note board", title: "Notes", icon: "folder", dragFactory: doc.emptyNoteboard as Doc, clickFactory: DocCast(doc.emptyNoteboard)}, { toolTip: "Tap or drag to create a collection", title: "Col", icon: "folder", dragFactory: doc.emptyCollection as Doc, clickFactory: DocCast(doc.emptyTab)}, { toolTip: "Tap or drag to create a webpage", title: "Web", icon: "globe-asia", dragFactory: doc.emptyWebpage as Doc, clickFactory: DocCast(doc.emptyWebpage)}, @@ -304,12 +304,12 @@ export class CurrentUserUtils { { toolTip: "Tap or drag to create a screen grabber", title: "Grab", icon: "photo-video", dragFactory: doc.emptyScreengrab as Doc, clickFactory: DocCast(doc.emptyScreengrab), openFactoryLocation: OpenWhere.overlay}, { toolTip: "Tap or drag to create a WebCam recorder", title: "WebCam", icon: "photo-video", dragFactory: doc.emptyWebCam as Doc, clickFactory: DocCast(doc.emptyWebCam), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, { toolTip: "Tap or drag to create a button", title: "Button", icon: "bolt", dragFactory: doc.emptyButton as Doc, clickFactory: DocCast(doc.emptyButton)}, - { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, clickFactory: DocCast(doc.emptyScript)}, - { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "chart-bar", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)}, - { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "file", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay}, - { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize",dragFactory: doc.emptyHeader as Doc,clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true }, + { toolTip: "Tap or drag to create a scripting box", title: "Script", icon: "terminal", dragFactory: doc.emptyScript as Doc, clickFactory: DocCast(doc.emptyScript), funcs: { hidden: "IsNoviceMode()"}}, + { toolTip: "Tap or drag to create a data viz node", title: "DataViz", icon: "chart-bar", dragFactory: doc.emptyDataViz as Doc, clickFactory: DocCast(doc.emptyDataViz)}, + { toolTip: "Tap or drag to create a bullet slide", title: "PPT Slide", icon: "file", dragFactory: doc.emptySlide as Doc, clickFactory: DocCast(doc.emptySlide), openFactoryLocation: OpenWhere.overlay, funcs: { hidden: "IsNoviceMode()"}}, + { toolTip: "Tap or drag to create a data note", title: "DataNote", icon: "window-maximize",dragFactory: doc.emptyHeader as Doc,clickFactory: DocCast(doc.emptyHeader), openFactoryAsDelegate: true, funcs: { hidden: "IsNoviceMode()"} }, { toolTip: "Toggle a Calculator REPL", title: "replviewer", icon: "calculator", clickFactory: '<ScriptingRepl />' as any, openFactoryLocation: OpenWhere.overlay}, // hack: clickFactory is not a Doc but will get interpreted as a custom UI by the openDoc() onClick script - { toolTip: "Toggle an UndoStack", title: "undostacker", icon: "calculator", clickFactory: "<UndoStack>" as any, openFactoryLocation: OpenWhere.overlay}, + // { toolTip: "Toggle an UndoStack", title: "undostacker", icon: "calculator", clickFactory: "<UndoStack>" as any, openFactoryLocation: OpenWhere.overlay}, ].map(tuple => ( { openFactoryLocation: OpenWhere.addRight, scripts: { onClick: 'openDoc(copyDragFactory(this.clickFactory,this.openFactoryAsDelegate), this.openFactoryLocation)', diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx index c2f121e1f..afc880a7b 100644 --- a/src/client/util/RTFMarkup.tsx +++ b/src/client/util/RTFMarkup.tsx @@ -2,6 +2,7 @@ import { action, computed, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { MainViewModal } from '../views/MainViewModal'; +import { SettingsManager } from './SettingsManager'; @observer export class RTFMarkup extends React.Component<{}> { @@ -30,7 +31,7 @@ export class RTFMarkup extends React.Component<{}> { */ @computed get cheatSheet() { return ( - <div style={{ background: 'white', textAlign: 'initial', height: '100%' }}> + <div style={{ background: SettingsManager.Instance.userBackgroundColor, color: SettingsManager.Instance.userColor, textAlign: 'initial', height: '100%' }}> <p> <b style={{ fontSize: 'larger' }}>{`wiki:phrase`}</b> {` display wikipedia page for entered text (terminate with carriage return)`} diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 6acba8af4..a2e5e54fe 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -169,9 +169,33 @@ export class SettingsManager extends React.Component<{}> { /> {userTheme === ColorScheme.Custom && ( <Group formLabel="Custom Theme"> - <ColorPicker tooltip={'User Color'} color={this.userColor} type={Type.SEC} icon={<FaFillDrip />} selectedColor={this.userColor} setSelectedColor={this.switchUserColor} /> - <ColorPicker tooltip={'User Background Color'} color={this.userColor} type={Type.SEC} icon={<FaPalette />} selectedColor={this.userBackgroundColor} setSelectedColor={this.switchUserBackgroundColor} /> - <ColorPicker tooltip={'User Variant Color'} color={this.userColor} type={Type.SEC} icon={<FaPalette />} selectedColor={this.userVariantColor} setSelectedColor={this.switchUserVariantColor} /> + <ColorPicker + tooltip={'User Color'} // + color={this.userColor} + type={Type.SEC} + icon={<FaFillDrip />} + selectedColor={this.userColor} + setSelectedColor={this.switchUserColor} + setFinalColor={this.switchUserColor} + /> + <ColorPicker + tooltip={'User Background Color'} + color={this.userColor} + type={Type.SEC} + icon={<FaPalette />} + selectedColor={this.userBackgroundColor} + setSelectedColor={this.switchUserBackgroundColor} + setFinalColor={this.switchUserBackgroundColor} + /> + <ColorPicker + tooltip={'User Variant Color'} + color={this.userColor} + type={Type.SEC} + icon={<FaPalette />} + selectedColor={this.userVariantColor} + setSelectedColor={this.switchUserVariantColor} + setFinalColor={this.switchUserVariantColor} + /> </Group> )} </div> diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 6dd1d53ee..730a926a2 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -12,6 +12,7 @@ import { TrackMovements } from '../util/TrackMovements'; import { CollectionView } from './collections/CollectionView'; import { MainView } from './MainView'; import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import +import { BranchingTrailManager } from '../util/BranchingTrailManager'; import { PingManager } from '../util/PingManager'; import './global/globalScripts'; dotenv.config(); @@ -50,6 +51,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' }; document.cookie = `loadtime=${loading};${expires};path=/`; new TrackMovements(); new ReplayMovements(); + new BranchingTrailManager(); new PingManager(); root.render(<MainView />); }, 0); diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 1a7c9eb64..a0b054851 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -1,5 +1,12 @@ @import './global/globalCssVariables.scss'; +.propertiesView-presentationTrails-title { + display: flex; +} +.propertiesView-presentationTrails-title-icon { + position: absolute; + right: 4; +} .propertiesView { height: 100%; width: 250; diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index 1b6037ed9..82ab54787 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -39,6 +39,7 @@ import { DefaultStyleProvider } from './StyleProvider'; import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView'; import { KeyValueBox } from './nodes/KeyValueBox'; import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails'; +import { SettingsManager } from '../util/SettingsManager'; const higflyout = require('@hig/flyout'); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -1701,7 +1702,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { </div> {!selectedItem ? null : ( <div className="propertiesView-presentationTrails"> - <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> + <div + className="propertiesView-presentationTrails-title" + onPointerDown={action(() => (this.openPresTransitions = !this.openPresTransitions))} + style={{ + color: SettingsManager.Instance.userColor, + backgroundColor: this.openPresTransitions ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Transitions <div className="propertiesView-presentationTrails-title-icon"> <FontAwesomeIcon icon={this.openPresTransitions ? 'caret-down' : 'caret-right'} size="lg" /> @@ -1715,7 +1722,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresVisibilityAndDuration = !this.openPresVisibilityAndDuration))} - style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> + style={{ + color: SettingsManager.Instance.userColor, + backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Visibilty <div className="propertiesView-presentationTrails-title-icon"> <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" /> @@ -1726,7 +1736,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { )} {!selectedItem ? null : ( <div className="propertiesView-presentationTrails"> - <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} style={{ backgroundColor: this.openPresTransitions ? 'black' : '' }}> + <div + className="propertiesView-presentationTrails-title" + onPointerDown={action(() => (this.openPresProgressivize = !this.openPresProgressivize))} + style={{ + color: SettingsManager.Instance.userColor, + backgroundColor: this.openPresProgressivize ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> Progressivize <div className="propertiesView-presentationTrails-title-icon"> <FontAwesomeIcon icon={this.openPresProgressivize ? 'caret-down' : 'caret-right'} size="lg" /> @@ -1737,7 +1753,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { )} {!selectedItem || (type !== DocumentType.VID && type !== DocumentType.AUDIO) ? null : ( <div className="propertiesView-presentationTrails"> - <div className="propertiesView-presentationTrails-title" onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} style={{ backgroundColor: this.openSlideOptions ? 'black' : '' }}> + <div + className="propertiesView-presentationTrails-title" + onPointerDown={action(() => (this.openSlideOptions = !this.openSlideOptions))} + style={{ + color: SettingsManager.Instance.userColor, + backgroundColor: this.openSlideOptions ? SettingsManager.Instance.userVariantColor : SettingsManager.Instance.userBackgroundColor, + }}> <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={type === DocumentType.AUDIO ? 'file-audio' : 'file-video'} /> {type === DocumentType.AUDIO ? 'Audio Options' : 'Video Options'} <div className="propertiesView-presentationTrails-title-icon"> <FontAwesomeIcon icon={this.openSlideOptions ? 'caret-down' : 'caret-right'} size="lg" /> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index c2dcf071d..46243d50a 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -239,12 +239,12 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps switch (doc?.type) { case DocumentType.COL: return StrCast( - doc?.layout_borderRounding, + doc?.layout_boxShadow, doc?._type_collection === CollectionViewType.Pile ? '4px 4px 10px 2px' : lockedPosition() || doc?._isGroup || docProps?.LayoutTemplateString ? undefined // groups have no drop shadow -- they're supposed to be "invisible". LayoutString's imply collection is being rendered as something else (e.g., title of a Slide) - : `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.layout_borderRounding, '0.2vw 0.2vw 0.8vw')}` + : `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}` ); case DocumentType.LABEL: diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index d22e85880..d3ba23b4e 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -23,6 +23,25 @@ .treeView-bulletIcons { width: 100%; height: 100%; + // position: absolute; + + .treeView-expandIcon { + display: none; + left: -8px; + position: absolute; + } + + .treeView-checkIcon { + left: 3.5px; + top: 2px; + position: absolute; + } + + &:hover { + .treeView-expandIcon { + display: unset; + } + } position: relative; display: flex; flex-direction: row; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index 27f9ebc49..a3725be75 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, IReactionDisposer, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; -import { Doc, DocListCast, Field, Opt, StrListCast } from '../../../fields/Doc'; +import { Doc, DocListCast, Field, FieldResult, Opt, StrListCast } from '../../../fields/Doc'; import { DocData, Height, Width } from '../../../fields/DocSymbols'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -227,6 +227,39 @@ export class TreeView extends React.Component<TreeViewProps> { } }; + @undoBatch + @action + recurToggle = (childList: Doc[]) => { + if (childList.length > 0) { + childList.forEach(child => { + console.log(child); + child.runProcess = !!!child.runProcess; + TreeView.ToggleChildrenRun.get(child)?.(); + }); + } + }; + + @undoBatch + @action + getRunningChildren = (childList: Doc[]) => { + if (childList.length === 0) { + return []; + } + + const runningChildren: FieldResult[] = []; + childList.forEach(child => { + if (child.runProcess && TreeView.GetRunningChildren.get(child)) { + if (child.runProcess) { + runningChildren.push(child); + } + runningChildren.push(...(TreeView.GetRunningChildren.get(child)?.() ?? [])); + } + }); + return runningChildren; + }; + + static GetRunningChildren = new Map<Doc, any>(); + static ToggleChildrenRun = new Map<Doc, () => void>(); constructor(props: any) { super(props); if (!TreeView._openLevelScript) { @@ -235,6 +268,19 @@ export class TreeView extends React.Component<TreeViewProps> { } this._openScript = Doc.IsSystem(this.props.document) ? undefined : () => TreeView._openLevelScript!; this._editTitleScript = Doc.IsSystem(this.props.document) ? () => TreeView._openLevelScript! : () => TreeView._openTitleScript!; + + // set for child processing highligting + // this.dataDoc.testing = 'testing'; + console.log(this.doc, this.dataDoc, this.childDocs); + this.dataDoc.hasChildren = this.childDocs.length > 0; + // this.dataDoc.children = this.childDocs; + TreeView.ToggleChildrenRun.set(this.doc, () => { + this.recurToggle(this.childDocs); + }); + + TreeView.GetRunningChildren.set(this.doc, () => { + return this.getRunningChildren(this.childDocs); + }); } _treeEle: any; @@ -722,15 +768,14 @@ export class TreeView extends React.Component<TreeViewProps> { ) ) : ( <div className="treeView-bulletIcons" style={{ color: Doc.IsSystem(DocCast(this.doc.proto)) ? 'red' : undefined }}> - {this.onCheckedClick ? ( - <IconButton - color={color} - icon={<FontAwesomeIcon size="sm" icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'} />} - size={Size.XSMALL} + <div className={`treeView-${this.onCheckedClick ? 'checkIcon' : 'expandIcon'}`}> + <FontAwesomeIcon + size="sm" + style={{ display: this.childDocs?.length >= 1 ? 'block' : 'none' }} + icon={checked === 'check' ? 'check' : checked === 'x' ? 'times' : checked === 'unchecked' ? 'square' : !this.treeViewOpen ? 'caret-right' : 'caret-down'} /> - ) : ( - <IconButton color={color} icon={<FontAwesomeIcon icon={iconType as IconProp} />} size={Size.XSMALL} /> - )} + </div> + {this.onCheckedClick ? null : typeof iconType === 'string' ? <FontAwesomeIcon icon={iconType as IconProp} /> : iconType} </div> )} </div> @@ -928,8 +973,8 @@ export class TreeView extends React.Component<TreeViewProps> { } })} Document={this.doc} + DataDoc={undefined} // or this.dataDoc? layout_fitWidth={returnTrue} - DataDoc={undefined} scriptContext={this} hideDecorationTitle={this.props.treeView.outlineMode} hideResizeHandles={this.props.treeView.outlineMode} diff --git a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx index 2c2f04b9f..96846673b 100644 --- a/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx +++ b/src/client/views/newlightbox/components/Recommendation/Recommendation.tsx @@ -25,11 +25,11 @@ export const Recommendation = (props: IRecommendation) => { switch (type) { case 'YouTube': console.log('create ', type, 'document'); - doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript: transcript }); + doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript }); break; case 'Video': console.log('create ', type, 'document'); - doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript: transcript }); + doc = Docs.Create.VideoDocument(data, { title: title, _width: 400, _height: 315, transcript }); break; case 'Webpage': console.log('create ', type, 'document'); diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx index ca5ec9389..a334e75f1 100644 --- a/src/client/views/nodes/ComparisonBox.tsx +++ b/src/client/views/nodes/ComparisonBox.tsx @@ -96,7 +96,7 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl const anchor = Docs.Create.ConfigDocument({ title: 'CompareAnchor:' + this.rootDoc.title, // set presentation timing properties for restoring view - presTransition: 1000, + presentation_transition: 1000, annotationOn: this.rootDoc, }); if (anchor) { diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index c7ccd1ea0..44da98f75 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -82,7 +82,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp config_panX: NumCast(this.layoutDoc._freeform_panX), config_panY: NumCast(this.layoutDoc._freeform_panY), config_viewScale: Cast(this.layoutDoc._freeform_scale, 'number', null), - presentation_transition: 1000, annotationOn: this.rootDoc, }); if (anchor) { diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 05f59d8fe..b02e7ecbd 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -36,6 +36,8 @@ import { FieldView, FieldViewProps } from '../FieldView'; import { ScriptingBox } from '../ScriptingBox'; import './PresBox.scss'; import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums'; +import { BranchingTrailManager } from '../../../util/BranchingTrailManager'; +import { TreeView } from '../../collections/TreeView'; const { Howl } = require('howler'); export interface pinDataTypes { @@ -256,7 +258,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { const serial = nextSelected + 1 < this.childDocs.length && NumCast(this.childDocs[nextSelected + 1].presentation_groupWithUp) > 1; if (serial) { this.gotoDocument(nextSelected, this.activeItem, true, async () => { - const waitTime = NumCast(this.activeItem.presentation_duration) - NumCast(this.activeItem.presentation_transition); + const waitTime = NumCast(this.activeItem.presentation_duration); await new Promise<void>(res => setTimeout(() => res(), Math.max(0, waitTime))); doGroupWithUp(nextSelected + 1)(); }); @@ -279,6 +281,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { return listItems.filter(doc => !doc.layout_unrendered); } }; + + // go to documents chain + runSubroutines = (childrenToRun: Doc[], normallyNextSlide: Doc) => { + console.log(childrenToRun, normallyNextSlide, 'runSUBFUNC'); + if (childrenToRun[0] === normallyNextSlide) { + return; + } + + childrenToRun.forEach(child => { + DocumentManager.Instance.showDocument(child, {}); + }); + }; + // Called when the user activates 'next' - to move to the next part of the pres. trail @action next = () => { @@ -319,6 +334,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { // Case 1: No more frames in current doc and next slide is defined, therefore move to next slide const slides = DocListCast(this.rootDoc[StrCast(this.presFieldKey, 'data')]); const curLast = this.selectedArray.size ? Math.max(...Array.from(this.selectedArray).map(d => slides.indexOf(DocCast(d)))) : this.itemIndex; + + // before moving onto next slide, run the subroutines :) + const currentDoc = this.childDocs[this.itemIndex]; + this.runSubroutines(TreeView.GetRunningChildren.get(currentDoc)?.(), this.childDocs[this.itemIndex + 1]); + this.nextSlide(curLast + 1 === this.childDocs.length ? (this.layoutDoc.presLoop ? 0 : curLast) : curLast + 1); progressiveReveal(true); // shows first progressive document, but without a transition effect } else { @@ -691,6 +711,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { navigateToActiveItem = (afterNav?: () => void) => { const activeItem: Doc = this.activeItem; const targetDoc: Doc = this.targetDoc; + BranchingTrailManager.Instance.observeDocumentChange(targetDoc, this); const finished = () => { afterNav?.(); console.log('Finish Slide Nav: ' + targetDoc.title); diff --git a/src/client/views/nodes/trails/PresElementBox.scss b/src/client/views/nodes/trails/PresElementBox.scss index 4f95f0c1f..9ac2b5a94 100644 --- a/src/client/views/nodes/trails/PresElementBox.scss +++ b/src/client/views/nodes/trails/PresElementBox.scss @@ -4,6 +4,10 @@ $light-background: #ececec; $slide-background: #d5dce2; $slide-active: #5b9fdd; +.testingv2 { + background-color: red; +} + .presItem-container { cursor: grab; display: flex; diff --git a/src/client/views/nodes/trails/PresElementBox.tsx b/src/client/views/nodes/trails/PresElementBox.tsx index 5de51dbe9..6bc1e95ac 100644 --- a/src/client/views/nodes/trails/PresElementBox.tsx +++ b/src/client/views/nodes/trails/PresElementBox.tsx @@ -25,6 +25,7 @@ import { PresBox } from './PresBox'; import './PresElementBox.scss'; import { PresMovement } from './PresEnums'; import React = require('react'); +import { TreeView } from '../../collections/TreeView'; /** * This class models the view a document added to presentation will have in the presentation. * It involves some functionality for its buttons and options. @@ -399,6 +400,19 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { } }; + @undoBatch + @action + lfg = (e: React.MouseEvent) => { + e.stopPropagation(); + console.log('lfg called'); + // TODO: fix this bug + const { toggleChildrenRun } = this.rootDoc; + TreeView.ToggleChildrenRun.get(this.rootDoc)?.(); + + // call this.rootDoc.recurChildren() to get all the children + // if (iconClick) PresElementBox.showVideo = false; + }; + @computed get toolbarWidth(): number { const presBoxDocView = DocumentManager.Instance.getDocumentView(this.presBox); @@ -414,6 +428,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; const targetDoc: Doc = this.targetDoc; const activeItem: Doc = this.rootDoc; + const hasChildren: boolean = Cast(this.rootDoc?.hasChildren, 'boolean') || false; const items: JSX.Element[] = []; items.push( @@ -445,7 +460,17 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { ); if (this.indexInPres !== 0) { items.push( - <Tooltip key="arrow" title={<div className="dash-tooltip">{activeItem.presentation_groupWithUp ? 'Ungroup' : 'Group with up'}</div>}> + <Tooltip + key="arrow" + title={ + <div className="dash-tooltip"> + {!activeItem.presentation_groupWithUp + ? 'Not grouped with previous slide (click to group)' + : activeItem.presentation_groupWithUp === 1 + ? 'Run simultaneously with previous slide (click again to run after)' + : 'Run after previous slide (click to ungroup from previous)'} + </div> + }> <div className="slideButton" onClick={() => (activeItem.presentation_groupWithUp = (NumCast(activeItem.presentation_groupWithUp) + 1) % 3)} @@ -476,6 +501,22 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { </div> </Tooltip> ); + if (!Doc.noviceMode && hasChildren) { + // TODO: replace with if treeveiw, has childrenDocs + items.push( + <Tooltip key="children" title={<div className="dash-tooltip">Run child processes (tree only)</div>}> + <div + className="slideButton" + onClick={e => { + e.stopPropagation(); + this.lfg(e); + }} + style={{ fontWeight: 700 }}> + <FontAwesomeIcon icon={'circle-play'} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + } items.push( <Tooltip key="trash" title={<div className="dash-tooltip">Remove from presentation</div>}> <div className={'slideButton'} onClick={this.removePresentationItem}> @@ -522,7 +563,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps>() { ) : ( <div ref={this._dragRef} - className={`presItem-slide ${isCurrent ? 'active' : ''}`} + className={`presItem-slide ${isCurrent ? 'active' : ''}${this.rootDoc.runProcess ? ' testingv2' : ''}`} style={{ display: 'infline-block', backgroundColor: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BackgroundColor), diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index 354f809e0..ee32de152 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -176,8 +176,8 @@ function proxyServe(req: any, requrl: string, response: any) { const htmlText = htmlInputText .toString('utf8') .replace('<head>', '<head> <style>[id ^= "google"] { display: none; } </style>') - .replace('<script', '<noscript') - .replace('</script', '</noscript') + // .replace('<script', '<noscript') + // .replace('</script', '</noscript') // .replace(/href="https?([^"]*)"/g, httpsToCors) .replace(/data-srcset="[^"]*"/g, '') .replace(/srcset="[^"]*"/g, '') |