aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/documents/Documents.ts10
-rw-r--r--src/client/util/CurrentUserUtils.ts64
-rw-r--r--src/client/util/LinkManager.ts123
-rw-r--r--src/client/views/Main.tsx3
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx2
-rw-r--r--src/fields/Doc.ts2
6 files changed, 104 insertions, 100 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 84e6258ac..3780df5b9 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -105,7 +105,6 @@ export class DocumentOptions {
userColor?: STRt = new StrInfo("color associated with a Dash user (seen in header fields of shared documents)");
color?: STRt = new StrInfo("foreground color data doc");
backgroundColor?: STRt = new StrInfo("background color for data doc");
- _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)");
_autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents");
_headerHeight?: NUMt = new NumInfo("height of document header used for displaying title");
_headerFontSize?: NUMt = new NumInfo("font size of header of custom notes");
@@ -328,6 +327,7 @@ export class DocumentOptions {
text?: string;
textTransform?: string; // is linear view expanded
letterSpacing?: string; // is linear view expanded
+ iconTemplate?: string; // name of icon template style
selectedIndex?: number; // which item in a linear view has been selected using the "thumb doc" ui
clipboard?: Doc;
searchQuery?: string; // for quersyBox
@@ -1288,9 +1288,7 @@ export namespace DocUtils {
const batch = UndoManager.StartBatch("makeCustomViewClicked");
runInAction(() => {
doc.layoutKey = "layout_" + templateSignature;
- if (doc[doc.layoutKey] === undefined) {
- createCustomView(doc, creator, templateSignature, docLayoutTemplate);
- }
+ createCustomView(doc, creator, templateSignature, docLayoutTemplate);
});
batch.end();
return doc;
@@ -1318,7 +1316,9 @@ export namespace DocUtils {
const options = { title: "data", backgroundColor: StrCast(doc.backgroundColor), _autoHeight: true, _width, x: -_width / 2, y: - _height / 2, _showSidebar: false };
if (docLayoutTemplate) {
- Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined);
+ if (docLayoutTemplate !== doc[customName]) {
+ Doc.ApplyTemplateTo(docLayoutTemplate, doc, customName, undefined);
+ }
} else {
let fieldTemplate: Opt<Doc>;
if (doc.data instanceof RichTextField || typeof (doc.data) === "string") {
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 5c77041e0..f585277d8 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -205,29 +205,37 @@ export class CurrentUserUtils {
const reqdOpts = { title: "icon templates", _height: 75, system: true };
const templateIconsDoc = this.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([], reqdOpts));
- const makeIconTemplate = (type: DocumentType | undefined, templateField: string, iconTemplate: (opts:DocumentOptions) => Doc) => {
+ const makeIconTemplate = (type: DocumentType | undefined, templateField: string, opts:DocumentOptions) => {
const iconFieldName = "icon" + (type ? "_" + type : "");
- return DocCast(templateIconsDoc[iconFieldName] ?? (templateIconsDoc[iconFieldName] = MakeTemplate(iconTemplate({onClick:deiconifyScript(), system: true}), true, iconFieldName, templateField))) ;
+ const curIcon = DocCast(templateIconsDoc[iconFieldName]);
+ let creator = labelBox;
+ switch (opts.iconTemplate) {
+ case DocumentType.IMG : creator = imageBox; break;
+ case DocumentType.FONTICON: creator = fontBox; break;
+ }
+ const allopts = {system: true, ...opts};
+ return this.AssignScripts( (curIcon?.iconTemplate === opts.iconTemplate ?
+ this.AssignOpts(curIcon, allopts):undefined) ?? ((templateIconsDoc[iconFieldName] = MakeTemplate(creator(allopts), true, iconFieldName, templateField))),
+ {onClick:"deiconifyView(documentView)"});
};
- const deiconifyScript = () => ScriptField.MakeScript("deiconifyView(documentView)", { documentView: "any" });
- const labelBox = (opts: object) => Docs.Create.LabelDocument({
+ const labelBox = (opts: DocumentOptions, data?:string) => Docs.Create.LabelDocument({
textTransform: "unset", letterSpacing: "unset", _singleLine: false, _minFontSize: 14, _maxFontSize: 24, borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts
});
- const imageBox = (url: Opt<string>, opts: object) => Docs.Create.ImageDocument(url ?? "http://www.cs.brown.edu/~bcz/noImage.png", { "icon-nativeWidth": 360 / 4, "icon-nativeHeight": 270 / 4, _width: 360 / 4, _height: 270 / 4, _showTitle: "title", ...opts });
- const fontBox = (opts:DocumentOptions) => Docs.Create.FontIconDocument({ _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts });
+ const imageBox = (opts: DocumentOptions, url?:string) => Docs.Create.ImageDocument(url ?? "http://www.cs.brown.edu/~bcz/noImage.png", { "icon-nativeWidth": 360 / 4, "icon-nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _showTitle: "title", ...opts });
+ const fontBox = (opts:DocumentOptions, data?:string) => Docs.Create.FontIconDocument({ _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts });
const iconTemplates = [
- makeIconTemplate(undefined, "title", (opts) => labelBox({ ...opts, _backgroundColor: "dimgray" })),
- makeIconTemplate(DocumentType.AUDIO, "title", (opts) => labelBox({ ...opts, _backgroundColor: "lightgreen" })),
- makeIconTemplate(DocumentType.PDF, "title", (opts) => labelBox({ ...opts, _backgroundColor: "pink" })),
- makeIconTemplate(DocumentType.WEB, "title", (opts) => labelBox({...opts, _backgroundColor: "brown" })),
- makeIconTemplate(DocumentType.RTF, "text", (opts) => labelBox({ ...opts, _showTitle: "creationDate" })),
- makeIconTemplate(DocumentType.IMG, "data", (opts) => imageBox("", { ...opts, _height: undefined, })),
- makeIconTemplate(DocumentType.COL, "icon", (opts) => imageBox(undefined, opts)),
- makeIconTemplate(DocumentType.VID, "icon", (opts) => imageBox(undefined, opts)),
- makeIconTemplate(DocumentType.BUTTON, "data", (opts) => fontBox(opts)),
+ makeIconTemplate(undefined, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "dimgray"}),
+ makeIconTemplate(DocumentType.AUDIO, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "lightgreen"}),
+ makeIconTemplate(DocumentType.PDF, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "pink"}),
+ makeIconTemplate(DocumentType.WEB, "title", { iconTemplate:DocumentType.LABEL, backgroundColor: "brown"}),
+ makeIconTemplate(DocumentType.RTF, "text", { iconTemplate:DocumentType.LABEL, _showTitle: "creationDate"}),
+ makeIconTemplate(DocumentType.IMG, "data", { iconTemplate:DocumentType.IMG, _height: undefined}),
+ makeIconTemplate(DocumentType.COL, "icon", { iconTemplate:DocumentType.IMG}),
+ makeIconTemplate(DocumentType.VID, "icon", { iconTemplate:DocumentType.IMG}),
+ makeIconTemplate(DocumentType.BUTTON,"data", { iconTemplate:DocumentType.FONTICON}),
//nasty hack .. templates are looked up exclusively by type -- but we want a template for a document with a certain field (transcription) .. so this hack and the companion hack in createCustomView does this for now
- makeIconTemplate("transcription" as any, "transcription", (opts) => labelBox({ ...opts, _backgroundColor: "orange" })),
- // makeIconTemplate(DocumentType.PDF, "icon", () => imageBox("http://www.cs.brown.edu/~bcz/noImage.png", {}))
+ makeIconTemplate("transcription" as any, "transcription", { iconTemplate:DocumentType.LABEL, backgroundColor: "orange" }),
+ //makeIconTemplate(DocumentType.PDF, "icon", {iconTemplate:DocumentType.IMG}, (opts) => imageBox("http://www.cs.brown.edu/~bcz/noImage.png", opts))
].filter(d => d).map(d => d!);
this.AssignOpts(DocCast(doc[field]), {}, iconTemplates);
}
@@ -779,23 +787,23 @@ export class CurrentUserUtils {
/// Initializes all the default buttons for the top bar context menu
static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") {
- const ctxtMenuBtnsDoc = DocCast(doc[field]);
+ const reqdCtxtOpts = { title: "context menu buttons", flexGap: 0, childDontRegisterViews: true, linearViewIsExpanded: true, ignoreClick: true, linearViewExpandable: false, _height: 35 };
+ const ctxtMenuBtnsDoc = this.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined);
const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => {
const menuBtnDoc = DocListCast(ctxtMenuBtnsDoc?.data).find(doc => doc.title === params.title);
if (!params.subMenu) {
return this.setupContextMenuButton(params, menuBtnDoc);
} else {
- const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, title:"submenu",
+ const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit,
childDontRegisterViews: true, flexGap: 0, _height: 30, ignoreClick: true,
linearViewSubMenu: true, linearViewExpandable: true, };
return this.AssignScripts(this.AssignOpts(menuBtnDoc, reqdSubMenuOpts) ??
- this.linearButtonList(reqdSubMenuOpts, params.subMenu.map(sub =>
+ (ctxtMenuBtnsDoc[StrCast(params.title)]= this.linearButtonList(reqdSubMenuOpts, params.subMenu.map(sub =>
this.setupContextMenuButton(sub, DocListCast(menuBtnDoc?.data).find(doc => doc.title === sub.title))
- )), undefined, params.funcs);
+ ))), undefined, params.funcs);
}
});
- const reqdCtxtOpts = { title: "context menu buttons", flexGap: 0, childDontRegisterViews: true, linearViewIsExpanded: true, ignoreClick: true, linearViewExpandable: false, _height: 35 };
- return this.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, ctxtMenuBtns);
+ return this.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns);
}
/// collection of documents rendered in the overlay layer above all tabs and other UI
@@ -957,12 +965,13 @@ export class CurrentUserUtils {
this.AssignDocField(doc, "globalScriptDatabase", (opts) => Docs.Prototypes.MainScriptDocument(), {});
this.AssignDocField(doc, "myHeaderBar", (opts) => Docs.Create.MulticolumnDocument([], opts), { title: "header bar", system: true }); // drop down panel at top of dashboard for stashing documents
- setTimeout(() => DocServer.UPDATE_SERVER_CACHE(), 2500);
if (doc.activeDashboard instanceof Doc) {
// undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme;
}
+ new LinkManager();
+ DocServer.UPDATE_SERVER_CACHE();
return doc;
}
static setupFieldInfos(doc:Doc, field="fieldInfos") {
@@ -1009,12 +1018,7 @@ export class CurrentUserUtils {
await Docs.Prototypes.initialize();
const userDoc = Docs.newAccount ? new Doc(userDocumentId, true) : field as Doc;
Docs.newAccount &&(userDoc.activePage = "home");
- const updated = this.updateUserDocument(Doc.SetUserDoc(userDoc), sharingDocumentId, linkDatabaseId);
- (await DocListCastAsync(Doc.LinkDBDoc()?.data))?.forEach(async link => { // make sure anchors are loaded to avoid incremental updates to computedFn's in LinkManager
- const a1 = await Cast(link?.anchor1, Doc, null);
- const a2 = await Cast(link?.anchor2, Doc, null);
- });
- return updated;
+ return this.updateUserDocument(Doc.SetUserDoc(userDoc), sharingDocumentId, linkDatabaseId);
});
} else {
throw new Error("There should be a user id! Why does Dash think there isn't one?");
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 2100b1195..d51cd350d 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -1,7 +1,6 @@
-import { validationResult } from "express-validator/check";
import { action, observable, observe } from "mobx";
import { computedFn } from "mobx-utils";
-import { DirectLinksSym, Doc, DocListCast, Field, Opt } from "../../fields/Doc";
+import { DirectLinksSym, Doc, DocListCast, DocListCastAsync, Field, Opt } from "../../fields/Doc";
import { List } from "../../fields/List";
import { ProxyField } from "../../fields/Proxy";
import { BoolCast, Cast, StrCast } from "../../fields/Types";
@@ -35,72 +34,74 @@ export class LinkManager {
constructor() {
LinkManager._instance = this;
this.createLinkrelationshipLists();
- setTimeout(() => {
- LinkManager.userLinkDBs = [];
- const addLinkToDoc = (link: Doc) => {
- const a1Prom = link?.anchor1;
- const a2Prom = link?.anchor2;
- Promise.all([a1Prom, a2Prom]).then((all) => {
- const a1 = all[0];
- const a2 = all[1];
- const a1ProtoProm = (link?.anchor1 as Doc)?.proto;
- const a2ProtoProm = (link?.anchor2 as Doc)?.proto;
- Promise.all([a1ProtoProm, a2ProtoProm]).then(action((all) => {
- if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
- Doc.GetProto(a1)[DirectLinksSym].add(link);
- Doc.GetProto(a2)[DirectLinksSym].add(link);
- Doc.GetProto(link)[DirectLinksSym].add(link);
- }
- }));
- });
- };
- const remLinkFromDoc = (link: Doc) => {
- const a1 = link?.anchor1;
- const a2 = link?.anchor2;
- Promise.all([a1, a2]).then(action(() => {
+ LinkManager.userLinkDBs = [];
+ const addLinkToDoc = (link: Doc) => {
+ const a1Prom = link?.anchor1;
+ const a2Prom = link?.anchor2;
+ Promise.all([a1Prom, a2Prom]).then((all) => {
+ const a1 = all[0];
+ const a2 = all[1];
+ const a1ProtoProm = (link?.anchor1 as Doc)?.proto;
+ const a2ProtoProm = (link?.anchor2 as Doc)?.proto;
+ Promise.all([a1ProtoProm, a2ProtoProm]).then(action((all) => {
if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
- Doc.GetProto(a1)[DirectLinksSym].delete(link);
- Doc.GetProto(a2)[DirectLinksSym].delete(link);
- Doc.GetProto(link)[DirectLinksSym].delete(link);
+ Doc.GetProto(a1)[DirectLinksSym].add(link);
+ Doc.GetProto(a2)[DirectLinksSym].add(link);
+ Doc.GetProto(link)[DirectLinksSym].add(link);
}
}));
- };
- const watchUserLinkDB = (userLinkDBDoc: Doc) => {
- LinkManager.links.push(...DocListCast(userLinkDBDoc.data));
- const toRealField = (field: Field) => field instanceof ProxyField ? field.value() : field; // see List.ts. data structure is not a simple list of Docs, but a list of ProxyField/Fields
- observe(userLinkDBDoc.data as Doc, change => { // observe pushes/splices on a user link DB 'data' field (should only happen for local changes)
- switch (change.type as any) {
- case "splice":
- (change as any).added.forEach((link: any) => addLinkToDoc(toRealField(link)));
- (change as any).removed.forEach((link: any) => remLinkFromDoc(toRealField(link)));
- break;
- case "update": //let oldValue = change.oldValue;
- }
- }, true);
- observe(userLinkDBDoc, "data", // obsever when a new array of links is assigned as the link DB 'data' field (should happen whenever a remote user adds/removes a link)
- change => {
- switch (change.type as any) {
- case "update":
- Promise.all([...(change.oldValue as any as Doc[] || []), ...(change.newValue as any as Doc[] || [])]).then(doclist => {
- const oldDocs = doclist.slice(0, (change.oldValue as any as Doc[] || []).length);
- const newDocs = doclist.slice((change.oldValue as any as Doc[] || []).length, doclist.length);
-
- const added = newDocs?.filter(link => !(oldDocs || []).includes(link));
- const removed = oldDocs?.filter(link => !(newDocs || []).includes(link));
- added?.forEach((link: any) => addLinkToDoc(toRealField(link)));
- removed?.forEach((link: any) => remLinkFromDoc(toRealField(link)));
- });
- }
- }, true);
- };
- observe(LinkManager.userLinkDBs, change => {
+ });
+ };
+ const remLinkFromDoc = (link: Doc) => {
+ const a1 = link?.anchor1;
+ const a2 = link?.anchor2;
+ Promise.all([a1, a2]).then(action(() => {
+ if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
+ Doc.GetProto(a1)[DirectLinksSym].delete(link);
+ Doc.GetProto(a2)[DirectLinksSym].delete(link);
+ Doc.GetProto(link)[DirectLinksSym].delete(link);
+ }
+ }));
+ };
+ const watchUserLinkDB = (userLinkDBDoc: Doc) => {
+ LinkManager.links.push(...DocListCast(userLinkDBDoc.data));
+ const toRealField = (field: Field) => field instanceof ProxyField ? field.value() : field; // see List.ts. data structure is not a simple list of Docs, but a list of ProxyField/Fields
+ observe(userLinkDBDoc.data as Doc, change => { // observe pushes/splices on a user link DB 'data' field (should only happen for local changes)
switch (change.type as any) {
- case "splice": (change as any).added.forEach(watchUserLinkDB); break;
+ case "splice":
+ (change as any).added.forEach((link: any) => addLinkToDoc(toRealField(link)));
+ (change as any).removed.forEach((link: any) => remLinkFromDoc(toRealField(link)));
+ break;
case "update": //let oldValue = change.oldValue;
}
}, true);
- LinkManager.addLinkDB(Doc.LinkDBDoc());
- });
+ observe(userLinkDBDoc, "data", // obsever when a new array of links is assigned as the link DB 'data' field (should happen whenever a remote user adds/removes a link)
+ change => {
+ switch (change.type as any) {
+ case "update":
+ Promise.all([...(change.oldValue as any as Doc[] || []), ...(change.newValue as any as Doc[] || [])]).then(doclist => {
+ const oldDocs = doclist.slice(0, (change.oldValue as any as Doc[] || []).length);
+ const newDocs = doclist.slice((change.oldValue as any as Doc[] || []).length, doclist.length);
+
+ const added = newDocs?.filter(link => !(oldDocs || []).includes(link));
+ const removed = oldDocs?.filter(link => !(newDocs || []).includes(link));
+ added?.forEach((link: any) => addLinkToDoc(toRealField(link)));
+ removed?.forEach((link: any) => remLinkFromDoc(toRealField(link)));
+ });
+ }
+ }, true);
+ };
+ observe(LinkManager.userLinkDBs, change => {
+ switch (change.type as any) {
+ case "splice": (change as any).added.forEach(watchUserLinkDB); break;
+ case "update": //let oldValue = change.oldValue;
+ }
+ }, true);
+ LinkManager.addLinkDB(Doc.LinkDBDoc());
+ DocListCastAsync(Doc.LinkDBDoc()?.data).then(dblist => dblist?.forEach(async link => { // make sure anchors are loaded to avoid incremental updates to computedFn's in LinkManager
+ const a1 = await Cast(link?.anchor1, Doc, null);
+ const a2 = await Cast(link?.anchor2, Doc, null);
+ }));
}
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 49c2dcf34..17841c055 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -10,7 +10,6 @@ import { CurrentUserUtils } from "../util/CurrentUserUtils";
import { LinkManager } from "../util/LinkManager";
import { RecordingApi } from "../util/RecordingApi";
import { CollectionView } from "./collections/CollectionView";
-import { DashboardView } from './DashboardView';
import { MainView } from "./MainView";
AssignAllExtensions();
@@ -24,6 +23,7 @@ AssignAllExtensions();
await CurrentUserUtils.loadUserDocument(info.id);
} else {
await Docs.Prototypes.initialize();
+ new LinkManager();
}
document.getElementById('root')!.addEventListener('wheel', event => {
if (event.ctrlKey) {
@@ -37,7 +37,6 @@ AssignAllExtensions();
d.setTime(d.getTime() + (100 * 24 * 60 * 60 * 1000));
const expires = "expires=" + d.toUTCString();
document.cookie = `loadtime=${loading};${expires};path=/`;
- new LinkManager();
new RecordingApi;
ReactDOM.render(<MainView />, document.getElementById('root'));
})(); \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 081a1a924..17f1106d0 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -517,7 +517,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
d.y = NumCast(d.y) - this.Bounds.top;
return d;
});
- const summary = Docs.Create.TextDocument("", { _backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitContentsToBox: true, _showSidebar: true, title: "overview" });
+ const summary = Docs.Create.TextDocument("", { backgroundColor: "#e2ad32", x: this.Bounds.left, y: this.Bounds.top, isPushpin: true, _width: 200, _height: 200, _fitContentsToBox: true, _showSidebar: true, title: "overview" });
const portal = Docs.Create.FreeformDocument(selected, { x: this.Bounds.left + 200, y: this.Bounds.top, isGroup: true, backgroundColor: "transparent" });
DocUtils.MakeLink({ doc: summary }, { doc: portal }, "summary of:summarized by", "");
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 4fe6eb1e7..a5d952176 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -21,7 +21,7 @@ import { FieldId, RefField } from "./RefField";
import { RichTextField } from "./RichTextField";
import { listSpec } from "./Schema";
import { ComputedField, ScriptField } from "./ScriptField";
-import { BoolCast, Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
+import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types";
import { AudioField, ImageField, MapField, PdfField, VideoField, WebField } from "./URLField";
import { deleteProperty, GetEffectiveAcl, getField, getter, inheritParentAcls, makeEditable, makeReadOnly, normalizeEmail, setter, SharingPermissions, updateFunction } from "./util";
import JSZip = require("jszip");