From 0d263dba422a96c5d22f29a9b6411ff074c92645 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 25 Jan 2020 17:28:57 -0500 Subject: added carousel view --- src/client/documents/Documents.ts | 7 ++- .../views/collections/CollectionCarouselView.scss | 28 ++++++++++ .../views/collections/CollectionCarouselView.tsx | 62 ++++++++++++++++++++++ .../views/collections/CollectionTreeView.tsx | 11 +--- src/client/views/collections/CollectionView.tsx | 5 ++ .../views/collections/CollectionViewChromes.tsx | 2 + 6 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 src/client/views/collections/CollectionCarouselView.scss create mode 100644 src/client/views/collections/CollectionCarouselView.tsx (limited to 'src') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 04ab514f0..ac643f91f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -74,6 +74,7 @@ export interface DocumentOptions { _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts _textTemplate?: RichTextField; // template used by a formattedTextBox to create a text box to render + _itemIndex?: number; x?: number; y?: number; z?: number; @@ -335,7 +336,7 @@ export namespace Docs { */ export namespace Create { - const delegateKeys = ["x", "y", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn", "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable"]; + const delegateKeys = ["x", "y", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn", "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex"]; /** * This function receives the relevant document prototype and uses @@ -518,6 +519,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Linear }, id); } + export function CarouselDocument(documents: Array, options: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel }); + } + export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, _viewType: CollectionViewType.Schema }); } diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss new file mode 100644 index 000000000..2e0e293b8 --- /dev/null +++ b/src/client/views/collections/CollectionCarouselView.scss @@ -0,0 +1,28 @@ + +.collectionCarouselView-outer { + background: gray; +} +.carouselView-back { + position: absolute; + display: flex; + left: 0; + top: 50%; + width: 30; + height: 30; + background: lightgray; + align-items: center; + border-radius: 5px; + justify-content: center; +} +.carouselView-fwd { + position: absolute; + display: flex; + right: 0; + top: 50%; + width: 30; + height: 30; + background: lightgray; + align-items: center; + border-radius: 5px; + justify-content: center; +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx new file mode 100644 index 000000000..f2cc2479f --- /dev/null +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -0,0 +1,62 @@ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { observable } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { documentSchema } from '../../../new_fields/documentSchemas'; +import { makeInterface } from '../../../new_fields/Schema'; +import { NumCast } from '../../../new_fields/Types'; +import { DragManager } from '../../util/DragManager'; +import { ContentFittingDocumentView } from '../nodes/ContentFittingDocumentView'; +import "./CollectionCarouselView.scss"; +import { CollectionSubView } from './CollectionSubView'; +import { faCaretLeft, faCaretRight } from '@fortawesome/free-solid-svg-icons'; +import { Doc } from '../../../new_fields/Doc'; + + + + +type CarouselDocument = makeInterface<[typeof documentSchema,]>; +const CarouselDocument = makeInterface(documentSchema); + +@observer +export class CollectionCarouselView extends CollectionSubView(CarouselDocument) { + @observable public addMenuToggle = React.createRef(); + private _dropDisposer?: DragManager.DragDropDisposer; + + componentWillUnmount() { + this._dropDisposer && this._dropDisposer(); + } + + componentDidMount() { + } + protected createDashEventsTarget = (ele: HTMLDivElement) => { //used for stacking and masonry view + this._dropDisposer && this._dropDisposer(); + if (ele) { + this._dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this)); + } + } + + render() { + const index = NumCast(this.layoutDoc._itemIndex); + return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : +
+ +
this.layoutDoc._itemIndex = (index - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length}> + +
+
this.layoutDoc._itemIndex = (index + 1) % this.childLayoutPairs.length}> + +
+
; + } +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 2208de264..a54449638 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -632,20 +632,13 @@ export class CollectionTreeView extends CollectionSubView(Document) { } ContextMenu.Instance.addItem({ description: "Buxton Layout", icon: "eye", event: () => { - const { TextDocument, ImageDocument, MulticolumnDocument, TreeDocument } = Docs.Create; + const { TextDocument, ImageDocument, MulticolumnDocument, TreeDocument, CarouselDocument } = Docs.Create; const { Document } = this.props; const fallbackImg = "http://www.cs.brown.edu/~bcz/face.gif"; const detailedTemplate = `{ "doc": { "type": "doc", "content": [ { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "short_description" } } ] }, { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "year" } } ] }, { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] } ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`; const detailedLayout = Docs.Create.StackingDocument([ - ImageDocument(fallbackImg, { title: "activeHero" }), - MulticolumnDocument([], { - title: "data", _height: 100, onChildClick: ScriptField.MakeFunction( - `containingCollection.resolvedDataDoc.activeHero = copyField(this.data); - containingCollection.resolvedDataDoc.activeHero["activeHero-nativeWidth"] = copyField(this.data["data-nativeWidth"]); - containingCollection.resolvedDataDoc.activeHero["activeHero-nativeHeight"] = copyField(this.data["data-nativeHeight"]); - `, { containingCollection: Doc.name }) - }), + CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0 }), TextDocument("", { title: "details", _autoHeight: true, _textTemplate: new RichTextField(detailedTemplate, "short_description year company") }) ], { _chromeStatus: "disabled", title: "detailed layout stack" }); detailedLayout.isTemplateDoc = makeTemplate(detailedLayout); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 338d74ca7..0910e6d40 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -26,6 +26,7 @@ import { Touchable } from '../Touchable'; import { CollectionDockingView } from "./CollectionDockingView"; import { AddCustomFreeFormLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines'; import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView'; +import { CollectionCarouselView } from './CollectionCarouselView'; import { CollectionLinearView } from './CollectionLinearView'; import { CollectionMulticolumnView } from './collectionMulticolumn/CollectionMulticolumnView'; import { CollectionPivotView } from './CollectionPivotView'; @@ -49,6 +50,7 @@ export enum CollectionViewType { Masonry, Pivot, Linear, + Carousel, Staff, Multicolumn, Timeline @@ -64,6 +66,7 @@ export namespace CollectionViewType { ["stacking", CollectionViewType.Stacking], ["masonry", CollectionViewType.Masonry], ["pivot", CollectionViewType.Pivot], + ["carousel", CollectionViewType.Carousel], ["linear", CollectionViewType.Linear], ["multicolumn", CollectionViewType.Multicolumn] ]); @@ -178,6 +181,7 @@ export class CollectionView extends Touchable { case CollectionViewType.Staff: return (); case CollectionViewType.Multicolumn: return (); case CollectionViewType.Linear: { return (); } + case CollectionViewType.Carousel: { return (); } case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Pivot: { return (); } @@ -220,6 +224,7 @@ export class CollectionView extends Touchable { subItems.push({ description: "Staff", event: () => this.props.Document._viewType = CollectionViewType.Staff, icon: "music" }); subItems.push({ description: "Multicolumn", event: () => this.props.Document._viewType = CollectionViewType.Multicolumn, icon: "columns" }); subItems.push({ description: "Masonry", event: () => this.props.Document._viewType = CollectionViewType.Masonry, icon: "columns" }); + subItems.push({ description: "Carousel", event: () => this.props.Document._viewType = CollectionViewType.Carousel, icon: "columns" }); subItems.push({ description: "Pivot", event: () => this.props.Document._viewType = CollectionViewType.Pivot, icon: "columns" }); switch (this.props.Document._viewType) { case CollectionViewType.Freeform: { diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index 94290b5b5..d3ac86070 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -70,6 +70,7 @@ export class CollectionViewBaseChrome extends React.ComponentMasonry View +