diff options
-rw-r--r-- | src/client/views/MainView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/PresentationView.tsx | 165 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/presentationview/PresentationElement.tsx | 115 | ||||
-rw-r--r-- | src/client/views/presentationview/PresentationView.scss (renamed from src/client/views/PresentationView.scss) | 5 | ||||
-rw-r--r-- | src/client/views/presentationview/PresentationView.tsx | 203 |
6 files changed, 325 insertions, 167 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index a093ffdec..c98e6e8fb 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -14,7 +14,7 @@ import { Docs } from '../documents/Documents'; import { SetupDrag, DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; -import { PresentationView } from './PresentationView'; +import { PresentationView } from './presentationview/PresentationView'; import { CollectionDockingView } from './collections/CollectionDockingView'; import { ContextMenu } from './ContextMenu'; import { DocumentDecorations } from './DocumentDecorations'; diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx deleted file mode 100644 index b6e0f0889..000000000 --- a/src/client/views/PresentationView.tsx +++ /dev/null @@ -1,165 +0,0 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, runInAction, reaction } from "mobx"; -import "./PresentationView.scss"; -import { DocumentManager } from "../util/DocumentManager"; -import { Utils } from "../../Utils"; -import { Doc, DocListCast, DocListCastAsync } from "../../new_fields/Doc"; -import { listSpec } from "../../new_fields/Schema"; -import { Cast, NumCast, FieldValue, PromiseValue, StrCast, BoolCast } from "../../new_fields/Types"; -import { Id } from "../../new_fields/FieldSymbols"; -import { List } from "../../new_fields/List"; -import { CurrentUserUtils } from "../../server/authentication/models/current_user_utils"; - -export interface PresViewProps { - Document: Doc; -} - -interface PresListProps extends PresViewProps { - deleteDocument(index: number): void; - gotoDocument(index: number): void; -} - - -@observer -/** - * Component that takes in a document prop and a boolean whether it's collapsed or not. - */ -class PresentationViewList extends React.Component<PresListProps> { - - - /** - * Renders a single child document. It will just append a list element. - * @param document The document to render. - */ - renderChild = (document: Doc, index: number) => { - let title = document.title; - - //to get currently selected presentation doc - let selected = NumCast(this.props.Document.selectedDoc, 0); - - let className = "presentationView-item"; - if (selected === index) { - //this doc is selected - className += " presentationView-selected"; - } - let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } - let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } - return ( - <div className={className} key={document[Id] + index} - onPointerEnter={onEnter} onPointerLeave={onLeave} - style={{ - outlineColor: "maroon", - outlineStyle: "dashed", - outlineWidth: BoolCast(document.libraryBrush, false) || BoolCast(document.protoBrush, false) ? `1px` : "0px", - }} - onClick={e => { this.props.gotoDocument(index); e.stopPropagation(); }}> - <strong className="presentationView-name"> - {`${index + 1}. ${title}`} - </strong> - <button className="presentation-icon" onClick={e => { this.props.deleteDocument(index); e.stopPropagation(); }}>X</button> - <br></br> - <button className="presentation-interaction">A</button> - <button className="presentation-interaction">B</button> - <button className="presentation-interaction">C</button> - <button className="presentation-interaction">D</button> - - </div> - ); - - } - - render() { - const children = DocListCast(this.props.Document.data); - - return ( - <div className="presentationView-listCont"> - {children.map(this.renderChild)} - </div> - ); - } -} - - -@observer -export class PresentationView extends React.Component<PresViewProps> { - public static Instance: PresentationView; - - //observable means render is re-called every time variable is changed - @observable - collapsed: boolean = false; - closePresentation = action(() => this.props.Document.width = 0); - next = () => { - const current = NumCast(this.props.Document.selectedDoc); - this.gotoDocument(current + 1); - - } - back = () => { - const current = NumCast(this.props.Document.selectedDoc); - this.gotoDocument(current - 1); - } - - @action - public RemoveDoc = (index: number) => { - const value = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); - if (value) { - value.splice(index, 1); - } - } - - public gotoDocument = async (index: number) => { - const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); - if (!list) { - return; - } - if (index < 0 || index >= list.length) { - return; - } - - this.props.Document.selectedDoc = index; - const doc = await list[index]; - DocumentManager.Instance.jumpToDocument(doc); - } - - //initilize class variables - constructor(props: PresViewProps) { - super(props); - PresentationView.Instance = this; - } - - /** - * Adds a document to the presentation view - **/ - @action - public PinDoc(doc: Doc) { - //add this new doc to props.Document - const data = Cast(this.props.Document.data, listSpec(Doc)); - if (data) { - data.push(doc); - } else { - this.props.Document.data = new List([doc]); - } - - this.props.Document.width = 300; - } - - render() { - let titleStr = StrCast(this.props.Document.title); - let width = NumCast(this.props.Document.width); - - //TODO: next and back should be icons - return ( - <div className="presentationView-cont" style={{ width: width, overflow: "hidden" }}> - <div className="presentationView-heading"> - <div className="presentationView-title">{titleStr}</div> - <button className='presentation-icon' onClick={this.closePresentation}>X</button> - </div> - <div className="presentation-buttons"> - <button className="presentation-button" onClick={this.back}>back</button> - <button className="presentation-button" onClick={this.next}>next</button> - </div> - <PresentationViewList Document={this.props.Document} deleteDocument={this.RemoveDoc} gotoDocument={this.gotoDocument} /> - </div> - ); - } -}
\ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7750b9173..984cac9b9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -23,7 +23,7 @@ import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { DocComponent } from "../DocComponent"; -import { PresentationView } from "../PresentationView"; +import { PresentationView } from "../presentationview/PresentationView"; import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; diff --git a/src/client/views/presentationview/PresentationElement.tsx b/src/client/views/presentationview/PresentationElement.tsx new file mode 100644 index 000000000..02d97ee4d --- /dev/null +++ b/src/client/views/presentationview/PresentationElement.tsx @@ -0,0 +1,115 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { Doc } from "../../../new_fields/Doc"; +import { NumCast, BoolCast } from "../../../new_fields/Types"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { observable, action } from "mobx"; +import "./PresentationView.scss"; + + + +interface PresentationElementProps { + mainDocument: Doc; + document: Doc; + index: number; + deleteDocument(index: number): void; + gotoDocument(index: number): void; + groupedMembers: [Doc[]]; + allListElements: Doc[]; + +} + +@observer +export default class PresentationElement extends React.Component<PresentationElementProps> { + + @observable selectedButtons: boolean[] = new Array(6); + + + @action + onGroupClick = (document: Doc, index: number, buttonStatus: boolean[] | boolean) => { + let p = this.props; + if (Array.isArray(buttonStatus)) { + if (buttonStatus[5]) { + buttonStatus[5] = false; + console.log("Reached!"); + if (index >= 1) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); + } + } + } else { + buttonStatus[5] = true; + if (index >= 1) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1].push(doc)); + } + p.groupedMembers[index - 1].push(document); + //this.onGroupClick() + } + } + } else { + if (!buttonStatus) { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => p.groupedMembers[index - 1] = p.groupedMembers[index - 1].slice(p.groupedMembers[index - 1].indexOf(doc), 1)); + } + } else { + if (p.groupedMembers[index].length >= 0) { + p.groupedMembers[index].forEach((doc: Doc) => { if (!p.groupedMembers[index - 1].includes(doc)) { p.groupedMembers[index - 1].push(doc); } }); + } + if (!p.groupedMembers[index - 1].includes(document)) { + p.groupedMembers[index - 1].push(document); + } + } + } + if (index >= 2) { + this.onGroupClick(p.allListElements[index - 1], index - 1, p.groupedMembers[index - 2].length !== 0); + } + + p.groupedMembers.forEach((docArray: Doc[], index: number) => console.log("Index: ", index, " size: ", docArray.length)); + console.log("Group Size: ", p.groupedMembers[index - 1].length); + } + + + + render() { + let p = this.props; + let title = p.document.title; + + //to get currently selected presentation doc + let selected = NumCast(p.mainDocument.selectedDoc, 0); + + let className = "presentationView-item"; + if (selected === p.index) { + //this doc is selected + className += " presentationView-selected"; + } + let onEnter = (e: React.PointerEvent) => { p.document.libraryBrush = true; } + let onLeave = (e: React.PointerEvent) => { p.document.libraryBrush = false; } + return ( + <div className={className} key={p.document[Id] + p.index} + onPointerEnter={onEnter} onPointerLeave={onLeave} + style={{ + outlineColor: "maroon", + outlineStyle: "dashed", + outlineWidth: BoolCast(p.document.libraryBrush, false) || BoolCast(p.document.protoBrush, false) ? `1px` : "0px", + }} + onClick={e => { p.gotoDocument(p.index); e.stopPropagation(); }}> + <strong className="presentationView-name"> + {`${p.index + 1}. ${title}`} + </strong> + <button className="presentation-icon" onClick={e => { this.props.deleteDocument(p.index); e.stopPropagation(); }}>X</button> + <br></br> + <button className={this.selectedButtons[0] ? "presentation-interaction-selected" : "presentation-interaction"}>A</button> + <button className={this.selectedButtons[1] ? "presentation-interaction-selected" : "presentation-interaction"}>B</button> + <button className={this.selectedButtons[2] ? "presentation-interaction-selected" : "presentation-interaction"}>C</button> + <button className={this.selectedButtons[3] ? "presentation-interaction-selected" : "presentation-interaction"}>D</button> + <button className={this.selectedButtons[4] ? "presentation-interaction-selected" : "presentation-interaction"}>E</button> + <button className={this.selectedButtons[5] ? "presentation-interaction-selected" : "presentation-interaction"} onClick={(e) => { + e.stopPropagation(); + this.onGroupClick(p.document, p.index, this.selectedButtons); + }}>F</button> + + </div> + ); + } +}
\ No newline at end of file diff --git a/src/client/views/PresentationView.scss b/src/client/views/presentationview/PresentationView.scss index 97ce80a02..07c3e69fd 100644 --- a/src/client/views/PresentationView.scss +++ b/src/client/views/presentationview/PresentationView.scss @@ -57,6 +57,11 @@ float: left; } +.presentation-interaction-selected { + background: #505050; + float: left; +} + .presentationView-name { font-size: 15px; display: inline-block; diff --git a/src/client/views/presentationview/PresentationView.tsx b/src/client/views/presentationview/PresentationView.tsx new file mode 100644 index 000000000..5a7d38e28 --- /dev/null +++ b/src/client/views/presentationview/PresentationView.tsx @@ -0,0 +1,203 @@ +import { observer } from "mobx-react"; +import React = require("react"); +import { observable, action, runInAction, reaction } from "mobx"; +import "./PresentationView.scss"; +import { DocumentManager } from "../../util/DocumentManager"; +import { Utils } from "../../../Utils"; +import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; +import { listSpec } from "../../../new_fields/Schema"; +import { Cast, NumCast, FieldValue, PromiseValue, StrCast, BoolCast } from "../../../new_fields/Types"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { List } from "../../../new_fields/List"; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import PresentationElement from "./PresentationElement"; + +export interface PresViewProps { + Document: Doc; +} + +interface PresListProps extends PresViewProps { + deleteDocument(index: number): void; + gotoDocument(index: number): void; + groupedMembers: [Doc[]]; + +} + + +@observer +/** + * Component that takes in a document prop and a boolean whether it's collapsed or not. + */ +class PresentationViewList extends React.Component<PresListProps> { + + + // onGroupClick = (document: Doc, index: number, buttonStatus: boolean[]) => { + // if (buttonStatus[5]) { + // buttonStatus[5] = false; + // if (index >= 1) { + // if (this.groupedMembers[index].length >= 0) { + // this.groupedMembers[index].forEach((doc: Doc) => this.groupedMembers[index - 1].slice(this.groupedMembers[index - 1].indexOf(doc), 1)); + // } + // } + // } else { + // buttonStatus[5] = true; + // console.log("reached!! ", buttonStatus[5]); + // if (index >= 1) { + // if (this.groupedMembers[index].length >= 0) { + // this.groupedMembers[index].forEach((doc: Doc) => this.groupedMembers[index - 1].push(doc)); + // } + // this.groupedMembers[index - 1].push(document); + // } + // } + // } + @action + initializeGroupArrays = (docList: Doc[]) => { + docList.forEach((doc: Doc, index: number) => { + if (this.props.groupedMembers.length < index + 1) { + this.props.groupedMembers[index] = new Array(); + } + }); + } + + // /** + // * Renders a single child document. It will just append a list element. + // * @param document The document to render. + // */ + // renderChild = (document: Doc, index: number) => { + // let title = document.title; + + // //to get currently selected presentation doc + // let selected = NumCast(this.props.Document.selectedDoc, 0); + + // let className = "presentationView-item"; + // if (selected === index) { + // //this doc is selected + // className += " presentationView-selected"; + // } + // let selectedButtons: boolean[] = new Array(6); + // let onEnter = (e: React.PointerEvent) => { document.libraryBrush = true; } + // let onLeave = (e: React.PointerEvent) => { document.libraryBrush = false; } + // return ( + // <div className={className} key={document[Id] + index} + // onPointerEnter={onEnter} onPointerLeave={onLeave} + // style={{ + // outlineColor: "maroon", + // outlineStyle: "dashed", + // outlineWidth: BoolCast(document.libraryBrush, false) || BoolCast(document.protoBrush, false) ? `1px` : "0px", + // }} + // onClick={e => { this.props.gotoDocument(index); e.stopPropagation(); }}> + // <strong className="presentationView-name"> + // {`${index + 1}. ${title}`} + // </strong> + // <button className="presentation-icon" onClick={e => { this.props.deleteDocument(index); e.stopPropagation(); }}>X</button> + // <br></br> + // <button className={selectedButtons[0] ? "presentation-interaction" : "presentation-interaction-selected"}>A</button> + // <button className={selectedButtons[1] ? "presentation-interaction" : "presentation-interaction-selected"}>B</button> + // <button className={selectedButtons[2] ? "presentation-interaction" : "presentation-interaction-selected"}>C</button> + // <button className={selectedButtons[3] ? "presentation-interaction" : "presentation-interaction-selected"}>D</button> + // <button className={selectedButtons[4] ? "presentation-interaction" : "presentation-interaction-selected"}>E</button> + // <button className={selectedButtons[5] ? "presentation-interaction" : "presentation-interaction-selected"} onClick={() => this.onGroupClick(document, index, selectedButtons)}>F</button> + + // </div> + // ); + + // } + + render() { + const children = DocListCast(this.props.Document.data); + this.initializeGroupArrays(children); + + return ( + <div className="presentationView-listCont"> + {children.map((doc: Doc, index: number) => <PresentationElement key={index} mainDocument={this.props.Document} document={doc} index={index} deleteDocument={this.props.deleteDocument} gotoDocument={this.props.gotoDocument} groupedMembers={this.props.groupedMembers} allListElements={children} />)} + </div> + ); + } +} + + +@observer +export class PresentationView extends React.Component<PresViewProps> { + public static Instance: PresentationView; + + @observable groupedMembers: [Doc[]] = [[]]; + + + //observable means render is re-called every time variable is changed + @observable + collapsed: boolean = false; + closePresentation = action(() => this.props.Document.width = 0); + next = () => { + const current = NumCast(this.props.Document.selectedDoc); + this.gotoDocument(current + 1); + + } + back = () => { + const current = NumCast(this.props.Document.selectedDoc); + this.gotoDocument(current - 1); + } + + @action + public RemoveDoc = (index: number) => { + const value = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + if (value) { + value.splice(index, 1); + } + } + + public gotoDocument = async (index: number) => { + const list = FieldValue(Cast(this.props.Document.data, listSpec(Doc))); + if (!list) { + return; + } + if (index < 0 || index >= list.length) { + return; + } + + this.props.Document.selectedDoc = index; + const doc = await list[index]; + DocumentManager.Instance.jumpToDocument(doc); + } + + //initilize class variables + constructor(props: PresViewProps) { + super(props); + PresentationView.Instance = this; + } + + /** + * Adds a document to the presentation view + **/ + @action + public PinDoc(doc: Doc) { + //add this new doc to props.Document + const data = Cast(this.props.Document.data, listSpec(Doc)); + if (data) { + data.push(doc); + } else { + this.props.Document.data = new List([doc]); + } + + this.props.Document.width = 300; + } + + render() { + let titleStr = StrCast(this.props.Document.title); + let width = NumCast(this.props.Document.width); + + //TODO: next and back should be icons + return ( + <div className="presentationView-cont" style={{ width: width, overflow: "hidden" }}> + <div className="presentationView-heading"> + <div className="presentationView-title">{titleStr}</div> + <button className='presentation-icon' onClick={this.closePresentation}>X</button> + </div> + <div className="presentation-buttons"> + <button className="presentation-button" onClick={this.back}>back</button> + <button className="presentation-button" onClick={this.next}>next</button> + </div> + <PresentationViewList Document={this.props.Document} deleteDocument={this.RemoveDoc} gotoDocument={this.gotoDocument} groupedMembers={this.groupedMembers} /> + </div> + ); + } +}
\ No newline at end of file |