diff options
-rw-r--r-- | src/client/documents/Documents.ts | 8 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 20 | ||||
-rw-r--r-- | src/client/views/TemplateMenu.tsx | 13 | ||||
-rw-r--r-- | src/client/views/Templates.tsx | 55 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 37 | ||||
-rw-r--r-- | src/fields/KeyStore.ts | 4 | ||||
-rw-r--r-- | src/fields/TemplateField.ts | 35 | ||||
-rw-r--r-- | src/server/Message.ts | 2 | ||||
-rw-r--r-- | src/server/ServerUtil.ts | 3 |
9 files changed, 92 insertions, 85 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8db1a1c6d..eba53273f 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -32,6 +32,8 @@ import { action } from "mobx"; import { ColumnAttributeModel } from "../northstar/core/attribute/AttributeModel"; import { AttributeTransformationModel } from "../northstar/core/attribute/AttributeTransformationModel"; import { AggregateFunction } from "../northstar/model/idea/idea"; +import { Template } from "../views/Templates"; +import { TemplateField } from "../../fields/TemplateField"; export interface DocumentOptions { x?: number; @@ -46,7 +48,9 @@ export interface DocumentOptions { pany?: number; page?: number; scale?: number; + baseLayout?: string; layout?: string; + template?: Template; layoutKeys?: Key[]; viewType?: number; backgroundColor?: string; @@ -95,7 +99,9 @@ export namespace Documents { if (options.viewType !== undefined) { doc.SetNumber(KeyStore.ViewType, options.viewType); } if (options.backgroundColor !== undefined) { doc.SetText(KeyStore.BackgroundColor, options.backgroundColor); } if (options.ink !== undefined) { doc.Set(KeyStore.Ink, new InkField(options.ink)); } + if (options.baseLayout !== undefined) { doc.SetText(KeyStore.BaseLayout, options.baseLayout); } if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); } + if (options.template !== undefined) { doc.Set(KeyStore.Template, new TemplateField(options.template)); } if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); } if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); } return doc; @@ -112,7 +118,7 @@ export namespace Documents { } function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document { - return assignOptions(new Document(protoId), { ...options, title: title, layout: layout }); + return assignOptions(new Document(protoId), { ...options, title: title, layout: layout , baseLayout: layout}); } function SetInstanceOptions<T, U extends Field & { Data: T }>(doc: Document, options: DocumentOptions, value: [T, { new(): U }] | Document, id?: string) { var deleg = doc.MakeDelegate(id); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 3dcdc596d..2a40d7347 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -17,25 +17,11 @@ import { LinkMenu } from "./nodes/LinkMenu"; import { TemplateMenu } from "./TemplateMenu"; import React = require("react"); import { Template, Templates } from "./Templates"; +import { TemplateField } from "../../fields/TemplateField"; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; -// @observer -// class TemplateToggle extends React.Component<{ template: Template, checked: boolean, toggle: (event: React.ChangeEvent<HTMLInputElement>, template: Template) => void }> { -// render() { -// if (this.props.template) { -// return ( -// <li> -// <input type="checkbox" checked={this.props.checked} onChange={(event) => this.props.toggle(event, this.props.template)} /> -// {this.props.template.Name} -// </li> -// ) -// } -// return (null); -// } -// } - @observer export class DocumentDecorations extends React.Component<{}, { value: string }> { static Instance: DocumentDecorations; @@ -409,8 +395,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> let templates: Map<Template, boolean> = new Map(); let doc = SelectionManager.SelectedDocuments()[0]; Array.from(Object.values(Templates)).map(template => { - templates.set(template, doc.Template === template); + templates.set(template, doc.template.Name === template.Name); }); + // let docSrc = doc.props.Document.GetT(KeyStore.Prototype, TemplateField); + // console.log(docSrc); return (<div className="documentDecorations"> <div className="documentDecorations-background" style={{ diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 0c8ae7055..1e83463c8 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -33,14 +33,11 @@ export interface TemplateMenuProps { export class TemplateMenu extends React.Component<TemplateMenuProps> { @observable private _hidden: boolean = true; - @observable private _useBase: boolean = true; @observable private _templates: Map<Template, boolean> = this.props.templates; @action toggleTemplate = (event: React.ChangeEvent<HTMLInputElement>, template: Template): void => { - this._useBase = false; - this.props.doc.toggleBase(false); this.props.doc.changeTemplate(template); this._templates.forEach((checked, temp) => { this._templates.set(temp, false); @@ -58,15 +55,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { } @action - toggleBase = (event: React.MouseEvent): void => { - this._useBase = true; - this.props.doc.toggleBase(true); - this._templates.forEach((checked, temp) => { - this._templates.set(temp, false); - }); - } - - @action toggleTemplateActivity = (): void => { this._hidden = !this._hidden; } @@ -81,7 +69,6 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> { <div className="templating-menu" > <div className="templating-button" onClick={() => this.toggleTemplateActivity()}>T</div> <ul id="template-list" style={{ display: this._hidden ? "none" : "block" }}> - <li><input type="checkbox" onClick={(event) => this.toggleBase(event)} checked={this._useBase} />Base layout</li> {templateMenu} </ul> </div> diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index c22b22286..3afdc711c 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -24,39 +24,34 @@ export class Template { } export namespace Templates { + export const BasicLayout = new Template("Basic layout", "{layout}"); + export const OuterCaption = new Template("Outer caption", - ` - <div> - <div style="margin:auto; height:calc(100%); width:100%;"> - {layout} - </div> - <div style="height:(100% + 25px); width:100%; position:absolute"> - <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/> - </div> - </div> - `); + `<div><div style="margin:auto; height:calc(100%); width:100%;">{layout}</div><div style="height:(100% + 50px); width:100%; position:absolute"><FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/></div></div>` + ); + export const InnerCaption = new Template("Inner caption", - ` - <div> - <div style="margin:auto; height:calc(100% - 25px); width:100%;"> - {layout} - </div> - <div style="height:25px; width:100%; position:absolute"> - <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/> - </div> - </div> - `); + `<div> + <div style="margin:auto; height:calc(100% - 50px); width:100%;"> + {layout} + </div> + <div style="height:50px; width:100%; position:absolute"> + <FormattedTextBox doc={Document} DocumentViewForField={DocumentView} bindings={bindings} fieldKey={CaptionKey} isSelected={isSelected} select={select} selectOnLoad={SelectOnLoad} isTopMost={isTopMost}/> + </div> + </div>` + ); export const Title = new Template("Title", - ` - <div> - <div style="margin:auto; height:calc(100% - 50px); width:100%;"> - {layout} - </div> - <div style="height:50px; width:100%; position:absolute"> - {Title} - </div> - </div> - `); + `<div> + <div style="margin:auto; height:calc(100% - 50px); width:100%;"> + {layout} + </div> + <div style="height:50px; width:100%; position:absolute; background-color: rgba(0, 0, 0, .6); color: white; padding:12px"> + {Title} + </div> + </div>` + ); + + } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 12332348b..440269e36 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -21,9 +21,10 @@ import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; import { DocumentContentsView } from "./DocumentContentsView"; -import { Template } from "./../Templates"; +import { Template, Templates } from "./../Templates"; import "./DocumentView.scss"; import React = require("react"); +import { TemplateField } from "../../../fields/TemplateField"; export interface DocumentViewProps { @@ -92,13 +93,19 @@ export class DocumentView extends React.Component<DocumentViewProps> { } private _downX: number = 0; private _downY: number = 0; - private _base: string = this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); - @observable private _template: Template = new Template("", ""); + @computed get base(): string { return this.props.Document.GetText(KeyStore.BaseLayout, "<p>Error loading base layout data</p>"); } @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); } @computed get topMost(): boolean { return this.props.isTopMost; } @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "<p>Error loading layout data</p>"); } @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array<Key>()); } @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array<Key>()); } + @computed get template(): Template { + let field = this.props.Document.GetT(KeyStore.Template, TemplateField); + return !field || field === FieldWaiting ? Templates.BasicLayout : field.Data; + } + set template(template: Template) { + this.props.Document.SetData(KeyStore.Template, template, TemplateField); + } screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect(); onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; @@ -303,33 +310,17 @@ export class DocumentView extends React.Component<DocumentViewProps> { } updateLayout = (): void => { - if (this._template.Name === "") { - this.props.Document.SetText(KeyStore.Layout, this._base); - } else { - let temp = this._template.Layout; - let layout = temp.replace("{layout}", this._base); - this.props.Document.SetText(KeyStore.Layout, layout); - } - } - - @action - toggleBase = (useBase: boolean) => { - if (useBase) { - this._template = new Template("", ""); - } - this.updateLayout(); + let temp = this.template.Layout; + let layout = temp.replace("{layout}", this.base); + this.props.Document.SetText(KeyStore.Layout, layout); } @action changeTemplate = (template: Template) => { - this._template = template; + this.template = template; this.updateLayout(); } - get Template() { - return this._template; - } - @action onContextMenu = (e: React.MouseEvent): void => { e.stopPropagation(); diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts index 16a909eb8..1602c3776 100644 --- a/src/fields/KeyStore.ts +++ b/src/fields/KeyStore.ts @@ -19,7 +19,9 @@ export namespace KeyStore { export const Data = new Key("Data"); export const Annotations = new Key("Annotations"); export const ViewType = new Key("ViewType"); + export const BaseLayout = new Key("BaseLayout"); export const Layout = new Key("Layout"); + export const Template = new Key("Template"); export const BackgroundColor = new Key("BackgroundColor"); export const BackgroundLayout = new Key("BackgroundLayout"); export const OverlayLayout = new Key("OverlayLayout"); @@ -49,7 +51,7 @@ export namespace KeyStore { export const CopyDraggedItems = new Key("CopyDraggedItems"); export const KeyList: Key[] = [Prototype, X, Y, Page, Title, Author, PanX, PanY, Scale, NativeWidth, NativeHeight, - Width, Height, ZIndex, Zoom, Data, Annotations, ViewType, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, + Width, Height, ZIndex, Zoom, Data, Annotations, ViewType, BaseLayout, Layout, BackgroundColor, BackgroundLayout, OverlayLayout, LayoutKeys, LayoutFields, ColumnsKey, SchemaSplitPercentage, Caption, ActiveWorkspace, DocumentText, BrushingDocs, LinkedToDocs, LinkedFromDocs, LinkDescription, LinkTags, Thumbnail, ThumbnailPage, CurPage, AnnotationOn, NumPages, Ink, Cursors, OptionalRightCollection, Archives, Workspaces, Minimized, CopyDraggedItems diff --git a/src/fields/TemplateField.ts b/src/fields/TemplateField.ts new file mode 100644 index 000000000..bc1e67d7b --- /dev/null +++ b/src/fields/TemplateField.ts @@ -0,0 +1,35 @@ +import { BasicField } from "./BasicField"; +import { Types } from "../server/Message"; +import { FieldId } from "./Field"; +import { Template, Templates } from "../client/views/Templates"; + + +export class TemplateField extends BasicField<Template> { + constructor(data: Template = Templates.BasicLayout, id?: FieldId, save: boolean = true) { + super(data, save, id); + } + + ToScriptString(): string { + return `new TemplateField("${this.Data}")`; + } + + Copy() { + return new TemplateField(this.Data); + } + + ToJson() { + return { + type: Types.Template, + data: this.Data, + id: this.Id, + }; + } + + UpdateFromServer(data: any) { + this.data = new Template(data.Name, data.layout); + } + + static FromJson(id: string, data: any): TemplateField { + return new TemplateField(new Template(data._name, data._layout), id, false); + } +}
\ No newline at end of file diff --git a/src/server/Message.ts b/src/server/Message.ts index bbe4ffcad..4a8812956 100644 --- a/src/server/Message.ts +++ b/src/server/Message.ts @@ -15,7 +15,7 @@ export class Message<T> { export enum Types { Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, - Html, Video, Audio, Ink, PDF, Tuple, HistogramOp, Boolean, Script, + Html, Video, Audio, Ink, PDF, Tuple, HistogramOp, Boolean, Script, Template } export interface Transferable { diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts index 818230c1a..a2256bca7 100644 --- a/src/server/ServerUtil.ts +++ b/src/server/ServerUtil.ts @@ -18,6 +18,8 @@ import { NumberField } from "./../fields/NumberField"; import { RichTextField } from "./../fields/RichTextField"; import { TextField } from "./../fields/TextField"; import { Transferable, Types } from "./Message"; +import { Template } from "../client/views/Templates"; +import { TemplateField } from "../fields/TemplateField"; export class ServerUtils { public static prepend(extension: string): string { @@ -50,6 +52,7 @@ export class ServerUtils { case Types.Video: return new VideoField(new URL(json.data), json.id, false); case Types.Tuple: return new TupleField(json.data, json.id, false); case Types.Ink: return InkField.FromJson(json.id, json.data); + case Types.Template: return TemplateField.FromJson(json.id, json.data); case Types.Document: return Document.FromJson(json.data, json.id, false); default: throw Error( |