aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2020-01-28 18:14:59 -0500
committerbob <bcz@cs.brown.edu>2020-01-28 18:14:59 -0500
commit0361c04360362c31e4bdd5d27b52707b4e288662 (patch)
tree8d2682b9a664c7f4e43ddb240ea135525d0bd416 /src
parentd1ed73e0a0fa3f3da9811edfe3233c663d34cffa (diff)
added captions to carousel. cleaned up some stuff.
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts7
-rw-r--r--src/client/util/RichTextSchema.tsx2
-rw-r--r--src/client/views/collections/CollectionCarouselView.scss12
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx24
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx44
-rw-r--r--src/client/views/collections/CollectionPivotView.tsx5
-rw-r--r--src/client/views/collections/CollectionSubView.tsx6
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx44
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx4
-rw-r--r--src/scraping/buxton/scraper.py20
10 files changed, 116 insertions, 52 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a7f939d7d..e481b1a4a 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -74,7 +74,8 @@ 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;
+ _itemIndex?: number; // which item index the carousel viewer is showing
+ _hideSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts
x?: number;
y?: number;
z?: number;
@@ -127,6 +128,7 @@ export interface DocumentOptions {
color?: string;
treeViewHideTitle?: boolean; // whether to hide the title of a tree view
treeViewOpen?: boolean; // whether this document is expanded in a tree view
+ treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
isFacetFilter?: boolean; // whether document functions as a facet filter in a tree view
limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents
// [key: string]: Opt<Field>;
@@ -336,7 +338,8 @@ export namespace Docs {
*/
export namespace Create {
- const delegateKeys = ["x", "y", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn", "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex"];
+ const delegateKeys = ["x", "y", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn",
+ "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_hideSidebar"];
/**
* This function receives the relevant document prototype and uses
diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx
index 7051ba1c3..f667b86af 100644
--- a/src/client/util/RichTextSchema.tsx
+++ b/src/client/util/RichTextSchema.tsx
@@ -757,7 +757,7 @@ export class DashDocView {
DocServer.GetRefField(node.attrs.docid).then(async dashDoc => {
if (dashDoc instanceof Doc) {
self._dashDoc = dashDoc;
- dashDoc.hideSidebar = true;
+ dashDoc._hideSidebar = true;
if (node.attrs.width !== dashDoc._width + "px" || node.attrs.height !== dashDoc._height + "px") {
try { // bcz: an exception will be thrown if two aliases are open at the same time when a doc view comment is made
view.dispatch(view.state.tr.setNodeMarkup(getPos(), null, { ...node.attrs, width: dashDoc._width + "px", height: dashDoc._height + "px" }));
diff --git a/src/client/views/collections/CollectionCarouselView.scss b/src/client/views/collections/CollectionCarouselView.scss
index 2e0e293b8..4815f1a59 100644
--- a/src/client/views/collections/CollectionCarouselView.scss
+++ b/src/client/views/collections/CollectionCarouselView.scss
@@ -1,6 +1,18 @@
.collectionCarouselView-outer {
background: gray;
+ .collectionCarouselView-caption {
+ margin-left: 10%;
+ margin-right: 10%;
+ height: 50;
+ display: inline-block;
+ width: 80%;
+ }
+ .collectionCarouselView-image {
+ height: calc(100% - 50px);
+ display: inline-block;
+ width: 100%;
+ }
}
.carouselView-back {
position: absolute;
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 815dfb35a..0933d5924 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -4,13 +4,14 @@ 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 { NumCast, StrCast } 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';
+import { FormattedTextBox } from '../nodes/FormattedTextBox';
@@ -45,20 +46,29 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument)
this.layoutDoc._itemIndex = (NumCast(this.layoutDoc._itemIndex) - 1 + this.childLayoutPairs.length) % this.childLayoutPairs.length;
}
+ panelHeight = () => this.props.PanelHeight() - 50;
@computed get content() {
const index = NumCast(this.layoutDoc._itemIndex);
return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) :
- <ContentFittingDocumentView {...this.props}
- Document={this.childLayoutPairs[index].layout}
- DataDocument={this.childLayoutPairs[index].data}
- getTransform={this.props.ScreenToLocalTransform} />
+ <div>
+ <div className="collectionCarouselView-image">
+ <ContentFittingDocumentView {...this.props}
+ Document={this.childLayoutPairs[index].layout}
+ DataDocument={this.childLayoutPairs[index].data}
+ PanelHeight={this.panelHeight}
+ getTransform={this.props.ScreenToLocalTransform} />
+ </div>
+ <div className="collectionCarouselView-caption" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }}>
+ <FormattedTextBox key={index} {...this.props} Document={this.childLayoutPairs[index].layout} DataDoc={undefined} fieldKey={"caption"}></FormattedTextBox>
+ </div>
+ </div>
}
@computed get buttons() {
return <>
- <div key="back" className="carouselView-back" onClick={this.goback}>
+ <div key="back" className="carouselView-back" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.goback}>
<FontAwesomeIcon icon={faCaretLeft} size={"2x"} />
</div>
- <div key="fwd" className="carouselView-fwd" onClick={this.advance}>
+ <div key="fwd" className="carouselView-fwd" style={{ background: `${StrCast(this.props.Document.backgroundColor)}` }} onClick={this.advance}>
<FontAwesomeIcon icon={faCaretRight} size={"2x"} />
</div>
</>;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 8cfaa5951..160279efd 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -174,6 +174,45 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
if (removed) CollectionDockingView.Instance._removedDocs.push(removed);
this.stateChanged();
}
+ @undoBatch
+ @action
+ public static ReplaceRightSplit(document: Doc, dataDoc: Doc | undefined, libraryPath?: Doc[]): boolean {
+ if (!CollectionDockingView.Instance) return false; const instance = CollectionDockingView.Instance;
+ const newItemStackConfig = {
+ type: 'stack',
+ content: [CollectionDockingView.makeDocumentConfig(document, dataDoc, undefined, libraryPath)]
+ };
+
+ const newContentItem = instance._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, instance._goldenLayout);
+
+ let retVal = false;
+ if (instance._goldenLayout.root.contentItems[0].isRow) {
+ retVal = Array.from(instance._goldenLayout.root.contentItems[0].contentItems).some((child: any) => {
+ if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" &&
+ DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)?.Document.isDisplayPanle) {
+ child.contentItems[0].remove();
+ child.addChild(newContentItem, undefined, true);
+ instance.layoutChanged(document);
+ return true;
+ } else {
+ Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => {
+ if (DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)?.Document.isDisplayPanel) {
+ child.contentItems[j].remove();
+ child.addChild(newContentItem, undefined, true);
+ return true;
+ }
+ return false;
+ });
+ }
+ return false;
+ });
+ }
+ if (retVal) {
+ instance.stateChanged();
+ }
+ return retVal;
+ }
+
//
// Creates a vertical split on the right side of the docking view, and then adds the Document to the right of that split
@@ -217,8 +256,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
@action
public static UseRightSplit(document: Doc, dataDoc: Doc | undefined, libraryPath?: Doc[]) {
document.isDisplayPanel = true;
- CollectionDockingView.CloseRightSplit(undefined);
- CollectionDockingView.AddRightSplit(document, dataDoc, libraryPath);
+ if (!CollectionDockingView.ReplaceRightSplit(document, dataDoc, libraryPath)) {
+ CollectionDockingView.AddRightSplit(document, dataDoc, libraryPath);
+ }
}
@undoBatch
diff --git a/src/client/views/collections/CollectionPivotView.tsx b/src/client/views/collections/CollectionPivotView.tsx
index 66c7c9745..6de20593b 100644
--- a/src/client/views/collections/CollectionPivotView.tsx
+++ b/src/client/views/collections/CollectionPivotView.tsx
@@ -9,7 +9,6 @@ import { listSpec } from "../../../new_fields/Schema";
import { ComputedField, ScriptField } from "../../../new_fields/ScriptField";
import { Cast, StrCast } from "../../../new_fields/Types";
import { Docs } from "../../documents/Documents";
-import { CompileScript } from "../../util/Scripting";
import { EditableView } from "../EditableView";
import { anchorPoints, Flyout } from "../TemplateMenu";
import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormView";
@@ -104,9 +103,7 @@ export class CollectionPivotView extends CollectionSubView(doc => doc) {
const flyout = (
<div className="collectionPivotView-flyout" style={{ width: `${this._facetWidth}` }}>
{this._allFacets.map(facet => <label className="collectionPivotView-flyout-item" key={`${facet}`} onClick={e => this.facetClick(facet)}>
- <input type="checkbox" onChange={e => { }} checked={this.props.Document._facetCollection instanceof Doc && DocListCast(this.props.Document._facetCollection.data).some(d => {
- return d.title === facet;
- })} />
+ <input type="checkbox" onChange={e => { }} checked={DocListCast((this.props.Document._facetCollection as Doc)?.data).some(d => d.title === facet)} />
<span className="checkmark" />
{facet}
</label>)}
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 321a6d34c..65d421c52 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -70,10 +70,10 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
(args) => {
const childLayout = Cast(this.props.Document.childLayout, Doc);
if (childLayout instanceof Doc) {
- this.childDocs.map(doc => Doc.ApplyTemplateTo(childLayout, doc, "layoutFromParent"));
+ this.childDocs.map(doc => Doc.ApplyTemplateTo(childLayout, doc, "layout_fromParent"));
}
else if (!(childLayout instanceof Promise)) {
- this.childDocs.filter(d => !d.isTemplateForField).map(doc => doc.layoutKey === "layoutFromParent" && (doc.layoutKey = "layout"));
+ this.childDocs.filter(d => !d.isTemplateForField).map(doc => doc.layoutKey === "layout_fromParent" && (doc.layoutKey = "layout"));
}
}, { fireImmediately: true });
@@ -183,7 +183,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
if (docDragData && !docDragData.applyAsTemplate) {
if (de.altKey && docDragData.draggedDocuments.length) {
this.childDocs.map(doc =>
- Doc.ApplyTemplateTo(docDragData.draggedDocuments[0], doc, "layoutFromParent"));
+ Doc.ApplyTemplateTo(docDragData.draggedDocuments[0], doc, "layout_fromParent"));
e.stopPropagation();
return true;
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 6927f2856..66055d31d 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -34,6 +34,7 @@ import "./CollectionTreeView.scss";
import React = require("react");
import { CollectionViewType } from './CollectionView';
import { RichTextField } from '../../../new_fields/RichTextField';
+import { ObjectField } from '../../../new_fields/ObjectField';
export interface TreeViewProps {
@@ -629,13 +630,23 @@ export class CollectionTreeView extends CollectionSubView(Document) {
}
ContextMenu.Instance.addItem({
description: "Buxton Layout", icon: "eye", event: () => {
- const { TextDocument, ImageDocument, MulticolumnDocument, TreeDocument, CarouselDocument } = Docs.Create;
+ DocListCast(this.dataDoc[this.props.fieldKey]).map(d => {
+ DocListCast(d.data).map((img, i) => {
+ const caption = (d.captions as any)[i]?.data;
+ if (caption instanceof ObjectField) {
+ Doc.GetProto(img).caption = ObjectField.MakeCopy(caption as ObjectField);
+ }
+ img._hideSidebar = true;
+ d.captions = undefined;
+ });
+ });
+ const { TextDocument, ImageDocument, 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([
- CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0 }),
+ CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
TextDocument("", { title: "details", _autoHeight: true, _textTemplate: new RichTextField(detailedTemplate, "short_description year company") })
], { _chromeStatus: "disabled", title: "detailed layout stack" });
detailedLayout.isTemplateDoc = makeTemplate(detailedLayout);
@@ -711,23 +722,18 @@ export class CollectionTreeView extends CollectionSubView(Document) {
}
Scripting.addGlobal(function readFacetData(layoutDoc: Doc, dataDoc: Doc, dataKey: string, facetHeader: string) {
- const facetValues = new Set<string>();
- DocListCast(dataDoc[dataKey]).forEach(child => {
- Object.keys(Doc.GetProto(child)).forEach(key => child[key] instanceof Doc && facetValues.add((child[key] as Doc)[facetHeader]?.toString() || "(null)"));
- facetValues.add(Field.toString(child[facetHeader] as Field));
- });
- const text = "determineCheckedState(layoutDoc, facetHeader, facetValue)";
- const params = {
- layoutDoc: Doc.name,
- facetHeader: "string",
- facetValue: "string"
- };
- const capturedVariables = { layoutDoc, facetHeader };
- return new List<Doc>(Array.from(facetValues).sort().map(facetValue => {
- const value = Docs.Create.TextDocument("", { title: facetValue.toString() });
- value.treeViewChecked = ComputedField.MakeFunction(text, params, { ...capturedVariables, facetValue });
- return value;
- }));
+ const allCollectionDocs = DocListCast(dataDoc[dataKey]);
+ const facetValues = Array.from(allCollectionDocs.reduce((set, child) =>
+ set.add(Field.toString(child[facetHeader] as Field)), new Set<string>()));
+
+ const facetValueDocSet = facetValues.sort().map(facetValue =>
+ Docs.Create.TextDocument("", {
+ title: facetValue.toString(),
+ treeViewChecked: ComputedField.MakeFunction("determineCheckedState(layoutDoc, facetHeader, facetValue)",
+ { layoutDoc: Doc.name, facetHeader: "string", facetValue: "string" },
+ { layoutDoc, facetHeader, facetValue })
+ }));
+ return new List<Doc>(facetValueDocSet);
});
Scripting.addGlobal(function determineCheckedState(layoutDoc: Doc, facetHeader: string, facetValue: string) {
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 5c9f1a754..732bbc976 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -1099,7 +1099,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
<div className={`formattedTextBox-outer`} style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, }} ref={this._scrollRef}>
<div className={`formattedTextBox-inner${rounded}`} style={{ whiteSpace: "pre-wrap", pointerEvents: ((this.Document.isButton || this.props.onClick) && !this.props.isSelected()) ? "none" : undefined }} ref={this.createDropTarget} />
</div>
- {this.props.Document.hideSidebar ? (null) : this.sidebarWidthPercent === "0%" ?
+ {this.props.Document._hideSidebar ? (null) : this.sidebarWidthPercent === "0%" ?
<div className="formattedTextBox-sidebar-handle" onPointerDown={this.sidebarDown} onClick={e => this.toggleSidebar()} /> :
<div className={"formattedTextBox-sidebar" + (InkingControl.Instance.selectedTool !== InkTool.None ? "-inking" : "")}
style={{ width: `${this.sidebarWidthPercent}`, backgroundColor: `${this.sidebarColor}` }}>
@@ -1116,7 +1116,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps &
whenActiveChanged={this.whenActiveChanged}
removeDocument={this.removeDocument}
moveDocument={this.moveDocument}
- addDocument={(doc: Doc) => { doc.hideSidebar = true; return this.addDocument(doc); }}
+ addDocument={(doc: Doc) => { doc._hideSidebar = true; return this.addDocument(doc); }}
CollectionView={undefined}
ScreenToLocalTransform={() => this.props.ScreenToLocalTransform().translate(-(this.props.PanelWidth() - this.sidebarWidth), 0)}
renderDepth={this.props.renderDepth + 1}
diff --git a/src/scraping/buxton/scraper.py b/src/scraping/buxton/scraper.py
index 16b248ae7..7cfa4696d 100644
--- a/src/scraping/buxton/scraper.py
+++ b/src/scraping/buxton/scraper.py
@@ -112,10 +112,6 @@ def write_collection(parse_results, display_fields, storage_key, viewType):
"url": parse_results["image_urls"][0],
"__type": "image"
}
- fields["activeHero"] = {
- "url": parse_results["image_urls"][0],
- "__type": "image"
- }
fields["isPrototype"] = True
fields["page"] = -1
@@ -139,7 +135,7 @@ def write_text_doc(content):
"proto": protofy(data_doc_guid),
"x": 10,
"y": 10,
- "width": 400,
+ "_width": 400,
"zIndex": 2
},
"__type": "Doc"
@@ -154,7 +150,7 @@ def write_text_doc(content):
"__type": "RichTextField"
},
"title": content,
- "nativeWidth": 200,
+ "_nativeWidth": 200,
"author": "Bill Buxton",
"creationDate": {
"date": datetime.datetime.utcnow().microsecond,
@@ -163,8 +159,8 @@ def write_text_doc(content):
"isPrototype": True,
"_autoHeight": True,
"page": -1,
- "nativeHeight": 200,
- "height": 200,
+ "_nativeHeight": 200,
+ "_height": 200,
"data_text": content
},
"__type": "Doc"
@@ -194,7 +190,7 @@ def write_image(folder, name):
"proto": protofy(data_doc_guid),
"x": 10,
"y": 10,
- "width": min(800, native_width),
+ "_width": min(800, native_width),
"zIndex": 2,
"widthUnit": "*",
"widthMagnitude": 1
@@ -211,7 +207,7 @@ def write_image(folder, name):
"__type": "image"
},
"title": name,
- "nativeWidth": native_width,
+ "_nativeWidth": native_width,
"author": "Bill Buxton",
"creationDate": {
"date": datetime.datetime.utcnow().microsecond,
@@ -219,8 +215,8 @@ def write_image(folder, name):
},
"isPrototype": True,
"page": -1,
- "nativeHeight": native_height,
- "height": native_height
+ "_nativeHeight": native_height,
+ "_height": native_height
},
"__type": "Doc"
}