diff options
-rw-r--r-- | package.json | 6 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 4 | ||||
-rw-r--r-- | src/client/util/CurrentUserUtils.ts | 5 | ||||
-rw-r--r-- | src/client/util/SharingManager.tsx | 10 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 18 | ||||
-rw-r--r-- | src/client/views/collections/CollectionDockingView.tsx | 7 | ||||
-rw-r--r-- | src/client/views/collections/CollectionMenu.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/CollectionTreeView.tsx | 2 | ||||
-rw-r--r-- | src/client/views/collections/CollectionView.tsx | 4 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/PropertiesView.scss | 27 | ||||
-rw-r--r-- | src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 259 | ||||
-rw-r--r-- | src/client/views/nodes/FontIconBox.scss | 56 | ||||
-rw-r--r-- | src/client/views/nodes/FontIconBox.tsx | 59 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.scss | 311 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.tsx | 355 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.tsx | 15 | ||||
-rw-r--r-- | src/server/MemoryDatabase.ts | 1 | ||||
-rw-r--r-- | src/server/websocket.ts | 6 | ||||
-rw-r--r-- | webpack.config.js | 62 |
19 files changed, 875 insertions, 336 deletions
diff --git a/package.json b/package.json index 420765e7c..7ae7cdc95 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "child_process": "empty" }, "scripts": { - "start-release": "cross-env RELEASE=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", - "start": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug --transpile-only -- src/server/index.ts", + "start-release": "cross-env RELEASE=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug -- src/server/index.ts", + "start": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug --transpile-only -- src/server/index.ts", "oldstart": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev --debug -- src/server/index.ts", "debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --transpile-only --inspect -- src/server/index.ts", "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 webpack --env production", @@ -260,4 +260,4 @@ "xoauth2": "^1.2.0", "xregexp": "^4.3.0" } -}
\ No newline at end of file +} diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 01cdb1eee..967ec08fd 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -157,6 +157,7 @@ export interface DocumentOptions { annotationOn?: Doc; removeDropProperties?: List<string>; // 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; + menuIcon?: boolean; // if the font icon box is in the menu linkRelationship?: string; // type of relatinoship a link represents ischecked?: ScriptField; // returns whether a font icon box is checked activeInkPen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts) @@ -306,9 +307,6 @@ export namespace Docs { layout: { view: FontIconBox, dataField: defaultDataKey }, options: { _width: 40, _height: 40, borderRounding: "100%" }, }], - [DocumentType.MENUICON, { - layout: { view: MenuIconBox, dataField: defaultDataKey }, - }], // [DocumentType.RECOMMENDATION, { // layout: { view: RecommendationsBox, dataField: defaultDataKey }, // options: { _width: 200, _height: 200 }, diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index b37c91c56..7b6868f73 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -48,6 +48,8 @@ export class CurrentUserUtils { @observable public static closedStack: any | undefined; @observable public static searchStack: any | undefined; + @observable public static selectedPanel: string = "none"; + // sets up the default User Templates - slideView, queryView, descriptionView static setupUserTemplateButtons(doc: Doc) { if (doc["template-button-query"] === undefined) { @@ -520,8 +522,9 @@ export class CurrentUserUtils { static setupMenuPanel(doc: Doc) { if (doc.menuStack === undefined) { const buttons = CurrentUserUtils.menuBtnDescriptions(); - const menuBtns = buttons.map(({ title, icon, click }) => Docs.Create.MenuIconDocument({ + const menuBtns = buttons.map(({ title, icon, click }) => Docs.Create.FontIconDocument({ icon, + menuIcon: true, title, _backgroundColor: "black", stayInCollection: true, diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 000b3e46c..7a0fe4140 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -142,7 +142,7 @@ export default class SharingManager extends React.Component<{}> { * @param group * @param permission */ - setInternalGroupSharing = (group: Doc, permission: string) => { + setInternalGroupSharing = (group: Doc, permission: string, targetDoc?: Doc) => { const members: string[] = JSON.parse(StrCast(group.members)); const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); @@ -179,6 +179,12 @@ export default class SharingManager extends React.Component<{}> { } } + shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, target: Doc) => { + const user = this.users.find(({ user: { email } }) => email === (shareWith === "Me" ? Doc.CurrentUserEmail : shareWith)); + if (user) this.setInternalSharing(user, permission, target); + else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, target); + } + /** * Removes the documents shared with a user through a group when the user is removed from the group. * @param group @@ -218,7 +224,7 @@ export default class SharingManager extends React.Component<{}> { } } - setInternalSharing = (recipient: ValidatedUser, permission: string) => { + setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => { const { user, notificationDoc } = recipient; const target = targetDoc || this.targetDoc!; const key = user.email.replace('.', '_'); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 54b57a887..18d5c53c6 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -237,7 +237,7 @@ export class MainView extends React.Component { const freeformOptions: DocumentOptions = { x: 0, y: 400, - _width: this._panelWidth * .7 - this.propertiesWidth(), + _width: this._panelWidth * .7 - this.propertiesWidth() * 0.7, _height: this._panelHeight, title: "Collection " + workspaceCount, }; @@ -370,7 +370,7 @@ export class MainView extends React.Component { @computed get dockingContent() { TraceMobx(); const mainContainer = this.mainContainer; - const width = this.flyoutWidth; + const width = this.flyoutWidth + this.propertiesWidth(); return <div className="mainContent-div" onDrop={this.onDrop} style={{ width: `calc(100% - ${width}px)` }}> {!mainContainer ? (null) : this.mainDocView} </div>; @@ -391,10 +391,16 @@ export class MainView extends React.Component { setupMoveUpEvents(this, e, action((e: PointerEvent) => { this.flyoutWidth = Math.max(e.clientX, 0); this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30; + if (this.flyoutWidth === 0) { + CurrentUserUtils.selectedPanel = "none"; + } return false; }), emptyFunction, action(() => { this.flyoutWidth = this.flyoutWidth < 15 ? 250 : 0; this.flyoutWidth && (this.sidebarButtonsDoc._columnWidth = this.flyoutWidth / 3 - 30); + if (this.flyoutWidth === 0) { + CurrentUserUtils.selectedPanel = "none"; + } })); } } @@ -467,7 +473,7 @@ export class MainView extends React.Component { onClick={undefined} ScreenToLocalTransform={this.mainContainerXf} ContentScaling={returnOne} - PanelWidth={() => 70} + PanelWidth={() => 60} PanelHeight={this.getContentsHeight} renderDepth={0} focus={emptyFunction} @@ -487,6 +493,7 @@ export class MainView extends React.Component { @action @undoBatch closeFlyout = () => { + CurrentUserUtils.selectedPanel = "none"; this.panelContent = "none"; this.flyoutWidth = 0; } @@ -496,10 +503,12 @@ export class MainView extends React.Component { @action @undoBatch selectMenu = (str: string) => { if (this.panelContent === str && this.flyoutWidth !== 0) { + CurrentUserUtils.selectedPanel = "none"; this.panelContent = "none"; this.flyoutWidth = 0; } else { this.panelContent = str; + CurrentUserUtils.selectedPanel = str; switch (this.panelContent) { case "Tools": this.sidebarContent.proto = CurrentUserUtils.toolsStack; break; case "Workspace": this.sidebarContent.proto = CurrentUserUtils.workspaceStack; break; @@ -508,7 +517,8 @@ export class MainView extends React.Component { case "Settings": this.sidebarContent.proto = SettingsManager.Instance.open(); break; case "Sharing": this.sidebarContent.proto = GroupManager.Instance.open(); break; } - if (str === "Settings" || str === "Sharing" || str === "Help") { + if (str === "Settings" || str === "Sharing" || str === "Help" || str === "Import") { + CurrentUserUtils.selectedPanel = "none"; this.panelContent = "none"; this.flyoutWidth = 0; } else { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index d685fac4e..7d6e67177 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -32,6 +32,8 @@ import { listSpec } from '../../../fields/Schema'; import { clamp } from 'lodash'; import { PresBox } from '../nodes/PresBox'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { InteractionUtils } from '../../util/InteractionUtils'; +import { InkTool } from '../../../fields/InkField'; const _global = (window /* browser */ || global /* node */) as any; @observer @@ -465,6 +467,11 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") { this._flush = true; } + if (e.nativeEvent.cancelBubble || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE) || InteractionUtils.IsType(e, InteractionUtils.PENTYPE) || (Doc.GetSelectedTool() === InkTool.Highlighter || Doc.GetSelectedTool() === InkTool.Pen)) { + return; + } else { + e.stopPropagation(); + } } updateDataField = async (json: string) => { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index fdd1b4e81..59e6ac7ff 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -332,11 +332,11 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking || this.isText ? (null) : this.viewModes} {this.props.type === CollectionViewType.Docking || this.isText ? (null) : this.templateChrome} - {/* <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}> + {Doc.UserDoc().noviceMode ? (null) : <div className="collectionViewBaseChrome-viewSpecs" title="filter documents to show" style={{ display: "grid" }}> <button className={"antimodeMenu-button"} onClick={this.toggleViewSpecs} > <FontAwesomeIcon icon="filter" size="lg" /> </button> - </div> */} + </div>} {this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? (null) : <button className={"antimodeMenu-button"} key="float" style={{ backgroundColor: !this.props.docView.layoutDoc.isAnnotating ? "121212" : undefined, borderRight: "1px solid gray" }} diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index e5c4b9187..bb5403930 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -332,7 +332,7 @@ class TreeView extends React.Component<TreeViewProps> { [...this.props.renderedIds, this.doc[Id]], this.props.libraryPath, this.props.onCheckedClick, this.props.onChildClick, this.props.ignoreFields)} </ul >; } else if (this.treeViewExpandedView === "fields") { - return <ul><div ref={this._dref} style={{ display: "inline-block" }} key={this.doc[Id] + this.doc.title}> + return <ul key={this.doc[Id] + this.doc.title}><div ref={this._dref} style={{ display: "inline-block" }} > {this.expandedField} </div></ul>; } else { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 62e8dc26a..c2b55d38e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -591,11 +591,11 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus Utils.CorsProxy(Cast(d.data, ImageField)!.url.href) : Cast(d.data, ImageField)!.url.href : ""))} - {/* {(!this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) : + {(Doc.UserDoc()?.noviceMode || !this.props.isSelected() && !this.props.Document.forceActive) || this.props.Document.hideFilterView ? (null) : <div className="collectionView-filterDragger" title="library View Dragger" onPointerDown={this.onPointerDown} style={{ right: this.facetWidth() - 1, top: this.props.Document._viewType === CollectionViewType.Docking ? "25%" : "55%" }} /> } - {this.facetWidth() < 10 ? (null) : this.filterView} */} + {Doc.UserDoc()?.noviceMode || this.facetWidth() < 10 ? (null) : this.filterView} </div>); } } diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index 74f32275a..6283a6669 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -241,7 +241,7 @@ .propertiesView-sharingTable-item-name { font-weight: bold; - width: 80px; + width: 95px; overflow-x: hidden; display: inline-block; text-overflow: ellipsis; @@ -259,8 +259,8 @@ border: none; background-color: inherit; width: 75px; - text-align: justify; // for Edge - text-align-last: end; + //text-align: justify; // for Edge + //text-align-last: end; &:hover { cursor: pointer; @@ -617,4 +617,25 @@ margin-top: 2px; } } + + .propertiesView-presSelected { + border-top: solid 1px darkgrey; + width: 100%; + padding-top: 5px; + font-family: Roboto; + font-weight: 500; + display: inline-flex; + + .propertiesView-selectedList { + border-left: solid 1px darkgrey; + margin-left: 10px; + padding-left: 5px; + + .selectedList-items { + font-size: 12; + font-weight: 300; + margin-top: 1; + } + } + } }
\ No newline at end of file diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 35c7fd425..ce8baf559 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -47,12 +47,9 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @computed get selectedDocumentView() { if (SelectionManager.SelectedDocuments().length) { return SelectionManager.SelectedDocuments()[0]; - } else if (PresBox.Instance) { - const presSlide = PresBox.Instance._selectedArray[0]; - const view = DocumentManager.Instance.getDocumentView(presSlide); - if (view) return view; - } else { return undefined; } + } else { console.log(undefined); return undefined; } } + @computed get isPres() { return this.selectedDoc?.type === DocumentType.PRES } @computed get selectedDoc() { return this.selectedDocumentView?.rootDoc; } @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; } @@ -64,6 +61,13 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @observable openLayout: boolean = true; @observable openAppearance: boolean = true; @observable openTransform: boolean = true; + //Pres Trails booleans: + @observable openAddSlide: boolean = true; + @observable openPresentationTools: boolean = true; + @observable openPresTransitions: boolean = true; + @observable openPresProgressivize: boolean = true; + @observable openSlideOptions: boolean = true; + @computed get isInk() { return this.selectedDoc?.type === DocumentType.INK; } @@ -162,7 +166,10 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { doc && Object.keys(doc).forEach(key => !(key in ids) && doc[key] !== ComputedField.undefined && (ids[key] = key)); const rows: JSX.Element[] = []; for (const key of Object.keys(ids).slice().sort()) { - if (key[0] === key[0].toUpperCase() || key[0] === "#" || key === "author" || key === "creationDate" || key.indexOf("lastModified") !== -1) { + if ((key[0] === key[0].toUpperCase() && key.substring(0, 3) !== "ACL") + || key[0] === "#" || key === "author" || + key === "creationDate" || key.indexOf("lastModified") !== -1) { + const contents = doc[key]; if (key[0] === "#") { rows.push(<div className="uneditable-field" key={key}> @@ -303,8 +310,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { sharingItem(name: string, effectiveAcl: symbol, permission?: string) { return <div className="propertiesView-sharingTable-item"> - <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "70px" : "80px" }}> {name} </div> - {name !== "Me" ? this.notifyIcon : null} + <div className="propertiesView-sharingTable-item-name" style={{ width: name !== "Me" ? "85px" : "80px" }}> {name} </div> + {/* {name !== "Me" ? this.notifyIcon : null} */} <div className="propertiesView-sharingTable-item-permission"> {effectiveAcl === AclAdmin && permission !== "Owner" ? this.getPermissionsSelect(name) : permission} {permission === "Owner" ? this.expansionIcon : null} @@ -749,110 +756,198 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const novice = Doc.UserDoc().noviceMode; - return <div className="propertiesView" style={{ width: this.props.width }} > - <div className="propertiesView-title" style={{ width: this.props.width }}> - Properties + + if (this.selectedDoc && !this.isPres) { + return <div className="propertiesView" style={{ width: this.props.width }} > + <div className="propertiesView-title" style={{ width: this.props.width }}> + Properties <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> - <FontAwesomeIcon icon="times" color="black" size="sm" /> + <FontAwesomeIcon icon="times" color="black" size="sm" /> + </div> </div> - </div> - <div className="propertiesView-name"> - {this.editableTitle} - </div> - <div className="propertiesView-settings"> - <div className="propertiesView-settings-title" - onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })} - style={{ backgroundColor: this.openActions ? "black" : "" }}> - Actions + <div className="propertiesView-name"> + {this.editableTitle} + </div> + <div className="propertiesView-settings"> + <div className="propertiesView-settings-title" + onPointerDown={() => runInAction(() => { this.openActions = !this.openActions; })} + style={{ backgroundColor: this.openActions ? "black" : "" }}> + Actions <div className="propertiesView-settings-title-icon"> - <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" /> + <FontAwesomeIcon icon={this.openActions ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openActions ? <div className="propertiesView-settings-content"> + <PropertiesButtons /> + </div> : null} </div> - {this.openActions ? <div className="propertiesView-settings-content"> - <PropertiesButtons /> - </div> : null} - </div> - <div className="propertiesView-sharing"> - <div className="propertiesView-sharing-title" - onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} - style={{ backgroundColor: this.openSharing ? "black" : "" }}> - Sharing {"&"} Permissions + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} + style={{ backgroundColor: this.openSharing ? "black" : "" }}> + Sharing {"&"} Permissions <div className="propertiesView-sharing-title-icon"> - <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openSharing ? <div className="propertiesView-sharing-content"> + {this.sharingTable} + </div> : null} </div> - {this.openSharing ? <div className="propertiesView-sharing-content"> - {this.sharingTable} - </div> : null} - </div> - {this.isInk ? <div className="propertiesView-appearance"> - <div className="propertiesView-appearance-title" - onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })} - style={{ backgroundColor: this.openAppearance ? "black" : "" }}> - Appearance + {this.isInk ? <div className="propertiesView-appearance"> + <div className="propertiesView-appearance-title" + onPointerDown={() => runInAction(() => { this.openAppearance = !this.openAppearance; })} + style={{ backgroundColor: this.openAppearance ? "black" : "" }}> + Appearance <div className="propertiesView-appearance-title-icon"> - <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" /> + <FontAwesomeIcon icon={this.openAppearance ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> - </div> - {this.openAppearance ? <div className="propertiesView-appearance-content"> - {this.appearanceEditor} + {this.openAppearance ? <div className="propertiesView-appearance-content"> + {this.appearanceEditor} + </div> : null} </div> : null} - </div> : null} - {this.isInk ? <div className="propertiesView-transform"> - <div className="propertiesView-transform-title" - onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })} - style={{ backgroundColor: this.openTransform ? "black" : "" }}> - Transform + {this.isInk ? <div className="propertiesView-transform"> + <div className="propertiesView-transform-title" + onPointerDown={() => runInAction(() => { this.openTransform = !this.openTransform; })} + style={{ backgroundColor: this.openTransform ? "black" : "" }}> + Transform <div className="propertiesView-transform-title-icon"> - <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" /> + <FontAwesomeIcon icon={this.openTransform ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> - </div> - {this.openTransform ? <div className="propertiesView-transform-content"> - {this.transformEditor} + {this.openTransform ? <div className="propertiesView-transform-content"> + {this.transformEditor} + </div> : null} </div> : null} - </div> : null} - <div className="propertiesView-fields"> - <div className="propertiesView-fields-title" - onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })} - style={{ backgroundColor: this.openFields ? "black" : "" }}> - <div className="propertiesView-fields-title-name"> - Fields {"&"} Tags + <div className="propertiesView-fields"> + <div className="propertiesView-fields-title" + onPointerDown={() => runInAction(() => { this.openFields = !this.openFields; })} + style={{ backgroundColor: this.openFields ? "black" : "" }}> + <div className="propertiesView-fields-title-name"> + Fields {"&"} Tags <div className="propertiesView-fields-title-icon"> - <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" /> + <FontAwesomeIcon icon={this.openFields ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> </div> - </div> - {!novice && this.openFields ? <div className="propertiesView-fields-checkbox"> - {this.fieldsCheckbox} - <div className="propertiesView-fields-checkbox-text">Layout</div> - </div> : null} - {this.openFields ? - <div className="propertiesView-fields-content"> - {novice ? this.noviceFields : this.expandedField} + {!novice && this.openFields ? <div className="propertiesView-fields-checkbox"> + {this.fieldsCheckbox} + <div className="propertiesView-fields-checkbox-text">Layout</div> </div> : null} - </div> - <div className="propertiesView-layout"> - <div className="propertiesView-layout-title" - onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })} - style={{ backgroundColor: this.openLayout ? "black" : "" }}> - Layout + {this.openFields ? + <div className="propertiesView-fields-content"> + {novice ? this.noviceFields : this.expandedField} + </div> : null} + </div> + <div className="propertiesView-layout"> + <div className="propertiesView-layout-title" + onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })} + style={{ backgroundColor: this.openLayout ? "black" : "" }}> + Layout <div className="propertiesView-layout-title-icon" - onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}> - <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" /> + onPointerDown={() => runInAction(() => { this.openLayout = !this.openLayout; })}> + <FontAwesomeIcon icon={this.openLayout ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> </div> + {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null} </div> - {this.openLayout ? <div className="propertiesView-layout-content">{this.layoutPreview}</div> : null} - </div> - </div>; + </div>; + } + + if (this.isPres) { + return <div className="propertiesView" style={{ width: this.props.width }} > + <div className="propertiesView-title" style={{ width: this.props.width }}> + Presentation Toolbar + <div className="propertiesView-title-icon" onPointerDown={this.props.onDown}> + <FontAwesomeIcon icon="times" color="black" size="sm" /> + </div> + </div> + <div className="propertiesView-name"> + {this.editableTitle} + <div className="propertiesView-presSelected"> + {PresBox.Instance._selectedArray.length} selected + <div className="propertiesView-selectedList"> + {PresBox.Instance.listOfSelected} + </div> + </div> + </div> + <div className="propertiesView-settings"> + <div className="propertiesView-settings-title" + onPointerDown={() => runInAction(() => { this.openAddSlide = !this.openAddSlide; })} + style={{ backgroundColor: this.openAddSlide ? "black" : "" }}> + <FontAwesomeIcon icon={"plus"} /> Add new slide + <div className="propertiesView-settings-title-icon"> + <FontAwesomeIcon icon={this.openAddSlide ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openAddSlide ? <div className="propertiesView-settings-content"> + {PresBox.Instance.newDocumentDropdown} + </div> : null} + </div> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openPresTransitions = !this.openPresTransitions; })} + style={{ backgroundColor: this.openPresTransitions ? "black" : "" }}> + <FontAwesomeIcon icon={"rocket"} /> Transitions + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openPresTransitions ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openPresTransitions ? <div className="propertiesView-sharing-content"> + {PresBox.Instance.transitionDropdown} + </div> : null} + </div> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openPresProgressivize = !this.openPresProgressivize; })} + style={{ backgroundColor: this.openPresProgressivize ? "black" : "" }}> + <FontAwesomeIcon icon={"tasks"} /> Progressivize + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openPresProgressivize ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openPresProgressivize ? <div className="propertiesView-sharing-content"> + {PresBox.Instance.progressivizeDropdown} + </div> : null} + </div> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openSlideOptions = !this.openSlideOptions; })} + style={{ backgroundColor: this.openSlideOptions ? "black" : "" }}> + <FontAwesomeIcon icon={"cog"} /> Slide options + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openSlideOptions ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openSlideOptions ? <div className="propertiesView-sharing-content"> + {PresBox.Instance.optionsDropdown} + </div> : null} + </div> + <div className="propertiesView-sharing"> + <div className="propertiesView-sharing-title" + onPointerDown={() => runInAction(() => { this.openSharing = !this.openSharing; })} + style={{ backgroundColor: this.openSharing ? "black" : "" }}> + Sharing {"&"} Permissions + <div className="propertiesView-sharing-title-icon"> + <FontAwesomeIcon icon={this.openSharing ? "caret-down" : "caret-right"} size="lg" color="white" /> + </div> + </div> + {this.openSharing ? <div className="propertiesView-sharing-content"> + {this.sharingTable} + </div> : null} + </div> + </div>; + } } }
\ No newline at end of file diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss index 69c835318..13af511a6 100644 --- a/src/client/views/nodes/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox.scss @@ -10,9 +10,9 @@ .fontIconBox-label { background: gray; - color:white; + color: white; border-radius: 8px; - width:100%; + width: 100%; position: absolute; text-align: center; font-size: 8px; @@ -26,4 +26,56 @@ width: 95% !important; height: 95%; } +} + +.menuButton { + //padding: 7px; + padding-left: 5px; + width: 100%; + width: 60px; + height: 70px; + padding-top: 3px; + padding-bottom: 3px; + + .menuButton-wrap { + width: 45px; + /* padding: 5px; */ + touch-action: none; + background: black; + transform-origin: top left; + /* margin-bottom: 5px; */ + margin-top: 5px; + margin-right: 25px; + border-radius: 8px; + + &:hover { + background: rgb(61, 61, 61); + cursor: pointer; + } + } + + .menuButton-label { + color: white; + margin-right: 4px; + border-radius: 8px; + width: 42px; + position: relative; + text-align: center; + font-size: 7px; + margin-top: 1px; + letter-spacing: normal; + padding: 3px; + background-color: inherit; + } + + .menuButton-icon { + width: auto; + height: 32px; + padding: 5px; + } + + svg { + width: 95% !important; + height: 95%; + } }
\ No newline at end of file diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index 2611d2ca7..720d6a15d 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -12,8 +12,10 @@ import { Doc } from '../../../fields/Doc'; import { ContextMenu } from '../ContextMenu'; import { ScriptField } from '../../../fields/ScriptField'; import { Tooltip } from '@material-ui/core'; +import { createUnionOrIntersectionTypeNode } from 'typescript'; +import { CurrentUserUtils } from '../../util/CurrentUserUtils'; const FontIconSchema = createSchema({ - icon: "string" + icon: "string", }); type FontIconDocument = makeInterface<[typeof FontIconSchema]>; @@ -59,20 +61,45 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>( } render() { - const referenceDoc = (this.layoutDoc.dragFactory instanceof Doc ? this.layoutDoc.dragFactory : this.layoutDoc); - const refLayout = Doc.Layout(referenceDoc); - const button = <button className="fontIconBox-outerDiv" ref={this._ref} onContextMenu={this.specificContextMenu} - style={{ - padding: Cast(this.layoutDoc._xPadding, "number", null), - background: StrCast(refLayout._backgroundColor, StrCast(refLayout.backgroundColor)), - boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined - }}> - <FontAwesomeIcon className="fontIconBox-icon" icon={StrCast(this.dataDoc.icon, "user") as any} color={StrCast(this.layoutDoc.color, this._foregroundColor)} size="sm" /> - {!this.rootDoc.title ? (null) : <div className="fontIconBox-label" style={{ width: this.rootDoc.label ? "max-content" : undefined }}> {StrCast(this.rootDoc.label, StrCast(this.rootDoc.title).substring(0, 6))} </div>} - </button>; - return !this.layoutDoc.toolTip ? button : - <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}> - {button} - </Tooltip>; + + //style={{ backgroundColor: this.props.backgroundColor?.(this.props.Document) }}> + + if (this.layoutDoc.menuIcon) { + + let backgroundColor = "black"; + if (this.dataDoc.title === "Sharing" || this.dataDoc.title === "Help" || this.dataDoc.title === "Settings" || this.dataDoc.title === "Import") { + backgroundColor = "black"; + } else { + backgroundColor = CurrentUserUtils.selectedPanel === this.dataDoc.title ? "lightgrey" : "black"; + } + + const color = backgroundColor === "lightgrey" ? "black" : "white"; + const menuBTN = <div className="menuButton" style={{ backgroundColor: backgroundColor }}> + + <div className="menuButton-wrap" style={{ backgroundColor: backgroundColor }}> + <FontAwesomeIcon className="menuButton-icon" icon={StrCast(this.dataDoc.icon, "user") as any} color={color} size="lg" /> + <div className="menuButton-label" style={{ color: color }}> {this.dataDoc.title} </div> + </div> + </div>; + + return menuBTN; + } else { + const referenceDoc = (this.layoutDoc.dragFactory instanceof Doc ? this.layoutDoc.dragFactory : this.layoutDoc); + const refLayout = Doc.Layout(referenceDoc); + const button = <button className="fontIconBox-outerDiv" ref={this._ref} onContextMenu={this.specificContextMenu} + style={{ + padding: Cast(this.layoutDoc._xPadding, "number", null), + background: StrCast(refLayout._backgroundColor, StrCast(refLayout.backgroundColor)), + boxShadow: this.layoutDoc.ischecked ? `4px 4px 12px black` : undefined + }}> + <FontAwesomeIcon className="fontIconBox-icon" icon={StrCast(this.dataDoc.icon, "user") as any} color={StrCast(this.layoutDoc.color, this._foregroundColor)} size="sm" /> + {!this.rootDoc.title ? (null) : <div className="fontIconBox-label" style={{ width: this.rootDoc.label ? "max-content" : undefined }}> {StrCast(this.rootDoc.label, StrCast(this.rootDoc.title).substring(0, 6))} </div>} + </button>; + return !this.layoutDoc.toolTip ? button : + <Tooltip title={<div className="dash-tooltip">{StrCast(this.layoutDoc.toolTip)}</div>}> + {button} + </Tooltip>; + } + } }
\ No newline at end of file diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index b06503472..e5878708f 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -24,6 +24,22 @@ display: none; } + .presBox-toolbar-dropdown { + border-radius: 5px; + background-color: white; + transform: translate(8px, -5px); + box-shadow: 1px 1px 4px 4px rgba(0, 0, 0, 0.25); + z-index: 1000; + width: 315; + height: max-content; + justify-self: center; + letter-spacing: normal; + height: max-content; + font-weight: 500; + position: relative; + font-size: 13; + } + .presBox-toolbar.active { position: relative; display: inline-flex; @@ -110,12 +126,12 @@ .presBox-ribbon { position: relative; - display: none; + display: inline; font-family: Roboto; - background-color: white; + /* background-color: white; */ color: black; width: 100%; - height: 0; + height: max-content; z-index: 100; transition: 0.7s; @@ -123,40 +139,117 @@ display: inline-flex; } - .toolbar-slider { - position: relative; - align-self: center; - justify-self: left; - -webkit-appearance: none; - transform: rotateY(180deg); - background-color: #40B3D8; - margin-top: 5px; - width: 100%; - max-width: 120px; - height: 2.5px; - left: 0px; - } - - .toolbar-slider:focus { - outline: none; + .presBox-reactiveGrid { + display: grid; + justify-content: flex-start; + align-items: center; + grid-template-columns: repeat(auto-fit, 50px); } - .effectDirection { - justify-self: center; - align-self: center; - align-items: center; + .ribbon-property { + font-size: 11; + font-weight: 200; + height: 20; + background-color: #ececec; + color: black; + border: solid 1px black; + display: flex; + margin-left: 5px; + margin-top: 5px; + margin-bottom: 5px; + /* border-radius: 5px; */ + margin-right: 5px; + width: max-content; justify-content: center; - grid-template-columns: 13px 13px 13px; - display: grid; + align-items: center; + padding-right: 10px; + padding-left: 10px; } - .toolbar-slider::-webkit-slider-thumb { - -webkit-appearance: none; - background-color: #40B3D8; - border: 1px white solid; - border-radius: 100%; - width: 9px; - height: 9px; + // .toolbar-slider { + // position: relative; + // align-self: center; + // justify-self: left; + // -webkit-appearance: none; + // background-color: #5b9ddd; + // overflow: hidden; + // margin-top: 5px; + // width: 100%; + // max-width: 200px; + + // } + + // .toolbar-slider:focus { + // outline: none; + // } + + // .effectDirection { + // justify-self: center; + // align-self: center; + // align-items: center; + // justify-content: center; + // grid-template-columns: 13px 13px 13px; + // display: grid; + // } + + // .toolbar-slider::-webkit-slider-thumb { + // -webkit-appearance: none; + // background-color: #5b9ddd; + // box-shadow: -100 vw 0 0 100vw pink; + // width: 12px; + // height: 12px; + // } + + // .toolbar-slider::-webkit-slider-runnable-track { + // position: relative; + // align-self: center; + // justify-self: left; + // -webkit-appearance: none; + // background-color: #5b9ddd; + // margin-top: 5px; + // border: solid 1px black; + // border-radius: 10px; + // height: 5px; + // left: 0px; + // } + .presBox-subheading { + font-size: 11; + font-weight: 400; + margin-top: 10px; + } + + @media screen and (-webkit-min-device-pixel-ratio:0) { + .toolbar-slider { + margin-top: 5px; + position: relative; + align-self: center; + justify-self: left; + overflow: hidden; + width: 100%; + height: 10px; + border-radius: 10px; + -webkit-appearance: none; + background-color: #ececec; + } + + .toolbar-slider:focus { + outline: none; + } + + .toolbar-slider::-webkit-slider-runnable-track { + height: 10px; + -webkit-appearance: none; + margin-top: -1px; + } + + .toolbar-slider::-webkit-slider-thumb { + width: 10px; + -webkit-appearance: none; + height: 10px; + cursor: ew-resize; + background: #5b9ddd; + box-shadow: -100vw 0 0 100vw #aedef8; + } } .slider-headers { @@ -165,12 +258,11 @@ justify-content: space-between; width: 100%; height: max-content; - max-width: 120px; grid-template-columns: auto auto auto; grid-template-rows: max-content; font-weight: 100; - /* margin-top: 5px; */ - font-size: 8px; + margin-top: 3px; + font-size: 10px; } .slider-value { @@ -199,14 +291,17 @@ .ribbon-textInput { border-radius: 2px; - height: 20px; - font-size: 10; + height: 30px; + font-size: 11.5; font-weight: 100; align-self: center; - justify-self: center; + justify-self: left; + margin-top: 5px; padding-left: 10px; + background-color: rgb(222, 222, 222); border: solid 1px black; min-width: 80px; + max-width: 200px; width: 100%; } @@ -214,6 +309,7 @@ border: black solid 1px; width: 60px; height: 20px; + margin-top: 5px; display: grid; grid-template-columns: auto 27px auto; position: relative; @@ -253,27 +349,28 @@ align-self: flex-start; justify-self: center; display: grid; + margin-top: 10px; grid-template-rows: auto auto; - padding-left: 10px; - padding-right: 10px; + /* padding-left: 10px; */ + /* padding-right: 10px; */ letter-spacing: normal; min-width: max-content; width: 100%; font-size: 13; - font-weight: 600; + font-weight: 500; position: relative; .ribbon-final-button { position: relative; - font-size: 10; + font-size: 11.5; font-weight: normal; letter-spacing: normal; display: flex; justify-content: center; align-items: center; margin-bottom: 5px; - height: 25px; + height: 30px; color: white; width: 100%; max-width: 120; @@ -285,14 +382,14 @@ .ribbon-final-button-hidden { position: relative; - font-size: 10; + font-size: 11.5; font-weight: normal; letter-spacing: normal; display: flex; justify-content: center; align-items: center; margin-bottom: 5px; - height: 25px; + height: 30px; color: lightgrey; width: 100%; max-width: 120; @@ -317,9 +414,10 @@ } .ribbon-button { - font-size: 10; + font-size: 11; font-weight: 200; - height: 20; + height: 30; + background-color: #dedede; border: solid 1px black; display: flex; margin-top: 5px; @@ -334,7 +432,7 @@ } .ribbon-button.active { - background-color: #5B9FDD; + background-color: #aedef8; } .ribbon-button:hover { @@ -351,22 +449,27 @@ display: grid; grid-template-rows: max-content auto; justify-self: center; - padding-left: 10px; + margin-top: 10px; + /* padding-left: 10px; */ padding-right: 10px; letter-spacing: normal; width: 100%; - font-weight: 600; + /* max-width: 100%; */ + height: max-content; + font-weight: 500; position: relative; font-size: 13; - border-right: solid 2px darkgrey; + padding-bottom: 10px; + border-bottom: solid 1px darkgrey; .presBox-dropdown:hover { border: solid 1px #378AD8; + border-bottom-left-radius: 0px; .presBox-dropdownOption { - font-size: 10; + font-size: 11; display: block; - padding-left: 5px; + padding-left: 10px; padding-right: 5px; padding-top: 3; padding-bottom: 3; @@ -384,7 +487,7 @@ .presBox-dropdownOptions { position: absolute; - top: 19px; + top: 29px; left: -1px; z-index: 200; width: 85%; @@ -406,8 +509,10 @@ grid-template-columns: auto 20%; position: relative; border: solid 1px black; + background-color: #dedede; + border-radius: 5px; font-size: 10; - height: 20; + height: 30; padding-left: 5px; align-items: center; margin-top: 5px; @@ -415,7 +520,7 @@ font-weight: 200; width: 100%; min-width: max-content; - max-width: 120; + max-width: 200px; overflow: visible; .presBox-dropdownOptions { @@ -522,52 +627,92 @@ display: block; } -.layout-container { - overflow-x: scroll; +.open-layout { + position: relative; display: flex; + align-items: center; + justify-content: center; + transform: translate(0px, -1px); + background-color: #dedede; + width: 40px; + height: 15px; + align-self: center; + justify-self: center; + border: solid 1px black; + border-top: 0px; + border-bottom-right-radius: 7px; + border-bottom-left-radius: 7px; +} + +.layout-container { + padding: 5px; + display: grid; + background-color: #dedede; + grid-template-columns: repeat(auto-fit, minmax(90px, 100px)); width: 100%; - /* max-width: 200px; */ + border: solid 1px black; min-width: 100px; - height: 100%; - // border: solid 1px; - /* display: block; */ - align-self: center; + overflow: hidden; .layout:hover { border: solid 2px #5c9edd; } .layout { + align-self: center; + justify-self: center; + margin-top: 5; + margin-bottom: 5; position: relative; - top: 10%; - height: 80%; - margin-right: 10; + height: 55px; min-width: 90px; width: 90px; - border: solid black 1px; + background-color: white; + border: solid darkgrey 1px; display: grid; - grid-template-rows: 20px 30px; + grid-template-rows: auto; align-items: center; text-align: center; - .header { - font-size: 10; - font-weight: 600; - width: 70%; - height: max-content; - align-self: center; - justify-self: center; - border: solid 0.8px black; + .title { + position: relative; + align-self: end; + padding-left: 3px; + margin-left: 3px; + margin-right: 3px; + height: 13; + font-size: 12; + display: flex; + background-color: #f1efec; } - .subheader { - font-size: 8; + .subtitle { + align-self: flex-start; + position: relative; + padding-left: 3px; + margin-left: 3px; + margin-right: 3px; font-weight: 400; - width: 70%; - height: 90%; - align-self: center; - justify-self: center; - border: solid 0.4px black; + height: 13; + font-size: 9; + display: flex; + background-color: #f1efec; + } + + .content { + position: relative; + font-weight: 200; + align-self: flex-start; + padding-left: 3px; + margin-left: 3px; + margin-right: 3px; + height: 13; + font-size: 10; + display: flex; + background-color: #f1efec; + height: 33; + text-align: left; + font-size: 8px; } } } diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 97f223c02..618161e97 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, DocCastAsync, WidthSym } from "../../../fields/Doc"; import { InkTool } from "../../../fields/InkField"; @@ -63,6 +63,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.props.Document.presentationFieldKey = this.fieldKey; // provide info to the presElement script so that it can look up rendering information about the presBox } + + componentDidMount() { this.rootDoc.presBox = this.rootDoc; this.rootDoc._forceRenderEngine = "timeline"; @@ -275,13 +277,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> console.log(collectionDocView); collectionDocView.props.addDocTab(srcContext, "inPlace"); } - } else if (srcContext) { - console.log("Case 2: srcContext - not open and collection containing this document exists, so open collection that contains it and then await zooming in on document"); - this.props.addDocTab(srcContext, "onRight"); - } else if (!srcContext) { - console.log("Case 3: !srcContext - no collection containing this document, therefore open document itself on right"); - this.props.addDocTab(targetDoc, "onRight"); } + // else if (srcContext) { + // console.log("Case 2: srcContext - not open and collection containing this document exists, so open collection that contains it and then await zooming in on document"); + // this.props.addDocTab(srcContext, "onRight"); + // } else if (!srcContext) { + // console.log("Case 3: !srcContext - no collection containing this document, therefore open document itself on right"); + // this.props.addDocTab(targetDoc, "onRight"); + // } this.updateCurrentPresentation(); const docToJump = curDoc; const willZoom = false; @@ -484,7 +487,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @computed get listOfSelected() { const list = this._selectedArray.map((doc: Doc, index: any) => { const activeItem = Cast(doc, Doc, null); - const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const targetDoc = Cast(activeItem.presentationTargetDoc!, Doc, null); return ( <div className="selectedList-items">{index + 1}. {targetDoc.title}</div> ); @@ -497,32 +500,28 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> selectElement = (doc: Doc) => { // this._selectedArray = []; this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex)); - const view = DocumentManager.Instance.getDocumentView(doc); - view && SelectionManager.SelectDoc(view, false); // this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); // console.log(this._selectedArray); } //Command click @action - multiSelect = (doc: Doc, ref: HTMLElement) => { + multiSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => { this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); this._eleArray.push(ref); - const view = DocumentManager.Instance.getDocumentView(doc); - view && SelectionManager.SelectDoc(view, true); + this._dragArray.push(drag); } //Shift click @action - shiftSelect = (doc: Doc, ref: HTMLElement) => { + shiftSelect = (doc: Doc, ref: HTMLElement, drag: HTMLElement) => { this._selectedArray = []; const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); if (activeItem) { for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) { this._selectedArray.push(this.childDocs[i]); this._eleArray.push(ref); - const view = DocumentManager.Instance.getDocumentView(doc); - view && SelectionManager.SelectDoc(view, true); + this._dragArray.push(drag); } } } @@ -788,25 +787,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className={`presBox-dropdownOption ${activeItem.presMovement === 'Switch' ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('switch')}>Switch</div> </div> </div> + <div className="ribbon-doubleButton" style={{ display: activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "inline-flex" : "none" }}> + <div className="presBox-subheading" >Transition Speed</div> + <div className="ribbon-property"> {transitionSpeed} s </div> + </div> <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} /> <div className={`slider-headers ${activeItem.presMovement === 'Pan' || activeItem.presMovement === 'Zoom' ? "" : "none"}`}> - <div className={`slider-value ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "none"}`} style={{ left: transitionThumbLocation + '%' }}>{transitionSpeed}s</div> - <div className="slider-text">Slow</div> - <div className="slider-text"></div> <div className="slider-text">Fast</div> + <div className="slider-text">Medium</div> + <div className="slider-text">Slow</div> </div> </div> <div className="ribbon-box"> - Visibility + Visibility {"&"} Duration <div className="ribbon-doubleButton"> - <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-button ${activeItem.presHideTillShownButton ? "active" : ""}`} onClick={() => activeItem.presHideTillShownButton = !activeItem.presHideTillShownButton}>HB</div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-button ${activeItem.presHideAfterButton ? "active" : ""}`} onClick={() => activeItem.presHideAfterButton = !activeItem.presHideAfterButton}>HA</div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Hide before presented"}</div></>}><div className={`ribbon-button ${activeItem.presHideTillShownButton ? "active" : ""}`} onClick={() => activeItem.presHideTillShownButton = !activeItem.presHideTillShownButton}>Hide before</div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Hide after presented"}</div></>}><div className={`ribbon-button ${activeItem.presHideAfterButton ? "active" : ""}`} onClick={() => activeItem.presHideAfterButton = !activeItem.presHideAfterButton}>Hide after</div></Tooltip> + </div> + <div className="ribbon-doubleButton" > + <div className="presBox-subheading">Slide Duration</div> + <div className="ribbon-property"> {duration} s </div> </div> <input type="range" step="0.1" min="0.1" max="10" value={duration} style={{ transform: 'rotate(0deg)' }} className={"toolbar-slider"} id="duration-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setDurationTime(e.target.value); }} /> <div className={"slider-headers"}> - <div className={"slider-value"} style={{ left: durationThumbLocation + '%' }}>{duration}s</div> <div className="slider-text">Short</div> - <div className="slider-text"></div> + <div className="slider-text">Medium</div> <div className="slider-text">Long</div> </div> </div> @@ -826,19 +831,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()} onClick={() => targetDoc.presEffect = 'Roll'}>Roll</div> </div> </div> - <div className="effectDirection" style={{ display: effect === 'None' ? "none" : "grid" }}> - <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "right" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'right'}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === "top" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'top'}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === "bottom" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'bottom'}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip> - <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection ? "solid 2px black" : "solid 2px #5a9edd", borderRadius: "100%" }} onClick={() => targetDoc.presEffectDirection = false}></div></Tooltip> - </div> - </div> - <div className="ribbon-final-box"> - {this._selectedArray.length} selected - <div className="selectedList"> - {this.listOfSelected} + <div className="presBox-subheading" style={{ display: effect === 'None' ? "none" : "block" }}>Effect direction</div> + <div className="presBox-reactiveGrid" style={{ display: effect === 'None' ? "none" : "grid", width: 40 }}> + <div className="effectDirection" style={{ display: "grid", width: 40 }}> + <Tooltip title={<><div className="dash-tooltip">{"Enter from left"}</div></>}><div style={{ gridColumn: 1, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "left" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'left'}><FontAwesomeIcon icon={"angle-right"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from right"}</div></>}><div style={{ gridColumn: 3, gridRow: 2, justifySelf: 'center', color: targetDoc.presEffectDirection === "right" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'right'}><FontAwesomeIcon icon={"angle-left"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from top"}</div></>}><div style={{ gridColumn: 2, gridRow: 1, justifySelf: 'center', color: targetDoc.presEffectDirection === "top" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'top'}><FontAwesomeIcon icon={"angle-down"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from bottom"}</div></>}><div style={{ gridColumn: 2, gridRow: 3, justifySelf: 'center', color: targetDoc.presEffectDirection === "bottom" ? "#5a9edd" : "black" }} onClick={() => targetDoc.presEffectDirection = 'bottom'}><FontAwesomeIcon icon={"angle-up"} /></div></Tooltip> + <Tooltip title={<><div className="dash-tooltip">{"Enter from center"}</div></>}><div style={{ gridColumn: 2, gridRow: 2, width: 10, height: 10, alignSelf: 'center', justifySelf: 'center', border: targetDoc.presEffectDirection ? "solid 2px black" : "solid 2px #5a9edd", borderRadius: "100%" }} onClick={() => targetDoc.presEffectDirection = false}></div></Tooltip> + </div> + <div className="ribbon-property"> + {this.effectDirection} + </div> </div> + </div> <div className="ribbon-final-box"> <div className={this._selectedArray.length === 0 ? "ribbon-final-button" : "ribbon-final-button-hidden"} onClick={() => this.applyTo(this._selectedArray)}> @@ -853,6 +859,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } + @computed get effectDirection(): string { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + let effect = ''; + switch (targetDoc.presEffectDirection) { + case 'left': effect = "Enter from left"; break; + case 'right': effect = "Enter from right"; break; + case 'top': effect = "Enter from top"; break; + case 'bottom': effect = "Enter from bottom"; break; + default: effect = "Enter from center"; break; + } + return effect; + } + applyTo = (array: Doc[]) => { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); @@ -870,61 +890,123 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> public inputRef = React.createRef<HTMLInputElement>(); - createNewSlide = (title: string, type: string) => { - let doc = null; - if (type === "text") { - doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 400, title: title }); - const data = Cast(this.rootDoc.data, listSpec(Doc)); - if (data) data.push(doc); - } else { - doc = Docs.Create.FreeformDocument([], { _nativeWidth: 400, _width: 400, title: title }); - const data = Cast(this.rootDoc.data, listSpec(Doc)); - if (data) data.push(doc); + + @computed get optionsDropdown() { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + if (activeItem && targetDoc) { + return ( + <div> + <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className="ribbon-box"> + {this.stringType} options + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.VID ? "inline-flex" : "none" }}> + <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeChild}>Child documents</div> + <div className="ribbon-button" style={{ display: activeItem.presProgressivize ? "flex" : "none", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Edit</div> + </div> + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}> + <div className="ribbon-button" style={{ backgroundColor: activeItem.zoomProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeZoom}>Internal zoom</div> + <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Viewfinder</div> + <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div> + </div> + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.RTF ? "inline-flex" : "none" }}> + <div className="ribbon-button" onClick={this.progressivizeText}>Text progressivize</div> + <div className="ribbon-button" style={{ display: activeItem.textProgressivize ? "flex" : "none", backgroundColor: targetDoc.editTextProgressivize ? "#aedef8" : "" }} onClick={this.editTextProgressivize}>Edit</div> + </div> + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.PDF ? "inline-flex" : "none" }}> + <div className="ribbon-button" style={{ backgroundColor: activeItem.scrollProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeScroll}>Scroll progressivize</div> + <div className="ribbon-button" style={{ display: activeItem.scrollProgressivize ? "flex" : "none", backgroundColor: targetDoc.editScrollProgressivize ? "#aedef8" : "" }} onClick={this.editScrollProgressivize}>Edit</div> + </div> + </div> + </div> + </div > + ); } } + @computed get newDocumentToolbarDropdown() { + return ( + <div> + <div className={'presBox-toolbar-dropdown'} style={{ display: this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "inline-flex" : "none" }} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className="layout-container" style={{ height: this.openLayouts ? 'max-content' : '75px' }}> + <div className="layout" style={{ border: this.layout === 'blank' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'blank' })} /> + <div className="layout" style={{ border: this.layout === 'title' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'title' })}> + <div className="title">Title</div> + <div className="subtitle">Subtitle</div> + </div> + <div className="layout" style={{ border: this.layout === 'header' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'header' })}> + <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div> + </div> + <div className="layout" style={{ border: this.layout === 'content' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'content' })}> + <div className="title" style={{ alignSelf: 'center' }}>Title</div> + <div className="content">Text goes here</div> + </div> + <div className="layout" style={{ border: this.layout === 'twoColumns' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'twoColumns' })}> + <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div> + <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div> + <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div> + </div> + </div> + <div className="open-layout" onClick={() => runInAction(() => { this.openLayouts = !this.openLayouts })}> + <FontAwesomeIcon style={{ transition: 'all 0.3s', transform: this.openLayouts ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"caret-down"} size={"lg"} /> + </div> + </div> + </div > + ); + } + + @observable openLayouts: boolean = false; + @observable addFreeform: boolean = true; + @observable layout: string = ""; + @observable title: string = ""; + @computed get newDocumentDropdown() { - let type = ""; - let title = ""; return ( <div> - <div className={`presBox-ribbon ${this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className={"presBox-ribbon"} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="ribbon-box"> Slide Title: <br></br> {/* <div className="dropdown-textInput"> */} <input className="ribbon-textInput" placeholder="..." type="text" name="fname" ref={this.inputRef} onChange={(e) => { e.stopPropagation(); - title = e.target.value; + runInAction(() => { (this.title = e.target.value) }); }}></input> {/* </div> */} </div> <div className="ribbon-box"> Choose type: - <div style={{ display: 'block', alignSelf: 'center' }}> - <div title="Text" className={'ribbon-button'} style={{ background: type === 'text' ? "#000000" : "#f6f6f6" }} onClick={action(() => { type = "text"; })}>Text</div> - <div title="Freeform" className={'ribbon-button'} style={{ background: type === 'freeform' ? "#000000" : "#f6f6f6" }} onClick={action(() => { type = "freeform"; })}>Freeform</div> + <div className="ribbon-doubleButton"> + <div title="Text" className={'ribbon-button'} style={{ background: this.addFreeform ? "" : "#aedef8" }} onClick={() => runInAction(() => { this.addFreeform = !this.addFreeform })}>Text</div> + <div title="Freeform" className={'ribbon-button'} style={{ background: this.addFreeform ? "#aedef8" : "" }} onClick={() => runInAction(() => { this.addFreeform = !this.addFreeform })}>Freeform</div> </div> </div> - <div className="ribbon-box"> + <div className="ribbon-box" style={{ display: this.addFreeform ? "grid" : "none" }}> Preset layouts: - <div className="layout-container"> - <div className="layout"> - <div className="header">HEADER</div> - <div className="subheader">Content goes here</div> + <div className="layout-container" style={{ height: this.openLayouts ? 'max-content' : '75px' }}> + <div className="layout" style={{ border: this.layout === 'blank' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'blank' })} /> + <div className="layout" style={{ border: this.layout === 'title' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'title' })}> + <div className="title">Title</div> + <div className="subtitle">Subtitle</div> + </div> + <div className="layout" style={{ border: this.layout === 'header' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'header' })}> + <div className="title" style={{ alignSelf: 'center', fontSize: 10 }}>Section header</div> </div> - <div className="layout"> - <div className="header" style={{ gridColumn: 1 / 2, gridRow: 1 }}>HEADER</div> - <div className="subheader" style={{ gridColumn: 1, gridRow: 2 }}>Some content</div> - <div className="subheader" style={{ gridColumn: 2, gridRow: 2 }}>Some more content</div> + <div className="layout" style={{ border: this.layout === 'content' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'content' })}> + <div className="title" style={{ alignSelf: 'center' }}>Title</div> + <div className="content">Text goes here</div> </div> - <div className="layout"> - <div className="header">HEADER</div> - <div className="subheader">Content goes here</div> + <div className="layout" style={{ border: this.layout === 'twoColumns' ? 'solid 2px #5b9ddd' : '' }} onClick={() => runInAction(() => { this.layout = 'twoColumns' })}> + <div className="title" style={{ alignSelf: 'center', gridColumn: '1/3' }}>Title</div> + <div className="content" style={{ gridColumn: 1, gridRow: 2 }}>Column one text</div> + <div className="content" style={{ gridColumn: 2, gridRow: 2 }}>Column two text</div> </div> </div> + <div className="open-layout" onClick={() => runInAction(() => { this.openLayouts = !this.openLayouts })}> + <FontAwesomeIcon style={{ transition: 'all 0.3s', transform: this.openLayouts ? 'rotate(180deg)' : 'rotate(0deg)' }} icon={"caret-down"} size={"lg"} /> + </div> </div> <div className="ribbon-final-box"> - <div className="ribbon-final-button" onClick={() => this.createNewSlide(title, type)}> + <div className={this.title !== "" && (this.addFreeform && this.layout !== "" || !this.addFreeform) ? "ribbon-final-button-hidden" : "ribbon-final-button"} onClick={() => this.createNewSlide(this.layout, this.title, this.addFreeform)}> Create New Slide </div> </div> @@ -933,6 +1015,78 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> ); } + createNewSlide = (layout?: string, title?: string, freeform?: boolean) => { + console.log("whats going on?"); + let doc = undefined; + if (freeform && layout) doc = this.createTemplate(layout, title); + if (!freeform) doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 225, title: title }); + const presCollection = Cast(this.layoutDoc.presCollection, Doc, null); + const data = Cast(presCollection.data, listSpec(Doc)); + const presData = Cast(this.rootDoc.data, listSpec(Doc)); + console.log(data); + console.log(doc); + if (data && doc && presData) { + console.log("data and doc"); + data.push(doc); + DockedFrameRenderer.PinDoc(doc, false); + } + } + + createTemplate = (layout: string, input?: string) => { + let doc = undefined; + const title = Docs.Create.TextDocument("Click to change title", { + title: "Slide title", _width: 380, _height: 60, x: 10, y: 58, _fontSize: "24pt" + }); + const subtitle = Docs.Create.TextDocument("Click to change subtitle", { + title: "Slide subtitle", _width: 380, _height: 50, x: 10, y: 118, _fontSize: "16pt" + }); + const header = Docs.Create.TextDocument("Click to change header", { + title: "Slide header", _width: 380, _height: 65, x: 10, y: 80, _fontSize: "20pt" + }); + const contentTitle = Docs.Create.TextDocument("Click to change title", { + title: "Slide title", _width: 380, _height: 60, x: 10, y: 10, _fontSize: "24pt" + }); + const content = Docs.Create.TextDocument("Click to change texte", { + title: "Slide text", _width: 380, _height: 145, x: 10, y: 70, _fontSize: "14pt" + }); + const content1 = Docs.Create.TextDocument("Click to change text", { + title: "Column 1", _width: 185, _height: 140, x: 10, y: 80, _fontSize: "14pt" + }); + const content2 = Docs.Create.TextDocument("Click to change text", { + title: "Column 2", _width: 185, _height: 140, x: 205, y: 80, _fontSize: "14pt" + }); + switch (layout) { + case 'blank': + doc = Docs.Create.FreeformDocument([], { + title: input ? input : "Blank slide", _width: 400, _height: 225, _fitToBox: true + }); + break; + case 'title': + doc = Docs.Create.FreeformDocument([title, subtitle], { + title: input ? input : "Title slide", _width: 400, _height: 225, _fitToBox: true + }); + break; + case 'header': + doc = Docs.Create.FreeformDocument([header], { + title: input ? input : "Section header", _width: 400, _height: 225, _fitToBox: true + }); + break; + case 'content': + doc = Docs.Create.FreeformDocument([contentTitle, content], { + title: input ? input : "Title and content", _width: 400, _height: 225, _fitToBox: true + }); + break; + case 'twoColumns': + doc = Docs.Create.FreeformDocument([contentTitle, content1, content2], { + title: input ? input : "Title and two columns", _width: 400, _height: 225, _fitToBox: true + }); + break; + default: + break; + } + return doc; + } + @computed get playDropdown() { return ( <div className={`dropdown-play ${this.playTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> @@ -1021,6 +1175,21 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } + @computed get stringType(): string { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); + let type: string = ''; + switch (targetDoc.type) { + case DocumentType.PDF: type = "PDF"; break; + case DocumentType.RTF: type = "Text node"; break; + case DocumentType.COL: type = "Collection"; break; + case DocumentType.AUDIO: type = "Audio"; break; + case DocumentType.VID: type = "Video"; break; + default: type = "Other node"; break; + } + return type; + } + @computed get progressivizeDropdown() { const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); const targetDoc = Cast(activeItem?.presentationTargetDoc, Doc, null); @@ -1030,32 +1199,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div> <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> <div className="ribbon-box"> - {targetDoc.type} selected - <div className="selectedList" style={{ height: 'max-content' }}> - <div className="selectedList-items">{targetDoc.title}</div> - </div> - <div className="ribbon-doubleButton"> - <div className="ribbon-frameSelector"> - <div key="back" title="back frame" className="backKeyframe" onClick={e => { e.stopPropagation(); this.prevKeyframe(targetDoc); }}> - <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> - </div> - <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: targetDoc.editing ? "#5a9edd" : "#5a9edd" }} - onClick={action(() => targetDoc.editing = !targetDoc.editing)} > - {NumCast(targetDoc.currentFrame)} - </div> - <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={e => { e.stopPropagation(); this.nextKeyframe(targetDoc); }}> - <FontAwesomeIcon icon={"caret-right"} size={"lg"} /> - </div> - </div> - <Tooltip title={<><div className="dash-tooltip">{"Last frame"}</div></>}><div style={{ fontWeight: 600, marginTop: 0, marginLeft: 3 }} className="ribbon-button">{NumCast(targetDoc.lastFrame)}</div></Tooltip> - </div> - </div> - <div className="ribbon-final-box"> + {this.stringType} selected <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL ? "inline-flex" : "none" }}> <div className="ribbon-button" style={{ backgroundColor: activeItem.presProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeChild}>Child documents</div> <div className="ribbon-button" style={{ display: activeItem.presProgressivize ? "flex" : "none", backgroundColor: targetDoc.editProgressivize ? "#aedef8" : "" }} onClick={this.editProgressivize}>Edit</div> </div> - <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL || targetDoc.type === "image" ? "inline-flex" : "none" }}> + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.COL || targetDoc.type === DocumentType.IMG ? "inline-flex" : "none" }}> <div className="ribbon-button" style={{ backgroundColor: activeItem.zoomProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeZoom}>Internal zoom</div> <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editZoomProgressivize ? "#aedef8" : "" }} onClick={this.editZoomProgressivize}>Viewfinder</div> <div className="ribbon-button" style={{ display: activeItem.zoomProgressivize ? "flex" : "none", backgroundColor: targetDoc.editSnapZoomProgressivize ? "#aedef8" : "" }} onClick={this.editSnapZoomProgressivize}>Snapshot</div> @@ -1064,11 +1213,30 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div className="ribbon-button" onClick={this.progressivizeText}>Text progressivize</div> <div className="ribbon-button" style={{ display: activeItem.textProgressivize ? "flex" : "none", backgroundColor: targetDoc.editTextProgressivize ? "#aedef8" : "" }} onClick={this.editTextProgressivize}>Edit</div> </div> - <div className="ribbon-doubleButton" style={{ display: targetDoc.type === "pdf" ? "inline-flex" : "none" }}> + <div className="ribbon-doubleButton" style={{ display: targetDoc.type === DocumentType.PDF ? "inline-flex" : "none" }}> <div className="ribbon-button" style={{ backgroundColor: activeItem.scrollProgressivize ? "#aedef8" : "" }} onClick={this.progressivizeScroll}>Scroll progressivize</div> <div className="ribbon-button" style={{ display: activeItem.scrollProgressivize ? "flex" : "none", backgroundColor: targetDoc.editScrollProgressivize ? "#aedef8" : "" }} onClick={this.editScrollProgressivize}>Edit</div> </div> </div> + <div className="ribbon-final-box" style={{ display: activeItem.zoomProgressivize || activeItem.scrollProgressivize || activeItem.presProgressivize || activeItem.textProgressivize ? "inline-flex" : "none" }}> + Frames + <div className="ribbon-doubleButton"> + <div className="ribbon-frameSelector"> + <div key="back" title="back frame" className="backKeyframe" onClick={e => { e.stopPropagation(); this.prevKeyframe(targetDoc); }}> + <FontAwesomeIcon icon={"caret-left"} size={"lg"} /> + </div> + <div key="num" title="toggle view all" className="numKeyframe" style={{ backgroundColor: targetDoc.editing ? "#5a9edd" : "#5a9edd" }} + onClick={action(() => targetDoc.editing = !targetDoc.editing)} > + {NumCast(targetDoc.currentFrame)} + </div> + <div key="fwd" title="forward frame" className="fwdKeyframe" onClick={e => { e.stopPropagation(); this.nextKeyframe(targetDoc); }}> + <FontAwesomeIcon icon={"caret-right"} size={"lg"} /> + </div> + </div> + <Tooltip title={<><div className="dash-tooltip">{"Last frame"}</div></>}><div className="ribbon-property">{NumCast(targetDoc.lastFrame)}</div></Tooltip> + </div> + <div className="ribbon-button" style={{ height: 20, backgroundColor: "#5a9edd" }} onClick={() => console.log("play frames")}>Play</div> + </div> </div> </div> ); @@ -1556,7 +1724,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </Tooltip> {/* <div className="toolbar-button"><FontAwesomeIcon title={"Portal"} icon={"eye"} onClick={this.toolbarTest} /></div> */} <div className="toolbar-divider" /> - <Tooltip title={<><div className="dash-tooltip">{"Transitions"}</div></>}><div className={`toolbar-button ${this.transitionTools ? "active" : ""}`} onClick={this.toggleTransitionTools}> + {/* <Tooltip title={<><div className="dash-tooltip">{"Transitions"}</div></>}><div className={`toolbar-button ${this.transitionTools ? "active" : ""}`} onClick={this.toggleTransitionTools}> <FontAwesomeIcon icon={"rocket"} /> <div style={{ display: this.props.PanelWidth() > 430 ? "block" : "none" }} className="toolbar-buttonText"> Transitions</div> <FontAwesomeIcon className={`dropdown ${this.transitionTools ? "active" : ""}`} icon={"angle-down"} /> @@ -1567,7 +1735,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <div style={{ display: this.props.PanelWidth() > 430 ? "block" : "none" }} className="toolbar-buttonText"> Progressivize</div> <FontAwesomeIcon className={`dropdown ${this.progressivizeTools ? "active" : ""}`} icon={"angle-down"} /> </div></Tooltip> - <div className="toolbar-divider" /> + <div className="toolbar-divider" /> */} <div className="toolbar-button" style={{ position: 'absolute', right: 23, transform: 'rotate(45deg)', fontSize: 16 }}> <FontAwesomeIcon className={"toolbar-thumbtack"} icon={"thumbtack"} /> </div> @@ -1704,10 +1872,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> </div> </div> <div id="toolbarContainer" className={`presBox-toolbar ${this.layoutDoc.presStatus === "edit" ? "active" : ""}`}> {this.toolbar} </div> - {this.newDocumentDropdown} + {this.newDocumentToolbarDropdown} + {/* {this.newDocumentDropdown} {this.moreInfoDropdown} {this.transitionDropdown} - {this.progressivizeDropdown} + {this.progressivizeDropdown} */} <div className="presBox-listCont"> {/* ref={this.createPresDropTarget}> */} {mode !== CollectionViewType.Invalid ? diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index a27d5ef16..0e245cf02 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -231,6 +231,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc } private _itemRef: React.RefObject<HTMLDivElement> = React.createRef(); + private _dragRef: React.RefObject<HTMLDivElement> = React.createRef(); headerDown = (e: React.PointerEvent<HTMLDivElement>) => { const element = document.elementFromPoint(e.clientX, e.clientY)?.parentElement; @@ -251,7 +252,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc // let value = this.getValue(this._heading); // value = typeof value === "string" ? `"${value}"` : value; if (activeItem) { - DragManager.StartDocumentDrag(PresBox.Instance._eleArray.map(ele => ele), dragData, e.clientX, e.clientY); + DragManager.StartDocumentDrag(PresBox.Instance._dragArray.map(ele => ele), dragData, e.clientX, e.clientY); activeItem.dragging = true; return true; } @@ -269,15 +270,19 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc ref={this._itemRef} style={{ outlineWidth: Doc.IsBrushed(this.targetDoc) ? `1px` : "0px", }} onClick={e => { + e.stopPropagation(); + e.preventDefault(); if (e.ctrlKey || e.metaKey) { - PresBox.Instance.multiSelect(this.rootDoc, this._itemRef.current!); + PresBox.Instance.multiSelect(this.rootDoc, this._itemRef.current!, this._dragRef.current!); console.log("cmmd click"); } else if (e.shiftKey) { - PresBox.Instance.shiftSelect(this.rootDoc, this._itemRef.current!); + PresBox.Instance.shiftSelect(this.rootDoc, this._itemRef.current!, , this._dragRef.current!); } else { - this.props.focus(this.rootDoc); e.stopPropagation(); + this.props.focus(this.rootDoc); PresBox.Instance._eleArray = []; PresBox.Instance._eleArray.push(this._itemRef.current!); + PresBox.Instance._dragArray = []; + PresBox.Instance._dragArray.push(this._dragRef.current!); console.log("normal click"); } }} @@ -290,7 +295,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc onPointerDown={this.headerDown} > <> - <div className="presElementBox-number"> + <div ref={this._dragRef} className="presElementBox-number"> {`${this.indexInPres + 1}.`} </div> <div className="presElementBox-name"> diff --git a/src/server/MemoryDatabase.ts b/src/server/MemoryDatabase.ts index 7f477327e..d2d8bb3b3 100644 --- a/src/server/MemoryDatabase.ts +++ b/src/server/MemoryDatabase.ts @@ -1,4 +1,3 @@ -import { DH_CHECK_P_NOT_SAFE_PRIME } from 'constants'; import * as mongodb from 'mongodb'; import { DocumentsCollection, IDatabase } from './IDatabase'; import { Transferable } from './Message'; diff --git a/src/server/websocket.ts b/src/server/websocket.ts index d5f89a750..827888ff7 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -1,5 +1,5 @@ -import { green } from "colors"; import * as express from "express"; +import { blue, green } from "colors"; import { createServer, Server } from "https"; import { networkInterfaces } from "os"; import * as sio from 'socket.io'; @@ -186,7 +186,7 @@ export namespace WebSocket { + currentdate.getHours() + ":" + currentdate.getMinutes() + ":" + currentdate.getSeconds(); - console.log(green(`user ${userEmail} has connected to the web socket at: ${datetime}`)); + console.log(blue(`user ${userEmail} has connected to the web socket at: ${datetime}`)); socketMap.set(socket, userEmail); } @@ -208,10 +208,12 @@ export namespace WebSocket { } function GetRefField([id, callback]: [string, (result?: Transferable) => void]) { + process.stdout.write(`(f)`) Database.Instance.getDocument(id, callback); } function GetRefFields([ids, callback]: [string[], (result?: Transferable[]) => void]) { + console.log(green(`> ${ids.length} fields`)); Database.Instance.getDocuments(ids, callback); } diff --git a/webpack.config.js b/webpack.config.js index a5fe6ad80..c973be1ed 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -66,42 +66,42 @@ module.exports = { }, module: { rules: [{ - test: [/\.tsx?$/], - use: [{ - loader: 'ts-loader', - options: { - transpileOnly: true - } - }] + test: [/\.tsx?$/], + use: [{ + loader: 'ts-loader', + options: { + transpileOnly: true + } + }] + }, + { + test: /\.scss|css$/, + use: [{ + loader: "style-loader" }, { - test: /\.scss|css$/, - use: [{ - loader: "style-loader" - }, - { - loader: "css-loader" - }, - { - loader: "sass-loader" - } - ] + loader: "css-loader" }, { - test: /\.(jpg|png|pdf)$/, - use: [{ - loader: 'file-loader' - }] - }, - { - test: /\.(png|jpg|gif)$/i, - use: [{ - loader: 'url-loader', - options: { - limit: 8192 - } - }] + loader: "sass-loader" } + ] + }, + { + test: /\.(jpg|png|pdf)$/, + use: [{ + loader: 'file-loader' + }] + }, + { + test: /\.(png|jpg|gif)$/i, + use: [{ + loader: 'url-loader', + options: { + limit: 8192 + } + }] + } ] }, plugins, |