aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Wilkins <samwilkins333@gmail.com>2020-04-26 19:29:50 -0700
committerSam Wilkins <samwilkins333@gmail.com>2020-04-26 19:29:50 -0700
commitc75ffd4900acea74c55b6bf275a5e8082c15d573 (patch)
treeb8cedbc9da3061e13ab321d3a86134e41690b8be /src
parent63985ba64dc4a3a94bac75a9120cd8a5ca791fec (diff)
formatted textbox disposers refactor, paragraph chunked rich text initialization and buxton importer updates
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts1
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx21
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx60
-rw-r--r--src/scraping/buxton/final/BuxtonImporter.ts17
4 files changed, 49 insertions, 50 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 1268c97b0..6bd2eee3c 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -407,6 +407,7 @@ export namespace Docs {
const doc = StackingDocument(deviceImages, { title: device.title, _LODdisable: true });
const deviceProto = Doc.GetProto(doc);
deviceProto.hero = new ImageField(constructed[0].url);
+ deviceProto.fontFamily = "Arial";
Docs.Get.FromJson({ data: device, appendToExisting: { targetDoc: deviceProto } });
Doc.AddDocToList(parentProto, "data", doc);
} else if (errors) {
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 7f5dc98f1..49eb90bc2 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -730,18 +730,31 @@ export class CollectionTreeView extends CollectionSubView<Document, Partial<coll
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": "year" } } ] }, { "type": "paragraph", "content": [ { "type": "dashField", "attrs": { "fieldKey": "company" } } ] } ] }, "selection":{"type":"text","anchor":1,"head":1},"storedMarks":[] }`;
const textDoc = TextDocument("", { title: "details", _autoHeight: true });
const detailView = Docs.Create.StackingDocument([
CarouselDocument([], { title: "data", _height: 350, _itemIndex: 0, backgroundColor: "#9b9b9b3F" }),
- // textDoc,
+ textDoc,
TextDocument("", { title: "shortDescription", _autoHeight: true }),
- // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
TextDocument("", { title: "longDescription", _height: 350 })
+ // TreeDocument([], { title: "narratives", _height: 75, treeViewHideTitle: true }),
], { _chromeStatus: "disabled", _width: 300, _height: 300, _autoHeight: true, title: "detailView" });
- textDoc.data = new RichTextField(detailedTemplate, "year company");
+ // const detailView = Cast(Cast(Doc.UserDoc()["template-button-detail"], Doc, null)?.dragFactor, Doc, null);
detailView.isTemplateDoc = makeTemplate(detailView);
+ detailView.fontFamily = "Arial";
+
+ const buxtonFieldKeys = ["year", "originalPrice", "degreesOfFreedom", "company", "attribute", "primaryKey", "secondaryKey", "dimensions"];
+ const detailedTemplate = {
+ doc: {
+ type: "doc", content: buxtonFieldKeys.map(fieldKey => ({
+ type: "paragraph",
+ content: [{ type: "dashField", attrs: { fieldKey } }]
+ }))
+ },
+ selection: { type: "text", anchor: 1, head: 1 },
+ storedMarks: []
+ };
+ textDoc.data = new RichTextField(JSON.stringify(detailedTemplate), buxtonFieldKeys.join(" "));
const heroView = ImageDocument(fallbackImg, { title: "heroView", isTemplateDoc: true, isTemplateForField: "hero", }); // this acts like a template doc and a template field ... a little weird, but seems to work?
heroView.proto!.layout = ImageBox.LayoutString("hero");
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 425af8ccf..dd0df9f3f 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -83,17 +83,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
private _lastX = 0;
private _lastY = 0;
private _undoTyping?: UndoManager.Batch;
- private _searchReactionDisposer?: Lambda;
- private _recordReactionDisposer: Opt<IReactionDisposer>;
- private _scrollToRegionReactionDisposer: Opt<IReactionDisposer>;
- private _reactionDisposer: Opt<IReactionDisposer>;
- private _heightReactionDisposer: Opt<IReactionDisposer>;
- private _proxyReactionDisposer: Opt<IReactionDisposer>;
- private _pullReactionDisposer: Opt<IReactionDisposer>;
- private _pushReactionDisposer: Opt<IReactionDisposer>;
- private _buttonBarReactionDisposer: Opt<IReactionDisposer>;
- private _linkMakerDisposer: Opt<IReactionDisposer>;
- private _scrollDisposer: Opt<IReactionDisposer>;
+ private _disposers: { [name: string]: IReactionDisposer } = {};
private dropDisposer?: DragManager.DragDropDisposer;
@computed get _recording() { return this.dataDoc.audioState === "recording"; }
@@ -564,7 +554,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
componentDidMount() {
- this._buttonBarReactionDisposer = reaction(
+ this._disposers.buttonBar = reaction(
() => DocumentButtonBar.Instance,
instance => {
if (instance) {
@@ -573,7 +563,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
);
- this._linkMakerDisposer = reaction(
+ this._disposers.linkMaker = reaction(
() => this.props.makeLink?.(),
(linkDoc: Opt<Doc>) => {
if (linkDoc) {
@@ -584,8 +574,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
},
{ fireImmediately: true }
);
-
- this._reactionDisposer = reaction(
+ this._disposers.editorState = reaction(
() => {
if (this.dataDoc[this.props.fieldKey + "-noTemplate"] || !this.props.Document[this.props.fieldKey + "-textTemplate"]) {
return Cast(this.dataDoc[this.props.fieldKey], RichTextField, null)?.Data;
@@ -600,8 +589,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
);
-
- this._pullReactionDisposer = reaction(
+ this._disposers.pullDoc = reaction(
() => this.props.Document[Pulls],
() => {
if (!DocumentButtonBar.hasPulledHack) {
@@ -611,8 +599,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
);
-
- this._pushReactionDisposer = reaction(
+ this._disposers.pushDoc = reaction(
() => this.props.Document[Pushes],
() => {
if (!DocumentButtonBar.hasPushedHack) {
@@ -621,19 +608,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
);
-
- this._heightReactionDisposer = reaction(
+ this._disposers.height = reaction(
() => [this.layoutDoc[WidthSym](), this.layoutDoc._autoHeight],
() => this.tryUpdateHeight()
);
this.setupEditor(this.config, this.props.fieldKey);
- this._searchReactionDisposer = reaction(() => this.rootDoc.searchMatch,
+ this._disposers.search = reaction(() => this.rootDoc.searchMatch,
search => search ? this.highlightSearchTerms([Doc.SearchQuery()]) : this.unhighlightSearchTerms(),
{ fireImmediately: true });
- this._recordReactionDisposer = reaction(() => this._recording,
+ this._disposers.record = reaction(() => this._recording,
() => {
if (this._recording) {
setTimeout(action(() => {
@@ -643,8 +629,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
} else setTimeout(() => this.stopDictation(true), 0);
}
);
-
- this._scrollToRegionReactionDisposer = reaction(
+ this._disposers.scrollToRegion = reaction(
() => StrCast(this.layoutDoc.scrollToLinkID),
async (scrollToLinkID) => {
const findLinkFrag = (frag: Fragment, editor: EditorView) => {
@@ -689,8 +674,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
},
{ fireImmediately: true }
);
-
- this._scrollDisposer = reaction(() => NumCast(this.props.Document.scrollPos),
+ this._disposers.scroll = reaction(() => NumCast(this.props.Document.scrollPos),
pos => this._scrollRef.current && this._scrollRef.current.scrollTo({ top: pos }), { fireImmediately: true }
);
@@ -876,7 +860,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
});
const startupText = !rtfField && this._editorView && Field.toString(this.dataDoc[fieldKey] as Field);
if (startupText) {
- this._editorView.dispatch(this._editorView.state.tr.insertText(startupText));
+ const paragraphSegments = startupText.split("\n\n");
+ const { state: { tr }, dispatch } = this._editorView;
+ if (paragraphSegments.length) {
+ for (const paragraph of paragraphSegments) {
+ dispatch(tr.insertText(paragraph));
+ }
+ } else {
+ dispatch(tr.insertText(startupText));
+ }
}
}
@@ -906,17 +898,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
componentWillUnmount() {
- this._scrollDisposer?.();
- this._scrollToRegionReactionDisposer?.();
- this._reactionDisposer?.();
- this._proxyReactionDisposer?.();
- this._pushReactionDisposer?.();
- this._pullReactionDisposer?.();
- this._heightReactionDisposer?.();
- this._searchReactionDisposer?.();
- this._recordReactionDisposer?.();
- this._buttonBarReactionDisposer?.();
- this._linkMakerDisposer?.();
+ Object.values(this._disposers).forEach(disposer => disposer?.());
this._editorView?.destroy();
}
diff --git a/src/scraping/buxton/final/BuxtonImporter.ts b/src/scraping/buxton/final/BuxtonImporter.ts
index 122415460..64b988610 100644
--- a/src/scraping/buxton/final/BuxtonImporter.ts
+++ b/src/scraping/buxton/final/BuxtonImporter.ts
@@ -16,6 +16,7 @@ interface DocumentContents {
hyperlinks: string[];
captions: string[];
embeddedFileNames: string[];
+ longDescriptionParagraphs: string[];
}
export interface DeviceDocument {
@@ -186,10 +187,6 @@ const RegexMap = new Map<keyof DeviceDocument, Processor<any>>([
exp: /Short Description:\s+(.*)Bill Buxton[’']s Notes/,
transformer: Utilities.correctSentences
}],
- ["longDescription", {
- exp: /Bill Buxton[’']s Notes(.*)Device Details/,
- transformer: Utilities.correctSentences
- }],
]);
const sourceDir = path.resolve(__dirname, "source");
@@ -267,7 +264,12 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
const body = document.root()?.text() ?? "No body found. Check the import script's XML parser.";
const captions: string[] = [];
const embeddedFileNames: string[] = [];
- const captionTargets = document.find(tableCellXPath).map(node => node.text());
+ const captionTargets = document.find(tableCellXPath).map(node => node.text().trim());
+
+ const paragraphs = document.find('//*[name()="w:p"]').map(node => Utilities.correctSentences(node.text()).transformed!);
+ const start = paragraphs.indexOf(paragraphs.find(el => /Bill Buxton[’']s Notes/.test(el))!) + 1;
+ const end = paragraphs.indexOf("Device Details");
+ const longDescriptionParagraphs = paragraphs.slice(start, end);
const { length } = captionTargets;
strictEqual(length > 3, true, "No captions written.");
@@ -290,7 +292,7 @@ async function extractFileContents(pathToDocument: string): Promise<DocumentCont
zip.close();
- return { body, imageData, captions, embeddedFileNames, hyperlinks };
+ return { body, longDescriptionParagraphs, imageData, captions, embeddedFileNames, hyperlinks };
}
const imageEntry = /^word\/media\/\w+\.(jpeg|jpg|png|gif)/;
@@ -337,7 +339,7 @@ async function writeImages(zip: any): Promise<ImageData[]> {
}
function analyze(fileName: string, contents: DocumentContents): AnalysisResult {
- const { body, imageData, captions, hyperlinks, embeddedFileNames } = contents;
+ const { body, imageData, captions, hyperlinks, embeddedFileNames, longDescriptionParagraphs } = contents;
const device: any = {
hyperlinks,
captions,
@@ -376,6 +378,7 @@ function analyze(fileName: string, contents: DocumentContents): AnalysisResult {
return { errors };
}
+ device.longDescription = longDescriptionParagraphs.join("\n\n");
return { device };
}