diff options
Diffstat (limited to 'src/client/views/collections/collectionLinearView')
3 files changed, 332 insertions, 0 deletions
diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.scss b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss new file mode 100644 index 000000000..a10d43917 --- /dev/null +++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.scss @@ -0,0 +1,139 @@ +@import "../../global/globalCssVariables"; +@import "../../_nodeModuleOverrides"; + +.collectionLinearView-outer { + overflow: visible; + height: 100%; + pointer-events: none; + + .collectionLinearView { + display: flex; + height: 100%; + align-items: center; + + >span { + background: $dark-gray; + color: $white; + border-radius: 18px; + margin-right: 6px; + cursor: pointer; + } + + .bottomPopup-background { + background: $medium-blue; + display: flex; + border-radius: 10px; + height: 35; + transform: translate3d(6px, 0px, 0px); + align-content: center; + justify-content: center; + align-items: center; + } + + .bottomPopup-text { + color: $white; + display: inline; + white-space: nowrap; + padding-left: 8px; + padding-right: 20px; + vertical-align: middle; + font-size: 12.5px; + } + + .bottomPopup-descriptions { + cursor:pointer; + display: inline; + white-space: nowrap; + padding-left: 8px; + padding-right: 8px; + vertical-align: middle; + background-color: $light-gray; + border-radius: 3px; + color: black; + margin-right: 5px; + } + + .bottomPopup-exit { + cursor:pointer; + display: inline; + white-space: nowrap; + margin-right: 10px; + padding-left: 8px; + padding-right: 8px; + vertical-align: middle; + background-color: $close-red; + border-radius: 3px; + color: black; + } + + >label { + margin-top: "auto"; + margin-bottom: "auto"; + background: $dark-gray; + color: $white; + display: inline-block; + border-radius: 18px; + font-size: 12.5px; + width: 18px; + height: 18px; + margin-top: auto; + margin-bottom: auto; + margin-right: 3px; + cursor: pointer; + transition: transform 0.2s; + } + + label p { + padding-left: 5px; + } + + label:hover { + background: $medium-gray; + transform: scale(1.15); + } + + >input { + display: none; + } + + >input:not(:checked)~.collectionLinearView-content { + display: none; + } + + >input:checked~label { + transform: rotate(45deg); + transition: transform 0.5s; + cursor: pointer; + } + + .collectionLinearView-content { + display: flex; + opacity: 1; + position: relative; + margin-top: auto; + + .collectionLinearView-docBtn, + .collectionLinearView-docBtn-scalable { + position: relative; + margin: auto; + margin-left: 3px; + transform-origin: center 80%; + } + + .collectionLinearView-docBtn-scalable:hover { + transform: scale(1.15); + } + + .collectionLinearView-round-button { + width: 18px; + height: 18px; + border-radius: 18px; + font-size: 15px; + } + + .collectionLinearView-round-button:hover { + transform: scale(1.15); + } + } + } +}
\ No newline at end of file diff --git a/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx new file mode 100644 index 000000000..8e2ba2275 --- /dev/null +++ b/src/client/views/collections/collectionLinearView/CollectionLinearView.tsx @@ -0,0 +1,192 @@ +import { Tooltip } from '@material-ui/core'; +import { action, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { makeInterface } from '../../../../fields/Schema'; +import { documentSchema } from '../../../../fields/documentSchemas'; +import { CollectionSubView } from '../CollectionSubView'; +import { DragManager } from '../../../util/DragManager'; +import { ScriptCast, NumCast, StrCast, BoolCast } from '../../../../fields/Types'; +import { HeightSym, Doc, WidthSym } from '../../../../fields/Doc'; +import { Utils, returnFalse, returnTrue, emptyFunction, returnEmptyDoclist } from '../../../../Utils'; +import { DocumentLinksButton } from '../../nodes/DocumentLinksButton'; +import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup'; +import { StyleProp } from '../../StyleProvider'; +import { CollectionViewType } from '../CollectionView'; +import { Id } from '../../../../fields/FieldSymbols'; +import { DocumentView } from '../../nodes/DocumentView'; +import { Transform } from '../../../util/Transform'; + + +type LinearDocument = makeInterface<[typeof documentSchema,]>; +const LinearDocument = makeInterface(documentSchema); + +@observer +export class CollectionLinearView extends CollectionSubView(LinearDocument) { + @observable public addMenuToggle = React.createRef<HTMLInputElement>(); + @observable private _selectedIndex = -1; + private _dropDisposer?: DragManager.DragDropDisposer; + private _widthDisposer?: IReactionDisposer; + private _selectedDisposer?: IReactionDisposer; + + componentWillUnmount() { + this._dropDisposer?.(); + this._widthDisposer?.(); + this._selectedDisposer?.(); + this.childLayoutPairs.map((pair, ind) => ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log)); + } + + componentDidMount() { + this._widthDisposer = reaction(() => 5 + (this.layoutDoc.linearViewIsExpanded ? this.childDocs.length * (this.rootDoc[HeightSym]()) : 10), + width => this.childDocs.length && (this.layoutDoc._width = width), + { fireImmediately: true } + ); + + this._selectedDisposer = reaction( + () => NumCast(this.layoutDoc.selectedIndex), + (i) => runInAction(() => { + this._selectedIndex = i; + let selected: any = undefined; + this.childLayoutPairs.map(async (pair, ind) => { + const isSelected = this._selectedIndex === ind; + if (isSelected) { + selected = pair; + } + else { + ScriptCast(pair.layout.proto?.onPointerUp)?.script.run({ this: pair.layout.proto }, console.log); + } + }); + if (selected && selected.layout) { + ScriptCast(selected.layout.proto?.onPointerDown)?.script.run({ this: selected.layout.proto }, console.log); + } + }), + { fireImmediately: true } + ); + } + protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view + this._dropDisposer && this._dropDisposer(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, this.onInternalDrop.bind(this), this.layoutDoc); + } + } + + dimension = () => NumCast(this.rootDoc._height); // 2 * the padding + getTransform = (ele: React.RefObject<HTMLDivElement>) => () => { + if (!ele.current) return Transform.Identity(); + const { scale, translateX, translateY } = Utils.GetScreenTransform(ele.current); + return new Transform(-translateX, -translateY, 1); + } + + @action + exitLongLinks = () => { + if (DocumentLinksButton.StartLink) { + if (DocumentLinksButton.StartLink.Document) { + action((e: React.PointerEvent<HTMLDivElement>) => { + Doc.UnBrushDoc(DocumentLinksButton.StartLink?.Document as Doc); + }); + } + } + DocumentLinksButton.StartLink = undefined; + DocumentLinksButton.StartLinkView = undefined; + } + + @action + changeDescriptionSetting = () => { + if (LinkDescriptionPopup.showDescriptions) { + if (LinkDescriptionPopup.showDescriptions === "ON") { + LinkDescriptionPopup.showDescriptions = "OFF"; + LinkDescriptionPopup.descriptionPopup = false; + } else { + LinkDescriptionPopup.showDescriptions = "ON"; + } + } else { + LinkDescriptionPopup.showDescriptions = "OFF"; + LinkDescriptionPopup.descriptionPopup = false; + } + } + + render() { + const guid = Utils.GenerateGuid(); + const flexDir: any = StrCast(this.Document.flexDirection); + const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor); + const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color); + + const menuOpener = <label htmlFor={`${guid}`} style={{ pointerEvents: "all", cursor: "pointer", background: backgroundColor === color ? "black" : backgroundColor, }} + onPointerDown={e => e.stopPropagation()} > + <p>{BoolCast(this.layoutDoc.linearViewIsExpanded) ? "–" : "+"}</p> + </label>; + + return <div className="collectionLinearView-outer"> + <div className="collectionLinearView" ref={this.createDashEventsTarget} > + <Tooltip title={<><div className="dash-tooltip">{BoolCast(this.layoutDoc.linearViewIsExpanded) ? "Close menu" : "Open menu"}</div></>} placement="top"> + {menuOpener} + </Tooltip> + <input id={`${guid}`} type="checkbox" checked={BoolCast(this.layoutDoc.linearViewIsExpanded)} ref={this.addMenuToggle} + onChange={action(() => this.layoutDoc.linearViewIsExpanded = this.addMenuToggle.current!.checked)} /> + + <div className="collectionLinearView-content" style={{ height: this.dimension(), flexDirection: flexDir }}> + {this.childLayoutPairs.map((pair, ind) => { + const nested = pair.layout._viewType === CollectionViewType.Linear; + const dref = React.createRef<HTMLDivElement>(); + const scalable = pair.layout.onClick || pair.layout.onDragStart; + return <div className={`collectionLinearView-docBtn` + (scalable ? "-scalable" : "")} key={pair.layout[Id]} ref={dref} + style={{ + pointerEvents: "all", + minWidth: 30, + width: nested ? pair.layout[WidthSym]() : this.dimension(), + height: nested && pair.layout.linearViewIsExpanded ? pair.layout[HeightSym]() : this.dimension(), + }} > + <DocumentView + Document={pair.layout} + DataDoc={pair.data} + isContentActive={returnFalse} + isDocumentActive={returnTrue} + addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} + addDocTab={this.props.addDocTab} + pinToPres={emptyFunction} + rootSelected={this.props.isSelected} + removeDocument={this.props.removeDocument} + ScreenToLocalTransform={this.getTransform(dref)} + PanelWidth={nested ? pair.layout[WidthSym] : this.dimension} + PanelHeight={nested ? pair.layout[HeightSym] : this.dimension} + renderDepth={this.props.renderDepth + 1} + focus={emptyFunction} + styleProvider={this.props.styleProvider} + layerProvider={this.props.layerProvider} + docViewPath={returnEmptyDoclist} + whenChildContentsActiveChanged={emptyFunction} + bringToFront={emptyFunction} + docFilters={this.props.docFilters} + docRangeFilters={this.props.docRangeFilters} + searchFilterDocs={this.props.searchFilterDocs} + ContainingCollectionView={undefined} + ContainingCollectionDoc={undefined} /> + </div>; + })} + </div> + {DocumentLinksButton.StartLink ? <span className="bottomPopup-background" style={{ + pointerEvents: "all" + }} + onPointerDown={e => e.stopPropagation()} > + <span className="bottomPopup-text" > + Creating link from: <b>{DocumentLinksButton.AnnotationId ? "Annotation in " : " "} {StrCast(DocumentLinksButton.StartLink.title).length < 51 ? DocumentLinksButton.StartLink.title : StrCast(DocumentLinksButton.StartLink.title).slice(0, 50) + '...'}</b> + </span> + + <Tooltip title={<><div className="dash-tooltip">{"Toggle description pop-up"} </div></>} placement="top"> + <span className="bottomPopup-descriptions" onClick={this.changeDescriptionSetting}> + Labels: {LinkDescriptionPopup.showDescriptions ? LinkDescriptionPopup.showDescriptions : "ON"} + </span> + </Tooltip> + + <Tooltip title={<><div className="dash-tooltip">Exit linking mode</div></>} placement="top"> + <span className="bottomPopup-exit" onClick={this.exitLongLinks}> + Stop + </span> + </Tooltip> + + </span> : null} + </div> + </div>; + } +}
\ No newline at end of file diff --git a/src/client/views/collections/collectionLinearView/index.ts b/src/client/views/collections/collectionLinearView/index.ts new file mode 100644 index 000000000..ff73e14ae --- /dev/null +++ b/src/client/views/collections/collectionLinearView/index.ts @@ -0,0 +1 @@ +export * from "./CollectionLinearView";
\ No newline at end of file |
