aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/documents/Documents.ts6
-rw-r--r--src/client/views/DocumentDecorations.tsx14
-rw-r--r--src/client/views/TemplateMenu.tsx18
-rw-r--r--src/client/views/Templates.tsx61
-rw-r--r--src/client/views/nodes/DocumentView.tsx43
-rw-r--r--src/fields/KeyStore.ts2
-rw-r--r--src/fields/TemplateField.ts22
-rw-r--r--src/server/Message.ts2
-rw-r--r--src/server/ServerUtil.ts3
9 files changed, 106 insertions, 65 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index eba53273f..c93e65edb 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -50,7 +50,7 @@ export interface DocumentOptions {
scale?: number;
baseLayout?: string;
layout?: string;
- template?: Template;
+ templates?: Array<Template>;
layoutKeys?: Key[];
viewType?: number;
backgroundColor?: string;
@@ -101,7 +101,7 @@ export namespace Documents {
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.templates !== undefined) { doc.Set(KeyStore.Templates, new TemplateField(options.templates)); }
if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); }
if (options.copyDraggedItems !== undefined) { doc.SetBoolean(KeyStore.CopyDraggedItems, options.copyDraggedItems); }
return doc;
@@ -118,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 , baseLayout: 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 2a40d7347..2b22d9e19 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -17,7 +17,6 @@ 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;
@@ -394,11 +393,16 @@ 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.Name === template.Name);
+ Array.from(Object.values(Templates.TemplateList)).map(template => {
+ let docTemps = doc.templates;
+ let checked = false;
+ docTemps.forEach(temp => {
+ if (template.Name === temp.Name) {
+ checked = true;
+ }
+ });
+ templates.set(template, checked);
});
- // 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 1e83463c8..8eb2fc6c6 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -38,15 +38,13 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
@action
toggleTemplate = (event: React.ChangeEvent<HTMLInputElement>, template: Template): void => {
- this.props.doc.changeTemplate(template);
- this._templates.forEach((checked, temp) => {
- this._templates.set(temp, false);
- });
- this._templates.set(template, true);
-
- // const docs = view.props.ContainingCollectionView;
- // const docs = view.props.Document.GetList<Document>(view.props.fieldKey, []);
-
+ if (event.target.checked) {
+ this.props.doc.addTemplate(template);
+ this._templates.set(template, true);
+ } else {
+ this.props.doc.removeTemplate(template);
+ this._templates.set(template, false);
+ }
}
@action
@@ -67,7 +65,7 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
return (
<div className="templating-menu" >
- <div className="templating-button" onClick={() => this.toggleTemplateActivity()}>T</div>
+ <div className="templating-button" onClick={() => this.toggleTemplateActivity()}>+</div>
<ul id="template-list" style={{ display: this._hidden ? "none" : "block" }}>
{templateMenu}
</ul>
diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx
index 3afdc711c..616bc2566 100644
--- a/src/client/views/Templates.tsx
+++ b/src/client/views/Templates.tsx
@@ -1,57 +1,66 @@
-import { observer } from "mobx-react";
-import { observable } from "mobx";
-import { action, computed } from "mobx";
import React = require("react");
-import { StringLiteral } from "babel-types";
+
+export enum TemplatePosition {
+ InnerTop,
+ InnerBottom,
+ InnerRight,
+ InnerLeft,
+ OutterTop,
+ OutterBottom,
+ OutterRight,
+ OutterLeft,
+}
export class Template {
- constructor(name: string, layout: string) {
+ constructor(name: string, position: TemplatePosition, layout: string) {
this._name = name;
+ this._position = position;
this._layout = layout;
}
private _name: string;
+ private _position: TemplatePosition;
private _layout: string;
get Name(): string {
return this._name;
}
+ get Position(): TemplatePosition {
+ return this._position;
+ }
+
get Layout(): string {
return this._layout;
}
-
}
export namespace Templates {
- export const BasicLayout = new Template("Basic layout", "{layout}");
+ // export const BasicLayout = new Template("Basic layout", "{layout}");
- export const OuterCaption = new Template("Outer caption",
+ export const OuterCaption = new Template("Outer caption", TemplatePosition.OutterBottom,
`<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% - 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 InnerCaption = new Template("Inner caption", TemplatePosition.InnerBottom,
+ `<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; background-color: rgba(0, 0, 0, .6); color: white; padding:12px">
- {Title}
- </div>
- </div>`
+ export const SideCaption = new Template("Side caption", TemplatePosition.OutterRight,
+ `<div><div style="margin:auto; height:100%; width:100%;">{layout}</div><div style="height:100%; width:300px; position:absolute; top: 0; right: -300px;"><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", TemplatePosition.InnerTop,
+ `<div><div style="margin:auto; height:calc(100% - 50px); width:100%;">{layout}</div><div style="height:50px; width:100%; position:absolute; top: 0; background-color: rgba(0, 0, 0, .6); color: white; padding:12px">{Title}</div></div>`
+ );
+
+ export const TemplateList: Template[] = [Title, OuterCaption, InnerCaption, SideCaption];
+
+ export function sortTemplates(a: Template, b: Template) {
+ if (a.Position < b.Position) { return -1; }
+ if (a.Position > b.Position) { return 1; }
+ return 0;
+ }
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 440269e36..e851bc9c5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -99,13 +99,11 @@ export class DocumentView extends React.Component<DocumentViewProps> {
@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);
+ @computed get templates(): Array<Template> {
+ let field = this.props.Document.GetT(KeyStore.Templates, TemplateField);
+ return !field || field === FieldWaiting ? [] : field.Data;
}
+ set templates(templates: Array<Template>) { this.props.Document.SetData(KeyStore.Templates, templates, TemplateField); }
screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect();
onPointerDown = (e: React.PointerEvent): void => {
this._downX = e.clientX;
@@ -310,14 +308,39 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
updateLayout = (): void => {
- let temp = this.template.Layout;
- let layout = temp.replace("{layout}", this.base);
+ let base = this.base;
+ let layout = this.base;
+
+ this.templates.forEach(template => {
+ let temp = template.Layout;
+ layout = temp.replace("{layout}", base);
+ base = layout;
+ });
+
this.props.Document.SetText(KeyStore.Layout, layout);
}
@action
- changeTemplate = (template: Template) => {
- this.template = template;
+ addTemplate = (template: Template) => {
+ let templates = this.templates;
+ templates.push(template);
+ templates = templates.splice(0, templates.length).sort(Templates.sortTemplates);
+ this.templates = templates;
+ this.updateLayout();
+ }
+
+ @action
+ removeTemplate = (template: Template) => {
+ let templates = this.templates;
+ for (let i = 0; i < templates.length; i++) {
+ let temp = templates[i];
+ if (temp.Name === template.Name) {
+ templates.splice(i, 1);
+ break;
+ }
+ }
+ templates = templates.splice(0, templates.length).sort(Templates.sortTemplates);
+ this.templates = templates;
this.updateLayout();
}
diff --git a/src/fields/KeyStore.ts b/src/fields/KeyStore.ts
index 1602c3776..5bd402890 100644
--- a/src/fields/KeyStore.ts
+++ b/src/fields/KeyStore.ts
@@ -21,7 +21,7 @@ export namespace KeyStore {
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 Templates = new Key("Templates");
export const BackgroundColor = new Key("BackgroundColor");
export const BackgroundLayout = new Key("BackgroundLayout");
export const OverlayLayout = new Key("OverlayLayout");
diff --git a/src/fields/TemplateField.ts b/src/fields/TemplateField.ts
index bc1e67d7b..72ae13c2e 100644
--- a/src/fields/TemplateField.ts
+++ b/src/fields/TemplateField.ts
@@ -1,11 +1,11 @@
import { BasicField } from "./BasicField";
import { Types } from "../server/Message";
import { FieldId } from "./Field";
-import { Template, Templates } from "../client/views/Templates";
+import { Template, TemplatePosition } from "../client/views/Templates";
-export class TemplateField extends BasicField<Template> {
- constructor(data: Template = Templates.BasicLayout, id?: FieldId, save: boolean = true) {
+export class TemplateField extends BasicField<Array<Template>> {
+ constructor(data: Array<Template> = [], id?: FieldId, save: boolean = true) {
super(data, save, id);
}
@@ -18,18 +18,26 @@ export class TemplateField extends BasicField<Template> {
}
ToJson() {
+ let templates: Array<{ name: string, position: TemplatePosition, layout: string }> = [];
+ this.Data.forEach(template => {
+ templates.push({ name: template.Name, layout: template.Layout, position: template.Position });
+ });
return {
- type: Types.Template,
- data: this.Data,
+ type: Types.Templates,
+ data: templates,
id: this.Id,
};
}
UpdateFromServer(data: any) {
- this.data = new Template(data.Name, data.layout);
+ this.data = new Array(data);
}
static FromJson(id: string, data: any): TemplateField {
- return new TemplateField(new Template(data._name, data._layout), id, false);
+ let templates: Array<Template> = [];
+ data.forEach((template: { name: string, position: number, layout: string }) => {
+ templates.push(new Template(template.name, template.position, template.layout));
+ });
+ return new TemplateField(templates, id, false);
}
} \ No newline at end of file
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 4a8812956..00a30b329 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, Template
+ Html, Video, Audio, Ink, PDF, Tuple, HistogramOp, Boolean, Script, Templates
}
export interface Transferable {
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index a2256bca7..a10bdd5e6 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -18,7 +18,6 @@ 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 {
@@ -52,7 +51,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.Templates: return TemplateField.FromJson(json.id, json.data);
case Types.Document: return Document.FromJson(json.data, json.id, false);
default:
throw Error(