diff options
Diffstat (limited to 'src/client/views/nodes/trails/PresSlideBox.tsx')
-rw-r--r-- | src/client/views/nodes/trails/PresSlideBox.tsx | 628 |
1 files changed, 628 insertions, 0 deletions
diff --git a/src/client/views/nodes/trails/PresSlideBox.tsx b/src/client/views/nodes/trails/PresSlideBox.tsx new file mode 100644 index 000000000..3dbb3da88 --- /dev/null +++ b/src/client/views/nodes/trails/PresSlideBox.tsx @@ -0,0 +1,628 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Tooltip } from '@mui/material'; +import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { returnFalse, returnTrue, setupMoveUpEvents } from '../../../../ClientUtils'; +import { Doc, DocListCast, Opt } from '../../../../fields/Doc'; +import { Id } from '../../../../fields/FieldSymbols'; +import { List } from '../../../../fields/List'; +import { BoolCast, DocCast, NumCast, StrCast } from '../../../../fields/Types'; +import { emptyFunction } from '../../../../Utils'; +import { Docs } from '../../../documents/Documents'; +import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes'; +import { DragManager } from '../../../util/DragManager'; +import { SnappingManager } from '../../../util/SnappingManager'; +import { Transform } from '../../../util/Transform'; +import { undoable, undoBatch } from '../../../util/UndoManager'; +import { TreeView } from '../../collections/TreeView'; +import { ViewBoxBaseComponent } from '../../DocComponent'; +import { EditableView } from '../../EditableView'; +import { Colors } from '../../global/globalEnums'; +import { PinDocView } from '../../PinFuncs'; +import { StyleProp } from '../../StyleProp'; +import { returnEmptyDocViewList } from '../../StyleProvider'; +import { DocumentView } from '../DocumentView'; +import { FieldView, FieldViewProps } from '../FieldView'; +import { PresBox } from './PresBox'; +import './PresSlideBox.scss'; +import { PresMovement } from './PresEnums'; +/** + * This class models the view a document added to presentation will have in the presentation. + * It involves some functionality for its buttons and options. + */ +@observer +export class PresSlideBox extends ViewBoxBaseComponent<FieldViewProps>() { + public static LayoutString(fieldKey: string) { + return FieldView.LayoutString(PresSlideBox, fieldKey); + } + private _itemRef: React.RefObject<HTMLDivElement> = React.createRef(); + private _dragRef: React.RefObject<HTMLDivElement> = React.createRef(); + private _titleRef: React.RefObject<EditableView> = React.createRef(); + private _heightDisposer: IReactionDisposer | undefined; + readonly expandViewHeight = 100; + readonly collapsedHeight = 35; + + constructor(props: FieldViewProps) { + super(props); + makeObservable(this); + } + + @observable _dragging = false; + + // the presentation view that renders this slide + @computed get presBoxView() { + return this.DocumentView?.() + .containerViewPath?.() + .slice() + .reverse() + .find(dv => dv?.ComponentView instanceof PresBox)?.ComponentView as Opt<PresBox>; + } + + // the presentation view document that renders this slide + @computed get presBox() { + return this.presBoxView?.Document; + } + + // Since this node is being rendered with a template, this method retrieves + // the actual slide being rendered from the auto-generated rendering template + @computed get slideDoc() { + return this.rootDoc; + } + + // this is the document in the workspaces that is targeted by the slide + @computed get targetDoc() { + return DocCast(this.slideDoc.presentation_targetDoc, this.slideDoc)!; + } + + // computes index of this presentation slide in the presBox list + @computed get indexInPres() { + return this.presBoxView?.SlideIndex(this.slideDoc) ?? 0; + } + + @computed get selectedArray() { + return this.presBoxView?.selectedArray; + } + + @computed get videoRecordingIsInOverlay() { + return Doc.MyOverlayDocs.some(doc => doc.slides === this.slideDoc); + } + + componentDidMount() { + this.layoutDoc.layout_hideLinkButton = true; + this._heightDisposer = reaction( + () => ({ expand: this.slideDoc.presentation_expandInlineButton, height: this.collapsedHeight }), + ({ expand, height }) => { + this.layoutDoc._height = height + (expand ? this.expandViewHeight : 0); + }, + { fireImmediately: true } + ); + } + componentWillUnmount() { + this._heightDisposer?.(); + } + + presExpandDocumentClick = () => { + this.slideDoc.presentation_expandInlineButton = !this.slideDoc.presentation_expandInlineButton; + }; + embedHeight = () => this.collapsedHeight + this.expandViewHeight; + embedWidth = () => this._props.PanelWidth() / 2; + // prettier-ignore + styleProvider = ( doc: Doc | undefined, props: Opt<FieldViewProps>, property: string ) => + (property === StyleProp.Opacity ? 1 : this._props.styleProvider?.(doc, props, property)); + /** + * The function that is responsible for rendering a preview or not for this + * presentation element. + */ + @computed get renderEmbeddedInline() { + return !this.slideDoc.presentation_expandInlineButton || !this.targetDoc ? null : ( + <div className="presItem-embedded" style={{ height: this.embedHeight(), width: '50%' }}> + <DocumentView + Document={PresBox.targetRenderedDoc(this.slideDoc) ?? this.slideDoc} + PanelWidth={this.embedWidth} + PanelHeight={this.embedHeight} + isContentActive={this._props.isContentActive} + styleProvider={this.styleProvider} + hideLinkButton + ScreenToLocalTransform={Transform.Identity} + renderDepth={this._props.renderDepth + 1} + containerViewPath={returnEmptyDocViewList} + childFilters={this._props.childFilters} + childFiltersByRanges={this._props.childFiltersByRanges} + searchFilterDocs={this._props.searchFilterDocs} + addDocument={returnFalse} + removeDocument={returnFalse} + fitContentsToBox={returnTrue} + moveDocument={this._props.moveDocument!} + focus={emptyFunction} + whenChildContentsActiveChanged={returnFalse} + addDocTab={returnFalse} + pinToPres={returnFalse} + /> + </div> + ); + } + + @computed get renderGroupSlides() { + const childDocs = DocListCast(this.targetDoc.data); + const groupSlides = childDocs.map((doc: Doc, ind: number) => ( + <div + key={doc[Id]} + className="presItem-groupSlide" + onClick={e => { + e.stopPropagation(); + e.preventDefault(); + this.presBoxView?.modifierSelect(doc, this._itemRef.current!, this._dragRef.current!, e.shiftKey || e.ctrlKey || e.metaKey, e.ctrlKey || e.metaKey, e.shiftKey); + this.presExpandDocumentClick(); + }}> + <div className="presItem-groupNum">{`${ind + 1}.`}</div> + <div className="presItem-name"> + <EditableView + ref={this._titleRef} + editing={undefined} + contents={StrCast(doc.title)} + overflow="ellipsis" + GetValue={() => StrCast(doc.title)} + SetValue={(value: string) => { + doc.title = !value.trim().length ? '-untitled-' : value; + return true; + }} + /> + </div> + </div> + )); + return groupSlides; + } + + @computed get transition() { + let transitionInS: number; + if (this.slideDoc.presentation_transition) transitionInS = NumCast(this.slideDoc.presentation_transition) / 1000; + else transitionInS = 0.5; + return this.slideDoc.presentation_movement === PresMovement.Jump || this.slideDoc.presentation_movement === PresMovement.None ? null : 'M: ' + transitionInS + 's'; + } + + @action + headerDown = (e: React.PointerEvent<HTMLDivElement>) => { + const element = e.target as HTMLDivElement; + e.stopPropagation(); + e.preventDefault(); + if (element && !(e.ctrlKey || e.metaKey || e.button === 2)) { + this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false); + setupMoveUpEvents(this, e, this.startDrag, emptyFunction, clickEv => { + clickEv.stopPropagation(); + clickEv.preventDefault(); + this.presBoxView?.modifierSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, clickEv.shiftKey || clickEv.ctrlKey || clickEv.metaKey, clickEv.ctrlKey || clickEv.metaKey, clickEv.shiftKey); + this.presBoxView?.activeItem && this.showRecording(this.presBoxView?.activeItem); + }); + } + }; + + /** + * Function to drag and drop the pres element to a diferent location + */ + startDrag = (e: PointerEvent) => { + this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false); + const miniView: boolean = this.toolbarWidth <= 100; + const activeItem = this.slideDoc; + const dragArray = this.presBoxView?._dragArray ?? []; + const dragData = new DragManager.DocumentDragData(this.presBoxView?.sortArray() ?? []); + if (!dragData.draggedDocuments.length) dragData.draggedDocuments.push(this.slideDoc); + dragData.treeViewDoc = this.presBox?._type_collection === CollectionViewType.Tree ? this.presBox : undefined; // this.DocumentView?.()?._props.treeViewDoc; + dragData.moveDocument = this._props.moveDocument; + const dragItem: HTMLElement[] = []; + const classesToRestore = new Map<HTMLElement, string>(); + if (dragArray.length === 1) { + const doc = this._itemRef.current || dragArray[0]; + if (doc) { + classesToRestore.set(doc, doc.className); + doc.className = miniView ? 'presItem-miniSlide' : 'presItem-slide'; + dragItem.push(doc); + } + } else if (dragArray.length >= 1) { + const doc = document.createElement('div'); + doc.className = 'presItem-multiDrag'; + doc.innerText = 'Move ' + (this.selectedArray?.size ?? 0) + ' slides'; + doc.style.position = 'absolute'; + doc.style.top = e.clientY + 'px'; + doc.style.left = e.clientX - 50 + 'px'; + dragItem.push(doc); + } + + if (activeItem) { + runInAction(() => { + this._dragging = true; + }); + DragManager.StartDocumentDrag( + dragItem.map(ele => ele), + dragData, + e.clientX, + e.clientY, + undefined, + action(() => { + Array.from(classesToRestore).forEach(pair => (pair[0].className = pair[1])); + this._dragging = false; + }) + ); + return true; + } + return false; + }; + + onPointerOver = () => { + document.removeEventListener('pointermove', this.onPointerMove); + document.addEventListener('pointermove', this.onPointerMove); + }; + + onPointerMove = (e: PointerEvent) => { + const slide = this._itemRef.current; + const dragIsPresItem = DragManager.docsBeingDragged.some(d => d.presentation_targetDoc); + if (slide && dragIsPresItem) { + const rect = slide.getBoundingClientRect(); + const y = e.clientY - rect.top; // y position within the element. + const height = slide.clientHeight; + const halfLine = height / 2; + if (y <= halfLine) { + slide.style.borderTop = `solid 2px ${Colors.MEDIUM_BLUE}`; + slide.style.borderBottom = '0px'; + } else if (y > halfLine) { + slide.style.borderTop = '0px'; + slide.style.borderBottom = `solid 2px ${Colors.MEDIUM_BLUE}`; + } + } + document.removeEventListener('pointermove', this.onPointerMove); + }; + + onPointerLeave = () => { + const slide = this._itemRef.current; + if (slide) { + slide.style.borderTop = '0px'; + slide.style.borderBottom = '0px'; + } + document.removeEventListener('pointermove', this.onPointerMove); + }; + + @action + toggleProperties = () => { + if (SnappingManager.PropertiesWidth < 5) { + SnappingManager.SetPropertiesWidth(250); + } + }; + + removePresentationItem = undoable( + action((e: React.MouseEvent) => { + e.stopPropagation(); + if (this.presBox && this.indexInPres < (this.presBoxView?.itemIndex || 0)) { + this.presBox.itemIndex = (this.presBoxView?.itemIndex || 0) - 1; + } + this._props.removeDocument?.(this.slideDoc); + this.presBoxView?.removeFromSelectedArray(this.slideDoc); + this.removeAllRecordingInOverlay(); + }), + 'Remove doc from pres trail' + ); + + // set title of the individual pres slide + onSetValue = undoable( + action((value: string) => { + this.slideDoc.title = !value.trim().length ? '-untitled-' : value; + return true; + }), + 'set title of pres element' + ); + + /** + * Method called for updating the view of the currently selected document + * + * @param targetDoc + * @param activeItem + */ + @undoBatch + updateCapturedContainerLayout = (presTargetDoc: Doc, activeItem: Doc) => { + const targetDoc = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc; + activeItem.config_x = NumCast(targetDoc.x); + activeItem.config_y = NumCast(targetDoc.y); + activeItem.config_rotation = NumCast(targetDoc.rotation); + activeItem.config_width = NumCast(targetDoc.width); + activeItem.config_height = NumCast(targetDoc.height); + activeItem.config_pinLayout = !activeItem.config_pinLayout; + // activeItem.config_pinLayout = true; + }; + + /** + * Method called for updating the view of the currently selected document + * + * @param presTargetDoc + * @param activeItem + */ + updateCapturedViewContents = undoable( + action((presTargetDoc: Doc, activeItem: Doc) => { + const target = DocCast(presTargetDoc.annotationOn) ?? presTargetDoc; + PinDocView(activeItem, { pinData: PresBox.pinDataTypes(target) }, target); + }), + 'updated captured view contents' + ); + + // a previously recorded video will have timecode defined + static videoIsRecorded = (activeItem: Opt<Doc>) => 'layout_currentTimecode' in (DocCast(activeItem?.recording) ?? {}); + + removeAllRecordingInOverlay = () => Doc.MyOverlayDocs.filter(doc => doc.slides === this.slideDoc).forEach(Doc.RemFromMyOverlay); + + /// remove all videos that have been recorded from overlay (leave videso that are being recorded to avoid losing data) + static removeEveryExistingRecordingInOverlay = () => { + Doc.MyOverlayDocs.filter(doc => doc.slides !== null && PresSlideBox.videoIsRecorded(DocCast(doc.slides))) // + .forEach(Doc.RemFromMyOverlay); + }; + + hideRecording = undoable( + action((e: React.MouseEvent) => { + e.stopPropagation(); + this.removeAllRecordingInOverlay(); + }), + 'hide video recording' + ); + + showRecording = undoable( + action((activeItem: Doc, iconClick: boolean = false) => { + // remove the overlays on switch *IF* not opened from the specific icon + if (!iconClick) PresSlideBox.removeEveryExistingRecordingInOverlay(); + + DocCast(activeItem.recording) && Doc.AddToMyOverlay(DocCast(activeItem.recording)!); + }), + 'show video recording' + ); + + startRecording = undoable( + action((e: React.MouseEvent, activeItem: Doc) => { + e.stopPropagation(); + if (PresSlideBox.videoIsRecorded(activeItem)) { + // if we already have an existing recording + this.showRecording(activeItem, true); + // // if we already have an existing recording + // Doc.AddToMyOverlay(Cast(activeItem.recording, Doc, null)); + } else { + // we dont have any recording + // Remove every recording that already exists in overlay view + // this is a design decision to clear to focus in on the recoding mode + PresSlideBox.removeEveryExistingRecordingInOverlay(); + + // create and add a recording to the slide + // make recording box appear in the bottom right corner of the screen + Doc.AddToMyOverlay( + (activeItem.recording = Docs.Create.WebCamDocument('', { + _width: 384, + _height: 216, + overlayX: window.innerWidth - 384 - 20, + overlayY: window.innerHeight - 216 - 20, + layout_hideDocumentButtonBar: true, + layout_hideDecorationTitle: true, + layout_hideOpenButton: true, + cloneFieldFilter: new List<string>(['isSystem']), + slides: activeItem, // attach the slide to the recording + })) + ); + } + }), + 'start video recording' + ); + + @undoBatch + lfg = (e: React.MouseEvent) => { + e.stopPropagation(); + // TODO: fix this bug + // const { toggleChildrenRun } = this.slideDoc; + TreeView.ToggleChildrenRun.get(this.slideDoc)?.(); + + // call this.slideDoc.recurChildren() to get all the children + // if (iconClick) PresSlideBox.showVideo = false; + }; + + @computed + get toolbarWidth(): number { + const presBoxDocView = DocumentView.getDocumentView(this.presBox); + const width = NumCast(this.presBox?._width); + return presBoxDocView ? presBoxDocView._props.PanelWidth() : width || 300; + } + + @computed get presButtons() { + const { presBox, targetDoc, slideDoc: activeItem } = this; + const presBoxColor = StrCast(presBox?._backgroundColor); + const presColorBool = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; + const hasChildren = BoolCast(this.slideDoc?.hasChildren); + + const items: JSX.Element[] = []; + + items.push( + <Tooltip key="slide" title={<div className="dash-tooltip">Update captured doc layout</div>}> + <div + className="slideButton" + onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedContainerLayout(targetDoc, activeItem), true)} + style={{ opacity: activeItem.config_pinLayout ? 1 : 0.5, fontWeight: 700, display: 'flex' }}> + L + </div> + </Tooltip> + ); + items.push( + <Tooltip key="flex" title={<div className="dash-tooltip">Update captured doc content</div>}> + <div + className="slideButton" + onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => this.updateCapturedViewContents(targetDoc, activeItem))} + style={{ opacity: activeItem.config_pinData || activeItem.config_pinView ? 1 : 0.5, fontWeight: 700, display: 'flex' }}> + C + </div> + </Tooltip> + ); + items.push( + <Tooltip key="slash" title={<div className="dash-tooltip">{this.videoRecordingIsInOverlay ? 'Hide Recording' : `${PresSlideBox.videoIsRecorded(activeItem) ? 'Show' : 'Start'} recording`}</div>}> + <div className="slideButton" onClick={e => (this.videoRecordingIsInOverlay ? this.hideRecording(e) : this.startRecording(e, activeItem))} style={{ fontWeight: 700 }}> + <FontAwesomeIcon icon={`video${this.videoRecordingIsInOverlay ? '-slash' : ''}`} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + if (this.indexInPres !== 0) { + items.push( + <Tooltip + key="arrow" + title={ + <div className="dash-tooltip"> + {!activeItem.presentation_groupWithUp + ? 'Not grouped with previous slide (click to group)' + : activeItem.presentation_groupWithUp === 1 + ? 'Run simultaneously with previous slide (click again to run after)' + : 'Run after previous slide (click to ungroup from previous)'} + </div> + }> + <div + className="slideButton" + onClick={() => { + activeItem.presentation_groupWithUp = (NumCast(activeItem.presentation_groupWithUp) + 1) % 3; + }} + style={{ + zIndex: 1000 - this.indexInPres, + fontWeight: 700, + backgroundColor: activeItem.presentation_groupWithUp ? (presColorBool ? presBoxColor : Colors.MEDIUM_BLUE) : undefined, + outline: NumCast(activeItem.presentation_groupWithUp) > 1 ? 'solid black 1px' : undefined, + height: activeItem.presentation_groupWithUp ? 53 : 18, + transform: activeItem.presentation_groupWithUp ? 'translate(0, -17px)' : undefined, + }}> + <div style={{ transform: activeItem.presentation_groupWithUp ? 'rotate(180deg) translate(0, -17.5px)' : 'rotate(0deg)' }}> + <FontAwesomeIcon icon="arrow-up" onPointerDown={e => e.stopPropagation()} /> + </div> + </div> + </Tooltip> + ); + } + items.push( + <Tooltip key="eye" title={<div className="dash-tooltip">{this.slideDoc.presentation_expandInlineButton ? 'Minimize' : 'Expand'}</div>}> + <div + className="slideButton" + onClick={e => { + e.stopPropagation(); + this.presExpandDocumentClick(); + }}> + <FontAwesomeIcon icon={this.slideDoc.presentation_expandInlineButton ? 'eye-slash' : 'eye'} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + if (!Doc.noviceMode && hasChildren) { + // TODO: replace with if treeveiw, has childrenDocs + items.push( + <Tooltip key="children" title={<div className="dash-tooltip">Run child processes (tree only)</div>}> + <div + className="slideButton" + onClick={e => { + e.stopPropagation(); + this.lfg(e); + }} + style={{ fontWeight: 700 }}> + <FontAwesomeIcon icon="circle-play" onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + } + items.push( + <Tooltip key="trash" title={<div className="dash-tooltip">Remove from presentation</div>}> + <div className="slideButton" onClick={this.removePresentationItem}> + <FontAwesomeIcon icon="trash" onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + items.push( + <Tooltip key="customize-slide" title={<div className="dash-tooltip">Customize Slide</div>}> + <div + className={'slideButton'} + onClick={() => { + this.presBoxView?.regularSelect(this.slideDoc, this._itemRef.current!, this._dragRef.current!, true, false); + PresBox.Instance.navigateToActiveItem(); + PresBox.Instance.openProperties(); + PresBox.Instance.slideToModify = this.Document; + }}> + <FontAwesomeIcon icon={'edit'} onPointerDown={e => e.stopPropagation()} /> + </div> + </Tooltip> + ); + return items; + } + + @computed get mainItem() { + const { presBox, slideDoc: activeItem } = this; + const isSelected: boolean = !!this.selectedArray?.has(activeItem); + const isCurrent: boolean = this.presBox?._itemIndex === this.indexInPres; + const miniView: boolean = this.toolbarWidth <= 110; + const presBoxColor: string = StrCast(presBox?._backgroundColor); + const presColorBool: boolean = presBoxColor ? presBoxColor !== Colors.WHITE && presBoxColor !== 'transparent' : false; + + return ( + <div + className="presItem-container" + key={activeItem[Id] + this.indexInPres} + ref={this._itemRef} + style={{ + backgroundColor: presColorBool ? (isSelected ? 'rgba(250,250,250,0.3)' : 'transparent') : isSelected ? Colors.LIGHT_BLUE : 'transparent', + opacity: this._dragging ? 0.3 : 1, + paddingLeft: NumCast(this.layoutDoc._xPadding, this._props.xPadding), + paddingRight: NumCast(this.layoutDoc._xPadding, this._props.xPadding), + paddingTop: NumCast(this.layoutDoc._yPadding, this._props.yPadding), + paddingBottom: NumCast(this.layoutDoc._yPadding, this._props.yPadding), + }} + onDoubleClick={action(() => { + this.toggleProperties(); + this.presBoxView?.regularSelect(activeItem, this._itemRef.current!, this._dragRef.current!, false); + })} + onPointerOver={this.onPointerOver} + onPointerLeave={this.onPointerLeave} + onPointerDown={this.headerDown}> + {miniView ? ( + <div className={`presItem-miniSlide ${isSelected ? 'active' : ''}`} ref={this._dragRef}> + {`${this.indexInPres + 1}.`} + </div> + ) : ( + <div + ref={this._dragRef} + className={`presItem-slide ${isCurrent ? 'active' : ''}${activeItem.runProcess ? ' testingv2' : ''}`} + style={{ + display: 'infline-block', + backgroundColor: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string, + // layout_boxShadow: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? '0 0 0px 1.5px' + presBoxColor : undefined) : undefined, + border: presBoxColor && presBoxColor !== 'white' && presBoxColor !== 'transparent' ? (isCurrent ? presBoxColor + ' solid 2.5px' : undefined) : undefined, + }}> + <div + className="presItem-name" + style={{ + display: 'inline-flex', + pointerEvents: isSelected ? undefined : 'none', + width: `calc(100% ${activeItem.presentation_expandInlineButton ? '- 50%' : ''} - ${this.presButtons.length * 22}px`, + cursor: isSelected ? 'text' : 'grab', + }}> + <div + className="presItem-number" + title="select without navigation" + onPointerDown={e => { + e.stopPropagation(); + if (this._itemRef.current && this._dragRef.current) { + this.presBoxView?.modifierSelect(activeItem, this._itemRef.current, this._dragRef.current, true, false, false); + } + }} + onClick={e => e.stopPropagation()}>{`${this.indexInPres + 1}. `}</div> + <EditableView ref={this._titleRef} oneLine editing={!isSelected ? false : undefined} contents={StrCast(activeItem.title)} overflow="ellipsis" GetValue={() => StrCast(activeItem.title)} SetValue={this.onSetValue} /> + </div> + {/* <Tooltip title={<><div className="dash-tooltip">{"Movement speed"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.transition}</div></Tooltip> */} + {/* <Tooltip title={<><div className="dash-tooltip">{"Duration"}</div></>}><div className="presItem-time" style={{ display: showMore ? "block" : "none" }}>{this.duration}</div></Tooltip> */} + <div className="presItem-slideButtons" style={{ position: 'absolute', right: 0 }}> + {...this.presButtons} + </div> + {this.renderEmbeddedInline} + </div> + )} + </div> + ); + } + + render() { + return !(this.slideDoc instanceof Doc) || this.targetDoc instanceof Promise ? null : this.mainItem; + } +} + +Docs.Prototypes.TemplateMap.set(DocumentType.PRESSLIDE, { + layout: { view: PresSlideBox, dataField: 'data' }, + options: { acl: '', title: 'presSlide', _layout_fitWidth: true, _xMargin: 0, isTemplateDoc: true }, +}); |