From d7f2f6994ce6f2a450dff67b3595a692be9cb977 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 2 Jul 2020 17:23:31 +0530 Subject: restructuring and simplifying group implementation --- src/fields/Doc.ts | 8 ++++---- src/fields/util.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/fields') diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index e4d11dd4d..7b1db1042 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -96,13 +96,13 @@ export const AclSym = Symbol("Acl"); export const AclPrivate = Symbol("AclOwnerOnly"); export const AclReadonly = Symbol("AclReadOnly"); export const AclAddonly = Symbol("AclAddonly"); -export const AclReadWrite = Symbol("AclReadWrite"); +export const AclEdit = Symbol("AclEdit"); export const UpdatingFromServer = Symbol("UpdatingFromServer"); const CachedUpdates = Symbol("Cached updates"); export function fetchProto(doc: Doc) { - if (doc.author !== Doc.CurrentUserEmail) { + if (doc.author !== Doc.CurrentUserEmail) { // storing acls for groups needs to be extended here - AclSym should store a datastructure that stores information about permissions const acl = Doc.Get(doc, "ACL", true); switch (acl) { case "ownerOnly": @@ -114,8 +114,8 @@ export function fetchProto(doc: Doc) { case "addOnly": doc[AclSym] = AclAddonly; break; - case "write": - doc[AclSym] = AclReadWrite; + case "edit": + doc[AclSym] = AclEdit; } } diff --git a/src/fields/util.ts b/src/fields/util.ts index 2dc21c987..7bb090a93 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -111,7 +111,7 @@ const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHe "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"]; export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean { let prop = in_prop; - if (target[AclSym] && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return true; + if (target[AclSym] && !_overrideAcl && !DocServer.PlaygroundFields.includes(in_prop.toString())) return true; // generalise to a testpermission function if (typeof prop === "string" && prop !== "__id" && prop !== "__fields" && (prop.startsWith("_") || layoutProps.includes(prop))) { if (!prop.startsWith("_")) { console.log(prop + " is deprecated - switch to _" + prop); -- cgit v1.2.3-70-g09d2 From f4830de4f8c4794ec98e54be9ba8730e46155c35 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 6 Jul 2020 18:18:17 +0530 Subject: trying first implementation of storing acls --- src/client/DocServer.ts | 7 ++- src/client/util/GroupManager.tsx | 60 +++---------------- src/client/util/SharingManager.tsx | 42 +++++++------- src/client/views/DocComponent.tsx | 7 ++- src/client/views/collections/CollectionView.tsx | 8 ++- src/client/views/nodes/DocumentContentsView.tsx | 6 +- src/client/views/nodes/DocumentView.tsx | 5 +- .../views/nodes/formattedText/FormattedTextBox.tsx | 8 ++- src/fields/Doc.ts | 67 ++++++++++++++-------- src/fields/util.ts | 60 +++++++++++++++++-- 10 files changed, 151 insertions(+), 119 deletions(-) (limited to 'src/fields') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index eac53bb02..860a8fd92 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -39,9 +39,10 @@ export namespace DocServer { const docsWithUpdates: { [field: string]: Set } = {}; export var PlaygroundFields: string[]; - export function setPlaygroundFields(livePlayougroundFields: string[]) { - DocServer.PlaygroundFields = livePlayougroundFields; - livePlayougroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground)); + export function setPlaygroundFields(livePlaygroundFields: string[]) { + console.log("here"); + DocServer.PlaygroundFields = livePlaygroundFields; + livePlaygroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground)); } export function setFieldWriteMode(field: string, writeMode: WriteMode) { diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index b14dcf55b..83b206f94 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -33,7 +33,7 @@ export default class GroupManager extends React.Component<{}> { @observable private selectedUsers: UserOptions[] | null = null; // list of users selected in the "Select users" dropdown. @observable currentGroup: Opt; // the currently selected group. private inputRef: React.RefObject = React.createRef(); // the ref for the input box. - private currentUserGroups: Doc[] = []; + currentUserGroups: string[] = []; constructor(props: Readonly<{}>) { super(props); @@ -51,7 +51,7 @@ export default class GroupManager extends React.Component<{}> { DocListCastAsync(this.GroupManagerDoc?.data).then(groups => { groups?.forEach(group => { const members: string[] = JSON.parse(StrCast(group.members)); - if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(group); + if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(StrCast(group.groupName)); }); }) .finally(() => console.log(this.currentUserGroups)); @@ -82,11 +82,6 @@ export default class GroupManager extends React.Component<{}> { return this.users.map(user => ({ label: user, value: user })); } - - get groupMemberships() { - return this.currentUserGroups; - } - /** * Makes the GroupManager visible. */ @@ -151,6 +146,11 @@ export default class GroupManager extends React.Component<{}> { ); } + getGroupMembers(group: string | Doc): string[] { + if (group instanceof Doc) return JSON.parse(StrCast(group.members)) as string[]; + else return JSON.parse(StrCast(this.getGroup(group)!.members)) as string[]; + } + /** * @returns the members of the admin group. */ @@ -279,52 +279,6 @@ export default class GroupManager extends React.Component<{}> { this.inputRef.current.value = ""; } - /** - * A getter that @returns the interface rendered to view an individual group. - */ - // private get editingInterface() { - // const members: string[] = this.currentGroup ? JSON.parse(StrCast(this.currentGroup.members)) : []; - // const options: UserOptions[] = this.currentGroup ? this.options.filter(option => !(JSON.parse(StrCast(this.currentGroup!.members)) as string[]).includes(option.value)) : []; - // return (!this.currentGroup ? null : - //
- //
- // {this.currentGroup.groupName} - //
this.currentGroup = undefined)}> - // - //
- - // {this.hasEditAccess(this.currentGroup) ? - //
- //
- // {items}; + return ; } - createNodesDropdown(activeMap: string, options: { node: NodeType | any | null, title: string, label: string, command: (node: NodeType | any) => void, hidden?: boolean, style?: {} }[], key: string): JSX.Element { - const activeOption = activeMap === "bullet" ? ":" : activeMap === "decimal" ? "1.1" : "A.1"; + createNodesDropdown(activeMap: string, options: { node: NodeType | any | null, title: string, label: string, command: (node: NodeType | any) => void, hidden?: boolean, style?: {} }[], key: string, setter: (val: string) => {}): JSX.Element { + const activeOption = activeMap === "bullet" ? ":" : activeMap === "decimal" ? "1.1" : activeMap === "multi" ? "A.1" : ""; const items = options.map(({ title, label, hidden, style }) => { if (hidden) { - return label === activeOption ? - : - ; + return ; } - return label === activeOption ? - : - ; + return ; }); const self = this; function onChange(val: string) { self.TextView.endUndoTypingBatch(); options.forEach(({ label, node, command }) => { - if (val === label) { - UndoManager.RunInBatch(() => self.view && node && command(node), "nodes dropdown"); + if (val === label && node) { + if (self.TextView.props.isSelected()) { + UndoManager.RunInBatch(() => self.view && node && command(node), "nodes dropdown"); + setter(val); + } } }); } - return ; + return ; } changeFontSize = (mark: Mark, view: EditorView) => { @@ -416,10 +426,21 @@ export default class RichTextMenu extends AntimodeMenu { // TODO: remove doesn't work //remove all node type and apply the passed-in one to the selected text changeListType = (nodeType: Node | undefined) => { - if (!this.view) return; + if (!this.view || (nodeType as any)?.attrs.mapStyle === "") return; + + const nextIsOL = this.view.state.selection.$from.nodeAfter?.type === schema.nodes.ordered_list; + let inList: any = undefined; + let fromList = -1; + let path: any = Array.from((this.view.state.selection.$from as any).path); + for (let i = 0; i < path.length; i++) { + if (path[i]?.type === schema.nodes.ordered_list) { + inList = path[i]; + fromList = path[i - 1]; + } + } const marks = this.view.state.storedMarks || (this.view.state.selection.$to.parentOffset && this.view.state.selection.$from.marks()); - if (!wrapInList(schema.nodes.ordered_list)(this.view.state, (tx2: any) => { + if (inList || !wrapInList(schema.nodes.ordered_list)(this.view.state, (tx2: any) => { const tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle, this.view!.state.selection.from - 1, this.view!.state.selection.to + 1); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); @@ -427,12 +448,12 @@ export default class RichTextMenu extends AntimodeMenu { this.view!.dispatch(tx2); })) { const tx2 = this.view.state.tr; - if (nodeType && this.view.state.selection.$from.nodeAfter?.type === schema.nodes.ordered_list) { - const tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle, this.view.state.selection.from, this.view.state.selection.to); + if (nodeType && (inList || nextIsOL)) { + const tx3 = updateBullets(tx2, schema, nodeType && (nodeType as any).attrs.mapStyle, inList ? fromList : this.view.state.selection.from, + inList ? fromList + inList.nodeSize : this.view.state.selection.to); marks && tx3.ensureMarks([...marks]); marks && tx3.setStoredMarks([...marks]); - - this.view.dispatch(tx3.setSelection(new NodeSelection(tx3.doc.resolve(this.view.state.selection.$from.pos)))); + this.view.dispatch(tx3); } } } @@ -448,13 +469,13 @@ export default class RichTextMenu extends AntimodeMenu { return true; } alignCenter = (state: EditorState, dispatch: any) => { - return this.alignParagraphs(state, "center", dispatch); + return this.TextView.props.isSelected() && this.alignParagraphs(state, "center", dispatch); } alignLeft = (state: EditorState, dispatch: any) => { - return this.alignParagraphs(state, "left", dispatch); + return this.TextView.props.isSelected() && this.alignParagraphs(state, "left", dispatch); } alignRight = (state: EditorState, dispatch: any) => { - return this.alignParagraphs(state, "right", dispatch); + return this.TextView.props.isSelected() && this.alignParagraphs(state, "right", dispatch); } alignParagraphs(state: EditorState, align: "left" | "right" | "center", dispatch: any) { @@ -914,7 +935,7 @@ export default class RichTextMenu extends AntimodeMenu { {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size"), this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family"),
, - this.createNodesDropdown(this.activeListType, this.listTypeOptions, "nodes"), + this.createNodesDropdown(this.activeListType, this.listTypeOptions, "nodes", action((val: string) => this.activeListType = val)), this.createButton("sort-amount-down", "Summarize", undefined, this.insertSummarizer), this.createButton("quote-left", "Blockquote", undefined, this.insertBlockquote), this.createButton("minus", "Horizontal Rule", undefined, this.insertHorizontalRule), diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts index ca30dde9d..ef0fead4a 100644 --- a/src/client/views/nodes/formattedText/RichTextRules.ts +++ b/src/client/views/nodes/formattedText/RichTextRules.ts @@ -90,7 +90,7 @@ export class RichTextRules { textDoc.inlineTextCount = numInlines + 1; const inlineFieldKey = "inline" + numInlines; // which field on the text document this annotation will write to const inlineLayoutKey = "layout_" + inlineFieldKey; // the field holding the layout string that will render the inline annotation - const textDocInline = Docs.Create.TextDocument("", { layoutKey: inlineLayoutKey, _width: 75, _height: 35, annotationOn: textDoc, _autoHeight: true, _fontSize: 9, title: "inline comment" }); + const textDocInline = Docs.Create.TextDocument("", { layoutKey: inlineLayoutKey, _width: 75, _height: 35, annotationOn: textDoc, _autoHeight: true, _fontSize: "9pt", title: "inline comment" }); textDocInline.title = inlineFieldKey; // give the annotation its own title textDocInline.customTitle = true; // And make sure that it's 'custom' so that editing text doesn't change the title of the containing doc textDocInline.isTemplateForField = inlineFieldKey; // this is needed in case the containing text doc is converted to a template at some point diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index c1659d4d5..61a37ef8a 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -55,7 +55,7 @@ export const documentSchema = createSchema({ _columnsHideIfEmpty: "boolean", // whether empty stacking view column headings should be hidden _columnHeaders: listSpec(SchemaHeaderField), // header descriptions for stacking/masonry _schemaHeaders: listSpec(SchemaHeaderField), // header descriptions for schema views - _fontSize: "number", + _fontSize: "string", _fontFamily: "string", _sidebarWidthPercent: "string", // percent of text window width taken up by sidebar -- cgit v1.2.3-70-g09d2 From db15b1d27a639af7a65f72dd5e4b6ea298412315 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Jul 2020 11:46:35 -0400 Subject: fixed issues with ACLs and writing to playground fields when you have Edit permission. Also fixed text editing by fixing fetchProto to use untracked references to fields --- src/client/util/SharingManager.tsx | 3 ++- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 2 +- src/fields/Doc.ts | 12 +++++------- src/fields/util.ts | 8 +++++--- 4 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index af68edab6..050ff0c4e 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -146,6 +146,7 @@ export default class SharingManager extends React.Component<{}> { const ACL = `ACL-${StrCast(group.groupName)}`; target[ACL] = permission; + Doc.GetProto(target)[ACL] = permission; group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]); // group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List).push(target) : group.docsShared = new List([target]); @@ -215,7 +216,7 @@ export default class SharingManager extends React.Component<{}> { // const permissions: { [key: string]: number } = target[ACL] ? JSON.parse(StrCast(target[ACL])) : {}; target[ACL] = permission; - + Doc.GetProto(target)[ACL] = permission; if (permission !== SharingPermissions.None) { console.log(target); diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 0af941182..01fbcb020 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -237,7 +237,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp this._applyingChange = true; (curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now()))); if ((!curTemp && !curProto) || curText || curLayout?.Data.includes("dash")) { // if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended) - if (json !== curLayout?.Data) { + if (json.replace(/"selection":.*/, "") !== curLayout?.Data.replace(/"selection":.*/, "")) { !curText && tx.storedMarks?.map(m => m.type.name === "pFontSize" && (Doc.UserDoc().fontSize = this.layoutDoc._fontSize = m.attrs.fontSize)); !curText && tx.storedMarks?.map(m => m.type.name === "pFontFamily" && (Doc.UserDoc().fontFamily = this.layoutDoc._fontFamily = m.attrs.fontFamily)); this.dataDoc[this.props.fieldKey] = new RichTextField(json, curText); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index e8dca5fb6..8ab4735a7 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1,4 +1,4 @@ -import { action, computed, observable, ObservableMap, runInAction } from "mobx"; +import { action, computed, observable, ObservableMap, runInAction, untracked } from "mobx"; import { computedFn } from "mobx-utils"; import { alias, map, serializable } from "serializr"; import { DocServer } from "../client/DocServer"; @@ -110,15 +110,13 @@ const AclMap = new Map([ export function fetchProto(doc: Doc) { if (doc.author !== Doc.CurrentUserEmail) { // storing acls for groups needs to be extended here - AclSym should store a datastructure that stores information about permissions + untracked(() => { + const permissions: { [key: string]: symbol } = {}; - const permissions: { [key: string]: symbol } = {}; + Object.keys(doc).filter(key => key.startsWith("ACL")).forEach(key => permissions[key] = AclMap.get(StrCast(doc[key]))!); - Object.keys(doc).forEach(key => { - if (key.startsWith("ACL")) permissions[key] = AclMap.get(StrCast(doc[key]))!; + if (Object.keys(permissions).length) doc[AclSym] = permissions; }); - - - if (Object.keys(permissions).length) doc[AclSym] = permissions; } if (doc.proto instanceof Promise) { diff --git a/src/fields/util.ts b/src/fields/util.ts index ebfc3933a..be7736413 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -70,8 +70,8 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number const writeMode = DocServer.getFieldWriteMode(prop as string); const fromServer = target[UpdatingFromServer]; const sameAuthor = fromServer || (receiver.author === Doc.CurrentUserEmail); - const writeToDoc = sameAuthor || (writeMode !== DocServer.WriteMode.LiveReadonly); - const writeToServer = (sameAuthor || (writeMode === DocServer.WriteMode.Default)) && !playgroundMode; + const writeToDoc = sameAuthor || GetEffectiveAcl(target) === AclEdit || (writeMode !== DocServer.WriteMode.LiveReadonly); + const writeToServer = (sameAuthor || GetEffectiveAcl(target) === AclEdit || writeMode === DocServer.WriteMode.Default) && !playgroundMode; if (writeToDoc) { if (value === undefined) { @@ -91,8 +91,9 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number redo: () => receiver[prop] = value, undo: () => receiver[prop] = curValue }); + return true; } - return true; + return false; }); let _setter: (target: any, prop: string | symbol | number, value: any, receiver: any) => boolean = _setterImpl; @@ -126,6 +127,7 @@ export function setGroups(groups: string[]) { } export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { + if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclEdit; const HierarchyMapping = new Map([ [AclPrivate, 0], -- cgit v1.2.3-70-g09d2 From d180732e4e9cc9291fa71715370763d38d4c4340 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Tue, 14 Jul 2020 22:12:01 +0530 Subject: added group creation modal to GroupManager + much ui --- src/client/util/GroupManager.scss | 174 ++++++++++++++++++--------------- src/client/util/GroupManager.tsx | 183 +++++++++++++++++++++-------------- src/client/util/GroupMemberView.scss | 37 +++++-- src/client/util/GroupMemberView.tsx | 21 +++- src/client/util/SharingManager.scss | 17 ++-- src/client/util/SharingManager.tsx | 63 ++++++------ src/client/views/MainViewModal.tsx | 2 +- src/fields/util.ts | 4 +- 8 files changed, 300 insertions(+), 201 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss index 544a79e98..2da1f0d95 100644 --- a/src/client/util/GroupManager.scss +++ b/src/client/util/GroupManager.scss @@ -1,23 +1,60 @@ -@import "../views/globalCssVariables"; +// @import "../views/globalCssVariables"; .group-interface { - background-color: whitesmoke !important; - color: grey; - width: 450px; + // background-color: whitesmoke !important; + // color: grey; + width: 550px; height: 300px; .dialogue-box { - width: 450; - height: 300; + .group-create { + display: flex; + flex-direction: column; + height: 90%; + justify-content: space-between; + // flex-basis: 30%; + margin-left: 5px; + + input { + border-radius: 5px; + // border: none; + padding: 8px; + min-width: 100%; + margin: 4px 0 4px 0; + border: 1px solid hsl(0, 0%, 80%); + outline: none; + + &:focus { + // border: unset; + border: 2.5px solid #2684FF; + } + } + + p { + font-size: 20px; + text-align: left; + color: black; + } + + button { + align-self: flex-end; + } + } } + // .dialogue-box { + // width: 450; + // height: 300; + // } + button { - background: $lighter-alt-accent; + // background: $lighter-alt-accent; + align-self: center; outline: none; border-radius: 5px; border: 0px; - color: #fcfbf7; - text-transform: uppercase; + // color: #fcfbf7; + text-transform: none; letter-spacing: 2px; font-size: 75%; padding: 10px; @@ -36,12 +73,6 @@ border-radius: 10px; } - button { - width: 100%; - align-self: center; - background: $darker-alt-accent; - } - .delete-button { background: rgb(227, 86, 86); } @@ -55,82 +86,73 @@ } .group-heading { - letter-spacing: .5em; + display: flex; + align-items: center; + margin-bottom: 25px; + + p { + font-size: 20px; + text-align: left; + // margin: 0 0 20px 0; + margin-right: 15px; + color: black; + // width: 60%; + } } .group-body { - display: flex; + // display: flex; justify-content: space-between; - max-height: 80%; - - .group-create { - display: flex; - flex-direction: column; - flex-basis: 30%; - margin-left: 5px; - - input { - border-radius: 5px; - border: none; - padding: 4px; - min-width: 100%; - margin: 4px 0 4px 0; - } + // max-height: 80%; + height: 100%; + background-color: #e8e8e8; + // flex-direction: column; - } - - .group-content { - padding-left: 1em; - padding-right: 1em; - justify-content: space-around; - text-align: left; + // padding-left: 1em; + padding-right: 1em; + justify-content: space-around; + text-align: left; - overflow-y: auto; - width: 100%; - - .group-row { - display: flex; - position: relative; - margin-bottom: 5px; - min-height: 40px; - border: 1px solid; - border-radius: 10px; - align-items: center; - - .group-name { - position: relative; - max-width: 65%; - left: 10; - } + overflow-y: auto; + width: 100%; - button { - position: absolute; - width: 30%; - right: 2; - margin-top: 0; - } + .group-row { + display: flex; + // position: relative; + margin-bottom: 5px; + min-height: 30px; + // border: 1px solid; + // border-radius: 10px; + align-items: center; + + .group-name { + // position: relative; + max-width: 65%; + // left: 10; + margin: 0 10; + color: black; } - ::placeholder { - color: $intermediate-color; + .group-info { + cursor: pointer; } - input { - border-radius: 5px; - border: none; - padding: 4px; - min-width: 100%; - margin: 2px 0; + button { + position: absolute; + width: 30%; + right: 2; + margin-top: 0; } + } + input { + border-radius: 5px; + border: none; + padding: 4px; + min-width: 100%; + margin: 2px 0; } - } - h1 { - color: $dark-color; - text-transform: uppercase; - letter-spacing: 2px; - font-size: 120%; } } \ No newline at end of file diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 23bdd248b..f2b502ae0 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -12,11 +12,12 @@ import { Utils } from "../../Utils"; import * as RequestPromise from "request-promise"; import Select from 'react-select'; import "./GroupManager.scss"; -import { StrCast } from "../../fields/Types"; +import { StrCast, Cast } from "../../fields/Types"; import GroupMemberView from "./GroupMemberView"; import { setGroups } from "../../fields/util"; +import { DocServer } from "../DocServer"; -library.add(fa.faWindowClose); +library.add(fa.faPlus, fa.faTimes, fa.faInfoCircle); export interface UserOptions { label: string; @@ -33,47 +34,37 @@ export default class GroupManager extends React.Component<{}> { @observable private users: string[] = []; // list of users populated from the database. @observable private selectedUsers: UserOptions[] | null = null; // list of users selected in the "Select users" dropdown. @observable currentGroup: Opt; // the currently selected group. + @observable private createGroupModalOpen: boolean = false; private inputRef: React.RefObject = React.createRef(); // the ref for the input box. - currentUserGroups: string[] = []; + private currentUserGroups: string[] = []; + @observable private buttonColour: "#979797" | "black" = "#979797"; constructor(props: Readonly<{}>) { super(props); GroupManager.Instance = this; } - // sets up the list of users - componentDidMount() { - this.populateUsers().then(resolved => runInAction(() => this.users = resolved)); - - // this.getAllGroups().forEach(group => { - // const members: string[] = JSON.parse(StrCast(group.members)); - // if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(group); - // }); - DocListCastAsync(this.GroupManagerDoc?.data).then(groups => { - groups?.forEach(group => { - const members: string[] = JSON.parse(StrCast(group.members)); - if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(StrCast(group.groupName)); - }); - }) - .finally(() => setGroups(this.currentUserGroups)); - - // (this.GroupManagerDoc?.data as List).forEach(group => { - // Promise.resolve(group).then(resolvedGroup => { - // const members: string[] = JSON.parse(StrCast(resolvedGroup.members)); - // if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(resolvedGroup); - // }); - // }); - - } - /** - * Fetches the list of users stored on the database and @returns a list of the emails. + * Fetches the list of users stored on the database. */ populateUsers = async () => { - const userList: User[] = JSON.parse(await RequestPromise.get(Utils.prepend("/getUsers"))); - // const currentUserIndex = userList.findIndex(user => user.email === Doc.CurrentUserEmail); - // currentUserIndex !== -1 && userList.splice(currentUserIndex, 1); - return userList.map(user => user.email); + const userList = await RequestPromise.get(Utils.prepend("/getUsers")); + const raw = JSON.parse(userList) as User[]; + const evaluating = raw.map(async user => { + const isCandidate = user.email !== Doc.CurrentUserEmail; + if (isCandidate) { + const userDocument = await DocServer.GetRefField(user.userDocumentId); + if (userDocument instanceof Doc) { + const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); + runInAction(() => { + if (notificationDoc instanceof Doc) { + this.users.push(user.email); + } + }); + } + } + }); + return Promise.all(evaluating); } /** @@ -90,6 +81,15 @@ export default class GroupManager extends React.Component<{}> { open = () => { SelectionManager.DeselectAll(); this.isOpen = true; + this.populateUsers(); + DocListCastAsync(this.GroupManagerDoc?.data).then(groups => { + groups?.forEach(group => { + const members: string[] = JSON.parse(StrCast(group.members)); + if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(StrCast(group.groupName)); + }); + + setGroups(this.currentUserGroups); + }); } /** @@ -99,6 +99,8 @@ export default class GroupManager extends React.Component<{}> { close = () => { this.isOpen = false; this.currentGroup = undefined; + this.users = []; + this.createGroupModalOpen = false; } /** @@ -277,6 +279,7 @@ export default class GroupManager extends React.Component<{}> { */ @action createGroup = () => { + // this.createGroupModalOpen = true; if (!this.inputRef.current?.value) { alert("Please enter a group name"); return; @@ -288,6 +291,66 @@ export default class GroupManager extends React.Component<{}> { this.createGroupDoc(this.inputRef.current.value, this.selectedUsers?.map(user => user.value)); this.selectedUsers = null; this.inputRef.current.value = ""; + this.buttonColour = "#979797"; + } + + private get groupCreationModal() { + const contents = ( +
+
+

New Group

+
this.createGroupModalOpen = false)}> + +
+
+ this.buttonColour = this.inputRef.current?.value ? "black" : "#979797")} /> + - this.props.group.groupName = e.currentTarget.value} + > +
- +
- {GroupManager.Instance.hasEditAccess(this.props.group) ?
@@ -55,13 +60,18 @@ export default class GroupMemberView extends React.Component : null}
+
{members.map(member => (
{member}
- {GroupManager.Instance.hasEditAccess(this.props.group) ? : null} + {GroupManager.Instance.hasEditAccess(this.props.group) ? +
GroupManager.Instance.removeMemberFromGroup(this.props.group, member)}> + +
+ : null}
))}
@@ -75,6 +85,7 @@ export default class GroupMemberView extends React.Component; } diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 2708876a3..ce23ce413 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -6,10 +6,10 @@ width: 600px; height: 360px; - .dialogue-box { - width: 450; - height: 300; - } + // .dialogue-box { + // width: 450; + // height: 300; + // } .overlay { transform: translate(-20px, -20px); @@ -60,11 +60,13 @@ .main-container { display: flex; - + margin-top: -10px; .individual-container, .group-container { width: 50%; + display: flex; + flex-direction: column; .share-title { margin-top: 20px; @@ -74,7 +76,7 @@ .groups-list, .users-list { font-style: italic; - background: gainsboro; + background: #e8e8e8; // border: 1px solid black; padding-left: 10px; padding-right: 10px; @@ -88,7 +90,7 @@ justify-content: center; // color: red; color: black; - height: 255px; + height: 250px; margin: 0 2; @@ -187,7 +189,6 @@ .permissions-dropdown { border: none; height: 25; - background: gainsboro; } .edit-actions { diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index af68edab6..6c7c634eb 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -22,7 +22,7 @@ import Select from "react-select"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { List } from "../../fields/List"; -library.add(fa.faCopy); +library.add(fa.faCopy, fa.faTimes); export interface User { email: string; @@ -140,7 +140,7 @@ export default class SharingManager extends React.Component<{}> { setInternalGroupSharing = (group: Doc, permission: string) => { const members: string[] = JSON.parse(StrCast(group.members)); - const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email)); + const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); const target = this.targetDoc!; const ACL = `ACL-${StrCast(group.groupName)}`; @@ -160,8 +160,8 @@ export default class SharingManager extends React.Component<{}> { }); } - shareWithAddedMember = (group: Doc, email: string) => { - const user: ValidatedUser = this.users.find(user => user.user.email === email)!; + shareWithAddedMember = (group: Doc, emailId: string) => { + const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!; if (group.docsShared) { DocListCastAsync(group.docsShared).then(docsShared => { @@ -173,8 +173,8 @@ export default class SharingManager extends React.Component<{}> { } } - removeMember = (group: Doc, email: string) => { - const user: ValidatedUser = this.users.find(user => user.user.email === email)!; + removeMember = (group: Doc, emailId: string) => { + const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!; if (group.docsShared) { DocListCastAsync(group.docsShared).then(docsShared => { @@ -194,9 +194,9 @@ export default class SharingManager extends React.Component<{}> { doc[ACL] = "Not Shared"; const members: string[] = JSON.parse(StrCast(group.members)); - const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email)); + const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); - users.forEach(user => Doc.RemoveDocFromList(user.notificationDoc, storage, doc)); + users.forEach(({ notificationDoc }) => Doc.RemoveDocFromList(notificationDoc, storage, doc)); }); }); @@ -330,24 +330,6 @@ export default class SharingManager extends React.Component<{}> { ); } - private computePermissions = (userKey: string) => { - // const sharingDoc = this.sharingDoc; - // if (!sharingDoc) { - // return SharingPermissions.None; - // } - // const metadata = sharingDoc[userKey] as Doc | string; - - if (!this.targetDoc) return SharingPermissions.None; - - const ACL = `ACL-${userKey}`; - const permission = StrCast(this.targetDoc[ACL]); - - // if (!metadata) { - // return SharingPermissions.None; - // } - return StrCast(this.targetDoc[ACL], SharingPermissions.None); - } - @action handleUsersChange = (selectedOptions: any) => { this.selectedUsers = selectedOptions as UserOptions[]; @@ -381,7 +363,7 @@ export default class SharingManager extends React.Component<{}> { [ { label: 'Individuals', - options: GroupManager.Instance.options.map(({ label, value }) => ({ label, value: "!indType/" + value })) + options: this.users.map(({ user: { email } }) => ({ label: email, value: "!indType/" + email })) }, { label: 'Groups', @@ -390,10 +372,12 @@ export default class SharingManager extends React.Component<{}> { ] : []; + console.log(this.users); + const userListContents: (JSX.Element | null)[] = this.users.map(({ user, notificationDoc }) => { // can't use async here const userKey = user.email.replace('.', '_'); // const userKey = user.userDocumentId; - const permissions = this.computePermissions(userKey); + const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None); // const color = ColorMapping.get(permissions); // console.log(manager); @@ -401,7 +385,7 @@ export default class SharingManager extends React.Component<{}> { // const usersShared = StrCast(metadata?.usersShared, ""); // console.log(usersShared) - return permissions === SharingPermissions.None ? null : ( + return permissions === SharingPermissions.None || user.email === this.targetDoc?.author ? null : (
{ ); }); + userListContents.unshift( + ( +
+ {this.targetDoc?.author} +
+
+ Owner +
+
+
+ ) + ); const groupListContents = GroupManager.Instance?.getAllGroups().map(group => { - const permissions = this.computePermissions(StrCast(group.groupName)); + const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`], SharingPermissions.None); // const color = ColorMapping.get(permissions); return permissions === SharingPermissions.None ? null : ( @@ -492,7 +491,7 @@ export default class SharingManager extends React.Component<{}> {

Share {this.focusOn(StrCast(this.targetDoc?.title, "this document"))}

- +
{this.targetDoc?.author !== Doc.CurrentUserEmail ? null : @@ -516,6 +515,7 @@ export default class SharingManager extends React.Component<{}> { }
+
Individuals
{/*200*/} { displayUserList ? @@ -530,6 +530,7 @@ export default class SharingManager extends React.Component<{}> {
+
Groups
{/*200*/} { displayGroupList ? diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx index 0b73a6ad7..249715511 100644 --- a/src/client/views/MainViewModal.tsx +++ b/src/client/views/MainViewModal.tsx @@ -21,7 +21,7 @@ export default class MainViewModal extends React.Component const dialogueOpacity = p.dialogueBoxDisplayedOpacity || 1; const overlayOpacity = p.overlayDisplayedOpacity || 0.4; return !p.isDisplayed ? (null) : ( -
+
Date: Tue, 14 Jul 2020 14:20:53 -0400 Subject: fixed issues with creating & using scripting boxes by making scriptFields be a function, not value, prop --- src/client/documents/Documents.ts | 2 ++ src/client/util/CurrentUserUtils.ts | 26 ++++++++++++------ src/client/views/OverlayView.scss | 2 ++ src/client/views/TemplateMenu.tsx | 7 +++-- .../views/collections/CollectionCarousel3DView.tsx | 10 +++---- .../views/collections/CollectionCarouselView.tsx | 7 +++-- .../views/collections/CollectionStackingView.tsx | 4 +-- .../views/collections/CollectionTreeView.tsx | 30 +++++++++++--------- src/client/views/collections/CollectionView.tsx | 11 +++++--- .../collectionFreeForm/CollectionFreeFormView.tsx | 9 +++--- .../collectionGrid/CollectionGridView.tsx | 2 +- .../CollectionMulticolumnView.tsx | 4 +-- .../CollectionMultirowView.tsx | 4 +-- src/client/views/nodes/DocumentView.tsx | 32 +++++++++++----------- src/fields/documentSchemas.ts | 1 - 15 files changed, 87 insertions(+), 64 deletions(-) (limited to 'src/fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index a415e17c8..90cef31d9 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -136,6 +136,8 @@ export interface DocumentOptions { dontRegisterChildViews?: boolean; lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document. see PresBox. "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form + "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form + "onChildClick-rawScript"?: string // on ChildClick script in raw text form "onClick-rawScript"?: string; // onClick script in raw text form "onCheckedClick-rawScript"?: string; // onChecked script in raw text form "onCheckedClick-params"?: List; // parameter list for onChecked treeview functions diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 7a06e1bc1..ad8336e8a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -413,7 +413,7 @@ export class CurrentUserUtils { { title: "Drag a presentation view", label: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc }, { title: "Drag a search box", label: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, { title: "Drag a scripting box", label: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc }, - // { title: "Drag an import folder", label: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, + { title: "Drag an import folder", label: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, { title: "Drag a mobile view", label: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, // { title: "Drag an instance of the device collection", label: "Buxton", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.Buxton()' }, // { title: "use pen", icon: "pen-nib", click: 'activatePen(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "blue", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, @@ -775,17 +775,17 @@ export class CurrentUserUtils { static setupClickEditorTemplates(doc: Doc) { if (doc["clickFuncs-child"] === undefined) { + // to use this function, select it from the context menu of a collection. then edit the onChildClick script. Add two Doc variables: 'target' and 'thisContainer', then assign 'target' to some target collection. After that, clicking on any document in the initial collection will open it in the target const openInTarget = Docs.Create.ScriptingDocument(ScriptField.MakeScript( - "docCast(thisContainer.target).then((target) => {" + - " target && docCast(this.source).then((source) => { " + - " target.proto.data = new List([source || this]); " + - " }); " + - "})", - { target: Doc.name }), { title: "Click to open in target", _width: 300, _height: 200, targetScriptKey: "onChildClick" }); + "docCast(thisContainer.target).then((target) => target && (target.proto.data = new List([self]))) ", + { thisContainer: Doc.name }), { + title: "Click to open in target", _width: 300, _height: 200, + targetScriptKey: "onChildClick", + }); const openDetail = Docs.Create.ScriptingDocument(ScriptField.MakeScript( "openOnRight(self.doubleClickView)", - { target: Doc.name }), { title: "Double click to open doubleClickView", _width: 300, _height: 200, targetScriptKey: "onChildDoubleClick" }); + {}), { title: "Double click to open doubleClickView", _width: 300, _height: 200, targetScriptKey: "onChildDoubleClick" }); doc["clickFuncs-child"] = Docs.Create.TreeDocument([openInTarget, openDetail], { title: "on Child Click function templates" }); } @@ -797,14 +797,22 @@ export class CurrentUserUtils { title: "onClick", "onClick-rawScript": "console.log('click')", isTemplateDoc: true, isTemplateForField: "onClick", _width: 300, _height: 200 }, "onClick"); + const onChildClick = Docs.Create.ScriptingDocument(undefined, { + title: "onChildClick", "onChildClick-rawScript": "console.log('child click')", + isTemplateDoc: true, isTemplateForField: "onChildClick", _width: 300, _height: 200 + }, "onChildClick"); const onDoubleClick = Docs.Create.ScriptingDocument(undefined, { title: "onDoubleClick", "onDoubleClick-rawScript": "console.log('double click')", isTemplateDoc: true, isTemplateForField: "onDoubleClick", _width: 300, _height: 200 }, "onDoubleClick"); + const onChildDoubleClick = Docs.Create.ScriptingDocument(undefined, { + title: "onChildDoubleClick", "onChildDoubleClick-rawScript": "console.log('child double click')", + isTemplateDoc: true, isTemplateForField: "onChildDoubleClick", _width: 300, _height: 200 + }, "onChildDoubleClick"); const onCheckedClick = Docs.Create.ScriptingDocument(undefined, { title: "onCheckedClick", "onCheckedClick-rawScript": "console.log(heading + checked + containingTreeView)", "onCheckedClick-params": new List(["heading", "checked", "containingTreeView"]), isTemplateDoc: true, isTemplateForField: "onCheckedClick", _width: 300, _height: 200 }, "onCheckedClick"); - doc.clickFuncs = Docs.Create.TreeDocument([onClick, onDoubleClick, onCheckedClick], { title: "onClick funcs" }); + doc.clickFuncs = Docs.Create.TreeDocument([onClick, onChildClick, onDoubleClick, onCheckedClick], { title: "onClick funcs" }); } PromiseValue(Cast(doc.clickFuncs, Doc)).then(func => func && PromiseValue(func.data).then(DocListCast)); diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss index 26c2e0e1e..09a349012 100644 --- a/src/client/views/OverlayView.scss +++ b/src/client/views/OverlayView.scss @@ -3,6 +3,8 @@ overflow: hidden; display: flex; flex-direction: column; + top: 0; + left: 0; } .overlayWindow-outerDiv, diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 916e631d0..9fb8a227e 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -108,8 +108,9 @@ export class TemplateMenu extends React.Component { return100 = () => 100; @computed get scriptField() { - return ScriptField.MakeScript("docs.map(d => switchView(d, this))", { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name }, + const script = ScriptField.MakeScript("docs.map(d => switchView(d, this))", { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name, firstDoc: Doc.name }, { docs: new List(this.props.docViews.map(dv => dv.props.Document)) }); + return script ? () => script : undefined; } templateIsUsed = (selDoc: Doc, templateDoc: Doc) => { const template = StrCast(templateDoc.dragFactory ? Cast(templateDoc.dragFactory, Doc, null)?.title : templateDoc.title); @@ -142,8 +143,8 @@ export class TemplateMenu extends React.Component { ContainingCollectionView={undefined} docFilters={returnEmptyFilter} rootSelected={returnFalse} - onCheckedClick={this.scriptField!} - onChildClick={this.scriptField!} + onCheckedClick={this.scriptField} + onChildClick={this.scriptField} LibraryPath={emptyPath} dropAction={undefined} active={returnTrue} diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 8f1cd5311..8e9970ada 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -38,15 +38,15 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume panelWidth = () => this.props.PanelWidth() / 3; panelHeight = () => this.props.PanelHeight() * 0.6; + onChildDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); @computed get content() { const currentIndex = NumCast(this.layoutDoc._itemIndex); const displayDoc = (childPair: { layout: Doc, data: Doc }) => { + const script = ScriptField.MakeScript("child._showCaption = 'caption'", { child: Doc.name }, { child: childPair.layout }); + const onChildClick = script && (() => script); return ; const CarouselDocument = makeInterface(documentSchema, collectionSchema); @@ -40,14 +41,16 @@ 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; + onContentDoubleClick = () => ScriptCast(this.layoutDoc.onChildDoubleClick); + onContentClick = () => ScriptCast(this.layoutDoc.onChildClick); @computed get content() { const index = NumCast(this.layoutDoc._itemIndex); return !(this.childLayoutPairs?.[index]?.layout instanceof Doc) ? (null) : <>
this.props.childClickScript || ScriptCast(this.Document.onChildClick); } + @computed get onChildDoubleClickHandler() { return () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); } addDocTab = (doc: Doc, where: string) => { if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index dbd39d8df..8438248ad 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -61,8 +61,8 @@ export interface TreeViewProps { treeViewHideHeaderFields: () => boolean; treeViewPreventOpen: boolean; renderedIds: string[]; // list of document ids rendered used to avoid unending expansion of items in a cycle - onCheckedClick?: ScriptField; - onChildClick?: ScriptField; + onCheckedClick?: () => ScriptField; + onChildClick?: () => ScriptField; ignoreFields?: string[]; } @@ -76,7 +76,7 @@ export interface TreeViewProps { * treeViewExpandedView : name of field whose contents are being displayed as the document's subtree */ class TreeView extends React.Component { - private _editTitleScript: ScriptField | undefined; + private _editTitleScript: (() => ScriptField) | undefined; private _header?: React.RefObject = React.createRef(); private _treedropDisposer?: DragManager.DragDropDisposer; private _dref = React.createRef(); @@ -124,7 +124,8 @@ class TreeView extends React.Component { constructor(props: any) { super(props); - this._editTitleScript = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); selectDoc(self);} `); + const script = ScriptField.MakeScript(`{setInPlace(self, 'editTitle', '${this._uniqueId}'); selectDoc(self);} `); + this._editTitleScript = script && (() => script); if (Doc.GetT(this.doc, "editTitle", "string", true) === "*") Doc.SetInPlace(this.doc, "editTitle", this._uniqueId, false); } @@ -368,13 +369,13 @@ class TreeView extends React.Component { } } - get onCheckedClick() { return this.props.onCheckedClick || ScriptCast(this.doc.onCheckedClick); } + get onCheckedClick() { return this.props.onCheckedClick || (() => ScriptCast(this.doc.onCheckedClick)); } @action bulletClick = (e: React.MouseEvent) => { - if (this.onCheckedClick && this.doc.type !== DocumentType.COL) { + if (this.onCheckedClick() && this.doc.type !== DocumentType.COL) { // this.props.document.treeViewChecked = this.props.document.treeViewChecked === "check" ? "x" : this.props.document.treeViewChecked === "x" ? undefined : "check"; - this.onCheckedClick.script.run({ + this.onCheckedClick()?.script.run({ this: this.doc.isTemplateForField && this.props.dataDoc ? this.props.dataDoc : this.doc, heading: this.props.containingCollection.title, checked: this.doc.treeViewChecked === "check" ? "x" : this.doc.treeViewChecked === "x" ? undefined : "check", @@ -388,7 +389,7 @@ class TreeView extends React.Component { @computed get renderBullet() { TraceMobx(); - const checked = this.doc.type === DocumentType.COL ? undefined : this.onCheckedClick ? (this.doc.treeViewChecked ?? "unchecked") : undefined; + const checked = this.doc.type === DocumentType.COL ? undefined : this.onCheckedClick() ? (this.doc.treeViewChecked ?? "unchecked") : undefined; return
{ treeViewPreventOpen: boolean, renderedIds: string[], libraryPath: Doc[] | undefined, - onCheckedClick: ScriptField | undefined, - onChildClick: ScriptField | undefined, + onCheckedClick?: () => ScriptField, + onChildClick?: () => ScriptField, ignoreFields: string[] | undefined ) { const viewSpecScript = Cast(containingCollection.viewSpecScript, ScriptField); @@ -658,8 +659,8 @@ class TreeView extends React.Component { export type collectionTreeViewProps = { treeViewHideTitle?: boolean; treeViewHideHeaderFields?: boolean; - onCheckedClick?: ScriptField; - onChildClick?: ScriptField; + onCheckedClick?: () => ScriptField; + onChildClick?: () => ScriptField; }; @observer @@ -797,6 +798,9 @@ export class CollectionTreeView extends CollectionSubView { console.log(e); } + onChildClick = () => { + return this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); + } render() { TraceMobx(); if (!(this.doc instanceof Doc)) return (null); @@ -839,7 +843,7 @@ export class CollectionTreeView extends CollectionSubView this.props.treeViewHideHeaderFields || BoolCast(this.doc.treeViewHideHeaderFields), BoolCast(this.doc.treeViewPreventOpen), [], this.props.LibraryPath, this.props.onCheckedClick, - this.props.onChildClick || ScriptCast(this.doc.onChildClick), this.props.ignoreFields) + this.onChildClick, this.props.ignoreFields) }
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index cbd1ac9af..5165a8f11 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -305,14 +305,16 @@ export class CollectionView extends Touchable onClicks.push({ description: `Edit ${func.name} script`, icon: "edit", event: (obj: any) => { - ScriptBox.EditButtonScript(func.name + "...", this.props.Document, func.key, obj.x, obj.y, { thisContainer: Doc.name }); + const alias = Doc.MakeAlias(this.props.Document); + DocUtils.makeCustomViewClicked(alias, undefined, func.key); + this.props.addDocTab(alias, "onRight"); } })); DocListCast(Cast(Doc.UserDoc()["clickFuncs-child"], Doc, null).data).forEach(childClick => onClicks.push({ description: `Set child ${childClick.title}`, icon: "edit", - event: () => this.props.Document[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)), + event: () => Doc.GetProto(this.props.Document)[StrCast(childClick.targetScriptKey)] = ObjectField.MakeCopy(ScriptCast(childClick.data)), })); !existingOnClick && cm.addItem({ description: "OnClick...", noexpand: true, subitems: onClicks, icon: "hand-point-right" }); @@ -470,7 +472,8 @@ export class CollectionView extends Touchable script : undefined; } @computed get filterView() { TraceMobx(); @@ -523,7 +526,7 @@ export class CollectionView extends Touchable (this.props.childClickScript || ScriptCast(this.Document.onChildClick)); } + @computed get onChildDoubleClickHandler() { return () => (this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick)); } @computed get backgroundActive() { return this.layoutDoc.isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); } backgroundHalo = () => BoolCast(this.Document.useClusters); parentActive = (outsideReaction: boolean) => this.props.active(outsideReaction) || this.backgroundActive ? true : false; @@ -1151,7 +1152,7 @@ export class CollectionFreeFormView extends CollectionSubView this._layoutElements = elements || [], { fireImmediately: true, name: "doLayout" }); - const handler = (e: Event) => this.handleDragging(e, (e as CustomEvent).detail); + const handler = (e: any) => this.handleDragging(e, (e as CustomEvent).detail); document.addEventListener("dashDragging", handler); } @@ -1159,7 +1160,7 @@ export class CollectionFreeFormView extends CollectionSubView this.handleDragging(e, (e as CustomEvent).detail); + const handler = (e: any) => this.handleDragging(e, (e as CustomEvent).detail); document.removeEventListener("dashDragging", handler); } diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index 188b88c41..b2e506dfa 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -31,7 +31,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { @observable private _rowHeight: Opt; // temporary store of row height to make change undoable @observable private _scroll: number = 0; // required to make sure the decorations box container updates on scroll - @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } + @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); } @computed get numCols() { return NumCast(this.props.Document.gridNumCols, 10); } @computed get rowHeight() { return this._rowHeight === undefined ? NumCast(this.props.Document.gridRowHeight, 100) : this._rowHeight; } diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index cd25c21b4..402e7563d 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -202,8 +202,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu } - @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } - @computed get onChildDoubleClickHandler() { return ScriptCast(this.Document.onChildDoubleClick); } + @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); } + @computed get onChildDoubleClickHandler() { return () => ScriptCast(this.Document.onChildDoubleClick); } addDocTab = (doc: Doc, where: string) => { diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index 51dcdcfe6..e4ef9b436 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -202,8 +202,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) } - @computed get onChildClickHandler() { return ScriptCast(this.Document.onChildClick); } - @computed get onChildDoubleClickHandler() { return ScriptCast(this.Document.onChildDoubleClick); } + @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); } + @computed get onChildDoubleClickHandler() { return () => ScriptCast(this.Document.onChildDoubleClick); } addDocTab = (doc: Doc, where: string) => { if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 11be4c2e7..e338d5203 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -11,7 +11,7 @@ import { InkTool } from '../../../fields/InkField'; import { listSpec } from "../../../fields/Schema"; import { SchemaHeaderField } from '../../../fields/SchemaHeaderField'; import { ScriptField } from '../../../fields/ScriptField'; -import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; +import { BoolCast, Cast, NumCast, StrCast, ScriptCast } from "../../../fields/Types"; import { TraceMobx } from '../../../fields/util'; import { GestureUtils } from '../../../pen-gestures/GestureUtils'; import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils, emptyPath } from "../../../Utils"; @@ -68,10 +68,10 @@ export interface DocumentViewProps { ignoreAutoHeight?: boolean; contextMenuItems?: () => { script: ScriptField, label: string }[]; rootSelected: (outsideReaction?: boolean) => boolean; // whether the root of a template has been selected - onClick?: ScriptField; - onDoubleClick?: ScriptField; - onPointerDown?: ScriptField; - onPointerUp?: ScriptField; + onClick?: () => ScriptField; + onDoubleClick?: () => ScriptField; + onPointerDown?: () => ScriptField; + onPointerUp?: () => ScriptField; treeViewDoc?: Doc; dropAction?: dropActionType; dragDivName?: string; @@ -127,10 +127,10 @@ export class DocumentView extends DocComponent(Docu @computed get freezeDimensions() { return this.props.FreezeDimensions; } @computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth, this.props.NativeWidth() || (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); } @computed get nativeHeight() { return NumCast(this.layoutDoc._nativeHeight, this.props.NativeHeight() || (this.freezeDimensions ? this.layoutDoc[HeightSym]() : 0)); } - @computed get onClickHandler() { return this.props.onClick || Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); } - @computed get onDoubleClickHandler() { return this.props.onDoubleClick || Cast(this.layoutDoc.onDoubleClick, ScriptField, null) || this.Document.onDoubleClick; } - @computed get onPointerDownHandler() { return this.props.onPointerDown ? this.props.onPointerDown : this.Document.onPointerDown; } - @computed get onPointerUpHandler() { return this.props.onPointerUp ? this.props.onPointerUp : this.Document.onPointerUp; } + @computed get onClickHandler() { return this.props.onClick?.() ? this.props.onClick : (() => Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null))); } + @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ? this.props.onDoubleClick : () => (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) || this.Document.onDoubleClick); } + @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ? this.props.onPointerDown : () => ScriptCast(this.Document.onPointerDown) } + @computed get onPointerUpHandler() { return this.props.onPointerUp ?? (() => ScriptCast(this.Document.onPointerUp)); } NativeWidth = () => this.nativeWidth; NativeHeight = () => this.nativeHeight; @@ -293,10 +293,10 @@ export class DocumentView extends DocComponent(Docu let stopPropagate = true; let preventDefault = true; !this.props.Document.isBackground && this.props.bringToFront(this.props.Document); - if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click + if (this._doubleTap && this.props.renderDepth && !this.onClickHandler()?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click if (!(e.nativeEvent as any).formattedHandled) { - if (this.onDoubleClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself - const func = () => this.onDoubleClickHandler.script.run({ + if (this.onDoubleClickHandler()?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself + const func = () => this.onDoubleClickHandler()?.script.run({ this: this.layoutDoc, self: this.rootDoc, thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey @@ -316,9 +316,9 @@ export class DocumentView extends DocComponent(Docu Doc.UnBrushDoc(this.props.Document); } } - } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself + } else if (this.onClickHandler()?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself //SelectionManager.DeselectAll(); - const func = () => this.onClickHandler.script.run({ + const func = () => this.onClickHandler()?.script.run({ this: this.layoutDoc, self: this.rootDoc, thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey @@ -553,8 +553,8 @@ export class DocumentView extends DocComponent(Docu onPointerUp = (e: PointerEvent): void => { this.cleanUpInteractions(); - if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { - this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log); + if (this.onPointerUpHandler()?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { + this.onPointerUpHandler()?.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log); document.removeEventListener("pointerup", this.onPointerUp); return; } diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 61a37ef8a..9dda644f3 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -3,7 +3,6 @@ import { ScriptField } from "./ScriptField"; import { Doc } from "./Doc"; import { DateField } from "./DateField"; import { SchemaHeaderField } from "./SchemaHeaderField"; -import { Schema } from "prosemirror-model"; export const documentSchema = createSchema({ // content properties -- cgit v1.2.3-70-g09d2 From 866561aa20aff0f570d31edf64eae36cd2d35279 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 14 Jul 2020 17:27:19 -0400 Subject: fixed onClickHandler stuff to use functions properly. fixed several linking to annotations/pushpins problems. --- src/client/documents/Documents.ts | 8 +- src/client/util/DocumentManager.ts | 4 +- src/client/util/LinkManager.ts | 11 ++- src/client/util/SettingsManager.tsx | 4 +- src/client/views/DocumentButtonBar.tsx | 2 +- src/client/views/MetadataEntryMenu.tsx | 96 ++++++---------------- src/client/views/collections/CollectionView.tsx | 7 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 10 +-- .../collectionFreeForm/FormatShapePane.tsx | 2 +- .../collectionFreeForm/InkOptionsMenu.tsx | 2 +- .../collectionGrid/CollectionGridView.tsx | 2 +- .../CollectionMulticolumnView.tsx | 5 +- .../CollectionMultirowView.tsx | 4 +- src/client/views/linking/LinkMenuGroup.tsx | 4 +- src/client/views/linking/LinkMenuItem.tsx | 5 +- src/client/views/nodes/DocumentLinksButton.tsx | 3 - src/client/views/nodes/DocumentView.tsx | 17 ++-- src/client/views/nodes/FieldView.tsx | 2 +- .../views/nodes/formattedText/RichTextMenu.tsx | 2 +- src/fields/documentSchemas.ts | 3 + 20 files changed, 78 insertions(+), 115 deletions(-) (limited to 'src/fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 90cef31d9..1fd533b62 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -102,6 +102,8 @@ export interface DocumentOptions { childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox or Buxton layout in tree view) childLayoutString?: string; // template string for collection to use to render its children hideFilterView?: boolean; // whether to hide the filter popout on collections + hideLinkButton?: boolean; // whether the blue link counter button should be hidden + hideAllLinks?: boolean; // whether all individual blue anchor dots should be hidden _columnsHideIfEmpty?: boolean; // whether stacking view column headings should be hidden isTemplateForField?: string; // the field key for which the containing document is a rendering template isTemplateDoc?: boolean; @@ -137,7 +139,7 @@ export interface DocumentOptions { lookupField?: ScriptField; // script that returns the value of a field. This script is passed the rootDoc, layoutDoc, field, and container of the document. see PresBox. "onDoubleClick-rawScript"?: string; // onDoubleClick script in raw text form "onChildDoubleClick-rawScript"?: string; // onChildDoubleClick script in raw text form - "onChildClick-rawScript"?: string // on ChildClick script in raw text form + "onChildClick-rawScript"?: string; // on ChildClick script in raw text form "onClick-rawScript"?: string; // onClick script in raw text form "onCheckedClick-rawScript"?: string; // onChecked script in raw text form "onCheckedClick-params"?: List; // parameter list for onChecked treeview functions @@ -779,7 +781,7 @@ export namespace Docs { export function FontIconDocument(options?: DocumentOptions) { - return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { ...(options || {}) }); + return InstanceFromProto(Prototypes.get(DocumentType.FONTICON), undefined, { hideLinkButton: true, ...(options || {}) }); } export function PresElementBoxDocument(options?: DocumentOptions) { @@ -912,6 +914,8 @@ export namespace DocUtils { if (target.doc === Doc.UserDoc()) return undefined; const linkDoc = Docs.Create.LinkDocument(source, target, { linkRelationship, layoutKey: "layout_linkView", description }, id); + linkDoc.linkDisplay = true; + linkDoc.hideAnhors = true; linkDoc.layout_linkView = Cast(Cast(Doc.UserDoc()["template-button-link"], Doc, null).dragFactory, Doc, null); Doc.GetProto(linkDoc).title = ComputedField.MakeFunction('self.anchor1?.title +" (" + (self.linkRelationship||"to") +") " + self.anchor2?.title'); diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 1fa5faeb3..b66e7fdc4 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -146,7 +146,7 @@ export class DocumentManager { }; const docView = getFirstDocView(targetDoc, originatingDoc); let annotatedDoc = await Cast(targetDoc.annotationOn, Doc); - if (annotatedDoc && !linkDoc?.isPushpin) { + if (annotatedDoc && !targetDoc?.isPushpin) { const first = getFirstDocView(annotatedDoc); if (first) { annotatedDoc = first.props.Document; @@ -156,7 +156,7 @@ export class DocumentManager { } } if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - if (linkDoc?.isPushpin) docView.props.Document.hidden = !docView.props.Document.hidden; + if (originatingDoc?.isPushpin) docView.props.Document.hidden = !docView.props.Document.hidden; else { docView.props.Document.hidden && (docView.props.Document.hidden = undefined); docView.props.focus(docView.props.Document, willZoom, undefined, focusAndFinish); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 50f3fc1d6..974744344 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -63,12 +63,17 @@ export class LinkManager { } // finds all links that contain the given anchor - public getAllRelatedLinks(anchor: Doc): Doc[] { + public getAllDirectLinks(anchor: Doc): Doc[] { const related = LinkManager.Instance.getAllLinks().filter(link => { const protomatch1 = Doc.AreProtosEqual(anchor, Cast(link.anchor1, Doc, null)); const protomatch2 = Doc.AreProtosEqual(anchor, Cast(link.anchor2, Doc, null)); return protomatch1 || protomatch2 || Doc.AreProtosEqual(link, anchor); }); + return related; + } + // finds all links that contain the given anchor + public getAllRelatedLinks(anchor: Doc): Doc[] { + const related = LinkManager.Instance.getAllDirectLinks(anchor); DocListCast(anchor[Doc.LayoutFieldKey(anchor) + "-annotations"]).map(anno => { related.push(...LinkManager.Instance.getAllRelatedLinks(anno)); }); @@ -208,4 +213,6 @@ export class LinkManager { } Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, - "creates a link to inputted document", "(doc: any)"); \ No newline at end of file + "returns all the links to the document or its annotations", "(doc: any)"); +Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); }, + "returns all the links directly to the document", "(doc: any)"); \ No newline at end of file diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index f7ca3942b..981ee698d 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -87,11 +87,11 @@ export default class SettingsManager extends React.Component<{}> { } @action googleAuthorize = (event: any) => { - GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true) + GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true); } @action hypothesisAuthorize = (event: any) => { - HypothesisAuthenticationManager.Instance.fetchAccessToken(true) + HypothesisAuthenticationManager.Instance.fetchAccessToken(true); } private get settingsInterface() { diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx index c188618f4..927c192cd 100644 --- a/src/client/views/DocumentButtonBar.tsx +++ b/src/client/views/DocumentButtonBar.tsx @@ -208,7 +208,7 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const view0 = this.view0; return !view0 ? (null) :
this.props.views().filter(dv => dv).map(dv => dv!.props.Document)} suggestWithFunction /> /* tfs: @bcz This might need to be the data document? */}> + content={ dv).map(dv => dv!.props.Document)} suggestWithFunction /> /* tfs: @bcz This might need to be the data document? */}>
e.stopPropagation()} > {}
diff --git a/src/client/views/MetadataEntryMenu.tsx b/src/client/views/MetadataEntryMenu.tsx index b0752ffb2..ca8a6e1d7 100644 --- a/src/client/views/MetadataEntryMenu.tsx +++ b/src/client/views/MetadataEntryMenu.tsx @@ -3,14 +3,14 @@ import "./MetadataEntryMenu.scss"; import { observer } from 'mobx-react'; import { observable, action, runInAction, trace, computed, IReactionDisposer, reaction } from 'mobx'; import { KeyValueBox } from './nodes/KeyValueBox'; -import { Doc, Field, DocListCastAsync } from '../../fields/Doc'; +import { Doc, Field, DocListCastAsync, DocListCast } from '../../fields/Doc'; import * as Autosuggest from 'react-autosuggest'; -import { undoBatch } from '../util/UndoManager'; +import { undoBatch, UndoManager } from '../util/UndoManager'; import { emptyFunction, emptyPath } from '../../Utils'; export type DocLike = Doc | Doc[] | Promise | Promise; export interface MetadataEntryProps { - docs: DocLike | (() => DocLike); + docs: Doc[]; onError?: () => boolean; suggestWithFunction?: boolean; } @@ -39,26 +39,13 @@ export class MetadataEntryMenu extends React.Component{ let onProto: boolean = false; let value: string | undefined = undefined; let docs = this.props.docs; - if (typeof docs === "function") { - if (this.props.suggestWithFunction) { - docs = docs(); - } else { - return; - } - } - docs = await docs; - if (docs instanceof Doc) { - await docs[this._currentKey]; - value = Field.toKeyValueString(docs, this._currentKey); - } else { - for (const doc of docs) { - const v = await doc[this._currentKey]; - onProto = onProto || !Object.keys(doc).includes(this._currentKey); - if (field === null) { - field = v; - } else if (v !== field) { - value = "multiple values"; - } + for (const doc of docs) { + const v = await doc[this._currentKey]; + onProto = onProto || !Object.keys(doc).includes(this._currentKey); + if (field === null) { + field = v; + } else if (v !== field) { + value = "multiple values"; } } if (value === undefined) { @@ -86,27 +73,16 @@ export class MetadataEntryMenu extends React.Component{ const script = KeyValueBox.CompileKVPScript(this._currentValue); if (!script) return; - let doc = this.props.docs; - if (typeof doc === "function") { - doc = doc(); - } - doc = await doc; - - let success: boolean; - if (doc instanceof Doc) { - success = KeyValueBox.ApplyKVPScript(doc, this._currentKey, script); - } else { - let childSuccess = true; - if (this._addChildren) { - for (const document of doc) { - const collectionChildren = await DocListCastAsync(document.data); - if (collectionChildren) { - childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script)); - } + let childSuccess = true; + if (this._addChildren) { + for (const document of this.props.docs) { + const collectionChildren = DocListCast(document.data); + if (collectionChildren) { + childSuccess = collectionChildren.every(c => KeyValueBox.ApplyKVPScript(c, this._currentKey, script)); } } - success = doc.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script)) && childSuccess; } + const success = this.props.docs.every(d => KeyValueBox.ApplyKVPScript(d, this._currentKey, script)) && childSuccess; if (!success) { if (this.props.onError) { if (this.props.onError()) { @@ -132,24 +108,12 @@ export class MetadataEntryMenu extends React.Component{ } } - getKeySuggestions = async (value: string): Promise => { + getKeySuggestions = (value: string) => { value = value.toLowerCase(); let docs = this.props.docs; - if (typeof docs === "function") { - if (this.props.suggestWithFunction) { - docs = docs(); - } else { - return []; - } - } - docs = await docs; - if (docs instanceof Doc) { - return Object.keys(docs).filter(key => key.toLowerCase().startsWith(value)); - } else { - const keys = new Set(); - docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); - return Array.from(keys).filter(key => key.toLowerCase().startsWith(value)); - } + const keys = new Set(); + docs.forEach(doc => Doc.allKeys(doc).forEach(key => keys.add(key))); + return Array.from(keys).filter(key => key.toLowerCase().startsWith(value)); } getSuggestionValue = (suggestion: string) => suggestion; @@ -157,9 +121,8 @@ export class MetadataEntryMenu extends React.Component{ return (null); } componentDidMount() { - this._suggestionDispser = reaction(() => this._currentKey, - () => this.getKeySuggestions(this._currentKey).then(action((s: string[]) => this._allSuggestions = s)), + () => this._allSuggestions = this.getKeySuggestions(this._currentKey), { fireImmediately: true }); } componentWillUnmount() { @@ -171,19 +134,8 @@ export class MetadataEntryMenu extends React.Component{ } private get considerChildOptions() { - let docSource = this.props.docs; - if (typeof docSource === "function") { - docSource = docSource(); - } - docSource = docSource as Doc[] | Doc; - if (docSource instanceof Doc) { - if (docSource._viewType === undefined) { - return (null); - } - } else if (Array.isArray(docSource)) { - if (!docSource.every(doc => doc._viewType !== undefined)) { - return null; - } + if (!this.props.docs.every(doc => doc._viewType !== undefined)) { + return null; } return (
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5165a8f11..6ab4645ea 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -140,17 +140,18 @@ export class CollectionView extends Touchable { const context = Cast(doc.context, Doc, null); - if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG) && - !DocListCast(doc.links).some(d => d.isPushpin)) { + if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) { const pushpin = Docs.Create.FontIconDocument({ icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7", _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null) }); + pushpin.isPushpin = true; + Doc.GetProto(pushpin).annotationOn = doc.annotationOn; + Doc.SetInPlace(doc, "annotationOn", undefined, true); Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin); const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", ""); const first = DocListCast(pushpin.links).find(d => d instanceof Doc); first && (first.hidden = true); - pushpinLink && (Doc.GetProto(pushpinLink).isPushpin = true); doc.displayTimecode = undefined; } doc.context = this.props.Document; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index f33b5371f..994f4ce6e 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -939,9 +939,9 @@ export class CollectionFreeFormView extends CollectionSubView (this.props.childClickScript || ScriptCast(this.Document.onChildClick)); } - @computed get onChildDoubleClickHandler() { return () => (this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick)); } @computed get backgroundActive() { return this.layoutDoc.isBackground && (this.props.ContainingCollectionView?.active() || this.props.active()); } + onChildClickHandler = () => this.props.childClickScript || ScriptCast(this.Document.onChildClick); + onChildDoubleClickHandler = () => this.props.childDoubleClickScript || ScriptCast(this.Document.onChildDoubleClick); backgroundHalo = () => BoolCast(this.Document.useClusters); parentActive = (outsideReaction: boolean) => this.props.active(outsideReaction) || this.backgroundActive ? true : false; getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps { @@ -1186,8 +1186,8 @@ export class CollectionFreeFormView extends CollectionSubView - (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt) + (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt); } @computed get selectedInk() { diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx index 15707ad9e..5d115df69 100644 --- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx @@ -128,7 +128,7 @@ export default class InkOptionsMenu extends AntimodeMenu { // doc.strokeBezier === 300 ? doc.strokeBezier = 0 : doc.strokeBezier = 300; break; case "dash": - doc.strokeDash = Number(value); + doc.strokeDash = value; default: break; } diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx index b2e506dfa..73d0ae374 100644 --- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx +++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx @@ -31,7 +31,7 @@ export class CollectionGridView extends CollectionSubView(GridSchema) { @observable private _rowHeight: Opt; // temporary store of row height to make change undoable @observable private _scroll: number = 0; // required to make sure the decorations box container updates on scroll - @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); } + onChildClickHandler = () => ScriptCast(this.Document.onChildClick); @computed get numCols() { return NumCast(this.props.Document.gridNumCols, 10); } @computed get rowHeight() { return this._rowHeight === undefined ? NumCast(this.props.Document.gridRowHeight, 100) : this._rowHeight; } diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx index 402e7563d..21d283547 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx @@ -202,9 +202,8 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu } - @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); } - @computed get onChildDoubleClickHandler() { return () => ScriptCast(this.Document.onChildDoubleClick); } - + onChildClickHandler = () => ScriptCast(this.Document.onChildClick); + onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick); addDocTab = (doc: Doc, where: string) => { if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx index e4ef9b436..d02088a6c 100644 --- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx +++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx @@ -202,8 +202,8 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument) } - @computed get onChildClickHandler() { return () => ScriptCast(this.Document.onChildClick); } - @computed get onChildDoubleClickHandler() { return () => ScriptCast(this.Document.onChildDoubleClick); } + onChildClickHandler = () => ScriptCast(this.Document.onChildClick); + onChildDoubleClickHandler = () => ScriptCast(this.Document.onChildDoubleClick); addDocTab = (doc: Doc, where: string) => { if (where === "inPlace" && this.layoutDoc.isInPlaceContainer) { diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx index 2f6b75437..2ae87ac13 100644 --- a/src/client/views/linking/LinkMenuGroup.tsx +++ b/src/client/views/linking/LinkMenuGroup.tsx @@ -11,6 +11,7 @@ import { DocumentView } from "../nodes/DocumentView"; import './LinkMenu.scss'; import { LinkMenuItem, StartLinkTargetsDrag } from "./LinkMenuItem"; import React = require("react"); +import { Cast } from "../../../fields/Types"; interface LinkMenuGroupProps { sourceDoc: Doc; @@ -66,7 +67,8 @@ export class LinkMenuGroup extends React.Component { render() { const groupItems = this.props.group.map(linkDoc => { - const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc); + const destination = LinkManager.Instance.getOppositeAnchor(linkDoc, this.props.sourceDoc) || + LinkManager.Instance.getOppositeAnchor(linkDoc, Cast(linkDoc.anchor2, Doc, null).annotationOn === this.props.sourceDoc ? Cast(linkDoc.anchor2, Doc, null) : Cast(linkDoc.anchor1, Doc, null)); if (destination && this.props.sourceDoc) { return { const eyeIcon = this.props.linkDoc.hidden ? "eye-slash" : "eye"; - let destinationIcon: string = "";; + let destinationIcon: FontAwesomeIconProps["icon"] = "question"; switch (this.props.destinationDoc.type) { case DocumentType.IMG: destinationIcon = "image"; break; case DocumentType.COMPARISON: destinationIcon = "columns"; break; @@ -205,7 +205,6 @@ export class LinkMenuItem extends React.Component { case DocumentType.SCRIPTING: destinationIcon = "terminal"; break; case DocumentType.IMPORT: destinationIcon = "cloud-upload-alt"; break; case DocumentType.DOCHOLDER: destinationIcon = "expand"; break; - default: "question"; } const title = StrCast(this.props.destinationDoc.title).length > 18 ? diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 83710cfbf..823e25471 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -101,8 +101,6 @@ export class DocumentLinksButton extends React.Component { if (linkDoc) { @@ -137,7 +135,6 @@ export class DocumentLinksButton extends React.Component { if (linkDoc) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 7d9c4da87..a6771443a 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -128,9 +128,9 @@ export class DocumentView extends DocComponent(Docu @computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth, this.props.NativeWidth() || (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); } @computed get nativeHeight() { return NumCast(this.layoutDoc._nativeHeight, this.props.NativeHeight() || (this.freezeDimensions ? this.layoutDoc[HeightSym]() : 0)); } @computed get onClickHandler() { return this.props.onClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null)); } - @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() || (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) || this.Document.onDoubleClick); } - @computed get onPointerDownHandler() { return this.props.onPointerDown?.() || ScriptCast(this.Document.onPointerDown) } - @computed get onPointerUpHandler() { return this.props.onPointerUp?.() || ScriptCast(this.Document.onPointerUp); } + @computed get onDoubleClickHandler() { return this.props.onDoubleClick?.() ?? (Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick); } + @computed get onPointerDownHandler() { return this.props.onPointerDown?.() ?? ScriptCast(this.Document.onPointerDown); } + @computed get onPointerUpHandler() { return this.props.onPointerUp?.() ?? ScriptCast(this.Document.onPointerUp); } NativeWidth = () => this.nativeWidth; NativeHeight = () => this.nativeHeight; onClickFunc = () => this.onClickHandler; @@ -298,7 +298,7 @@ export class DocumentView extends DocComponent(Docu if (this._doubleTap && this.props.renderDepth && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click if (!(e.nativeEvent as any).formattedHandled) { if (this.onDoubleClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself - const func = () => this.onDoubleClickHandler?.script.run({ + const func = () => this.onDoubleClickHandler.script.run({ this: this.layoutDoc, self: this.rootDoc, thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey @@ -320,7 +320,7 @@ export class DocumentView extends DocComponent(Docu } } else if (this.onClickHandler?.script && !StrCast(Doc.LayoutField(this.layoutDoc))?.includes("ScriptingBox")) { // bcz: hack? don't execute script if you're clicking on a scripting box itself //SelectionManager.DeselectAll(); - const func = () => this.onClickHandler?.script.run({ + const func = () => this.onClickHandler.script.run({ this: this.layoutDoc, self: this.rootDoc, thisContainer: this.props.ContainingCollectionDoc, shiftKey: e.shiftKey @@ -556,7 +556,7 @@ export class DocumentView extends DocComponent(Docu this.cleanUpInteractions(); if (this.onPointerUpHandler?.script && !InteractionUtils.IsType(e, InteractionUtils.PENTYPE)) { - this.onPointerUpHandler?.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log); + this.onPointerUpHandler.script.run({ self: this.rootDoc, this: this.layoutDoc }, console.log); document.removeEventListener("pointerup", this.onPointerUp); return; } @@ -644,7 +644,6 @@ export class DocumentView extends DocComponent(Docu const makeLink = action((linkDoc: Doc) => { LinkManager.currentLink = linkDoc; linkDoc.hidden = true; - linkDoc.linkDisplay = true; LinkCreatedBox.popupX = de.x; LinkCreatedBox.popupY = de.y - 33; @@ -1076,7 +1075,7 @@ export class DocumentView extends DocComponent(Docu layoutKey={this.finalLayoutKey} /> {this.layoutDoc.hideAllLinks ? (null) : this.allAnchors} {/* {this.allAnchors} */} - {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.props.dontRegisterView ? (null) : } + {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || this.layoutDoc.hideLinkButton || this.props.dontRegisterView ? (null) : }
); } @@ -1105,7 +1104,7 @@ export class DocumentView extends DocComponent(Docu return (this.props.treeViewDoc && this.props.LayoutTemplateString) || // render nothing for: tree view anchor dots this.layoutDoc.presBox || // presentationbox nodes this.props.dontRegisterView ? (null) : // view that are not registered - DocUtils.FilterDocs(DocListCast(this.Document.links), this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => + DocUtils.FilterDocs(LinkManager.Instance.getAllDirectLinks(this.Document), this.props.docFilters(), []).filter(d => !d.hidden && this.isNonTemporalLink).map((d, i) => ScriptField; dropAction: dropActionType; backgroundHalo?: () => boolean; docFilters: () => string[]; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 8da1f99b5..c8798d757 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -431,7 +431,7 @@ export default class RichTextMenu extends AntimodeMenu { const nextIsOL = this.view.state.selection.$from.nodeAfter?.type === schema.nodes.ordered_list; let inList: any = undefined; let fromList = -1; - let path: any = Array.from((this.view.state.selection.$from as any).path); + const path: any = Array.from((this.view.state.selection.$from as any).path); for (let i = 0; i < path.length; i++) { if (path[i]?.type === schema.nodes.ordered_list) { inList = path[i]; diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts index 9dda644f3..ddffb56c3 100644 --- a/src/fields/documentSchemas.ts +++ b/src/fields/documentSchemas.ts @@ -65,6 +65,7 @@ export const documentSchema = createSchema({ color: "string", // foreground color of document fitToBox: "boolean", // whether freeform view contents should be zoomed/panned to fill the area of the document view fontSize: "string", + hidden: "boolean", // whether a document should not be displayed isInkMask: "boolean", // is the document a mask (ie, sits on top of other documents, has an unbounded width/height that is dark, and content uses 'hard-light' mix-blend-mode to let other documents pop through) layout: "string", // this is the native layout string for the document. templates can be added using other fields and setting layoutKey below layoutKey: "string", // holds the field key for the field that actually holds the current lyoat @@ -87,6 +88,8 @@ export const documentSchema = createSchema({ onPointerUp: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) onDragStart: ScriptField, // script to run when document is dragged (without being selected). the script should return the Doc to be dropped. followLinkLocation: "string",// flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab, ) + hideLinkButton: "boolean", // whether the blue link counter button should be hidden + hideAllLinks: "boolean", // whether all individual blue anchor dots should be hidden isInPlaceContainer: "boolean",// whether the marked object will display addDocTab() calls that target "inPlace" destinations isLinkButton: "boolean", // whether document functions as a link follow button to follow the first link on the document when clicked isBackground: "boolean", // whether document is a background element and ignores input events (can only select with marquee) -- cgit v1.2.3-70-g09d2 From 3ad593cc8865d3fa1dc22bf403ad7cfaf1a751e6 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 15 Jul 2020 21:52:23 +0530 Subject: bugfix + cleanup --- src/client/util/GroupManager.scss | 25 -------- src/client/util/GroupManager.tsx | 4 -- src/client/util/GroupMemberView.scss | 10 --- src/client/util/GroupMemberView.tsx | 3 - src/client/util/SharingManager.scss | 30 --------- src/client/util/SharingManager.tsx | 106 +++++--------------------------- src/client/views/nodes/DocumentView.tsx | 22 +++---- src/fields/Doc.ts | 2 +- 8 files changed, 28 insertions(+), 174 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss index 8a2c616b1..34d4f40f8 100644 --- a/src/client/util/GroupManager.scss +++ b/src/client/util/GroupManager.scss @@ -1,8 +1,4 @@ -// @import "../views/globalCssVariables"; - .group-interface { - // background-color: whitesmoke !important; - // color: grey; width: 550px; height: 300px; @@ -12,21 +8,17 @@ flex-direction: column; height: 90%; justify-content: space-between; - // flex-basis: 30%; margin-left: 5px; input { border-radius: 5px; - // border: none; padding: 8px; min-width: 100%; - // margin: 4px 0 4px 0; border: 1px solid hsl(0, 0%, 80%); outline: none; height: 30; &:focus { - // border: unset; border: 2.5px solid #2684FF; } } @@ -43,18 +35,12 @@ } } - // .dialogue-box { - // width: 450; - // height: 300; - // } button { - // background: $lighter-alt-accent; align-self: center; outline: none; border-radius: 5px; border: 0px; - // color: #fcfbf7; text-transform: none; letter-spacing: 2px; font-size: 75%; @@ -94,10 +80,8 @@ p { font-size: 20px; text-align: left; - // margin: 0 0 20px 0; margin-right: 15px; color: black; - // width: 60%; } } @@ -112,14 +96,10 @@ } .group-body { - // display: flex; justify-content: space-between; - // max-height: 80%; height: 220; background-color: #e8e8e8; - // flex-direction: column; - // padding-left: 1em; padding-right: 1em; justify-content: space-around; text-align: left; @@ -129,17 +109,12 @@ .group-row { display: flex; - // position: relative; margin-bottom: 5px; min-height: 30px; - // border: 1px solid; - // border-radius: 10px; align-items: center; .group-name { - // position: relative; max-width: 65%; - // left: 10; margin: 0 10; color: black; } diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 2d8930660..12951f2ab 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -286,7 +286,6 @@ export default class GroupManager extends React.Component<{}> { */ @action createGroup = () => { - // this.createGroupModalOpen = true; if (!this.inputRef.current?.value) { alert("Please enter a group name"); return; @@ -410,9 +409,6 @@ export default class GroupManager extends React.Component<{}> {
this.currentGroup = group)}>
- {/* */}
)}
diff --git a/src/client/util/GroupMemberView.scss b/src/client/util/GroupMemberView.scss index a34e5b989..c609c5c7b 100644 --- a/src/client/util/GroupMemberView.scss +++ b/src/client/util/GroupMemberView.scss @@ -1,18 +1,12 @@ -// @import "../views/globalCssVariables"; - .editing-interface { - // background-color: whitesmoke !important; - // color: grey; width: 100%; height: 100%; - // color: black; hr { margin-top: 20; } button { - // background: $darker-alt-accent; outline: none; border-radius: 5px; border: 0px; @@ -78,7 +72,6 @@ .editing-contents { overflow-y: auto; - // max-height: 67%; height: 65%; width: 100%; color: black; @@ -89,11 +82,8 @@ align-items: center; margin-bottom: 10px; position: relative; - // border: 1px solid; - // border-radius: 10px; .user-email { - // position: relative; min-width: 65%; word-break: break-all; padding: 0 5; diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx index ebe9830ba..f20670c4e 100644 --- a/src/client/util/GroupMemberView.tsx +++ b/src/client/util/GroupMemberView.tsx @@ -28,9 +28,6 @@ export default class GroupMemberView extends React.Component !(JSON.parse(StrCast(this.props.group.members)) as string[]).includes(option.value)) : []; - console.log(this.props.group, options); - console.log(GroupManager.Instance.options); - return (!this.props.group ? null :
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 572b94ffb..130785672 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -1,16 +1,7 @@ -// @import "../views/globalCssVariables"; - .sharing-interface { - // display: flex; - // flex-direction: column; width: 600px; height: 360px; - // .dialogue-box { - // width: 450; - // height: 300; - // } - .overlay { transform: translate(-20px, -20px); } @@ -87,7 +78,6 @@ .users-list { font-style: italic; background: #e8e8e8; - // border: 1px solid black; padding-left: 10px; padding-right: 10px; overflow-y: scroll; @@ -98,7 +88,6 @@ align-items: center; text-align: center; justify-content: center; - // color: red; color: black; height: 250px; margin: 0 2; @@ -113,7 +102,6 @@ } button { - // background: $darker-alt-accent; outline: none; border-radius: 5px; border: 0px; @@ -135,8 +123,6 @@ p { font-size: 20px; text-align: left; - // font-style: italic; - // padding: 0; margin: 0 0 20px 0; color: black; } @@ -174,8 +160,6 @@ -ms-user-select: none; user-select: none; width: 100%; - // min-width: 700px; - // max-width: 700px; text-align: left; font-style: normal; font-size: 14; @@ -249,18 +233,4 @@ padding-top: 12px; } } - - // .close-button { - // border-radius: 5px; - // margin-top: 20px; - // padding: 10px 0; - // background: aliceblue; - // transition: 0.5s ease all; - // border: 1px solid; - // border-color: aliceblue; - // } - - // .close-button:hover { - // border-color: black; - // } } \ No newline at end of file diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index be86b183f..8d4e508ac 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -36,13 +36,6 @@ export enum SharingPermissions { None = "Not Shared" } -// const ColorMapping = new Map([ -// [SharingPermissions.None, "red"], -// [SharingPermissions.View, "maroon"], -// [SharingPermissions.Add, "blue"], -// [SharingPermissions.Edit, "green"] -// ]); - interface GroupOptions { label: string; options: UserOptions[]; @@ -67,10 +60,9 @@ export default class SharingManager extends React.Component<{}> { public static Instance: SharingManager; @observable private isOpen = false; @observable private users: ValidatedUser[] = []; - // @observable private groups: Doc[] = []; @observable private targetDoc: Doc | undefined; @observable private targetDocView: DocumentView | undefined; - @observable private copied = false; + // @observable private copied = false; @observable private dialogueBoxOpacity = 1; @observable private overlayOpacity = 0.4; @observable private selectedUsers: UserOptions[] | null = null; @@ -90,32 +82,20 @@ export default class SharingManager extends React.Component<{}> { this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; - // if (!this.sharingDoc) { - // this.sharingDoc = new Doc; - // } })); - // runInAction(() => this.groups = GroupManager.Instance.getAllGroups()); } public close = action(() => { this.isOpen = false; this.users = []; setTimeout(action(() => { - this.copied = false; + // this.copied = false; DictationOverlay.Instance.hasActiveModal = false; this.targetDoc = undefined; }), 500); }); - // private get sharingDoc() { - // return this.targetDoc ? Cast(this.targetDoc[SharingKey], Doc) as Doc : undefined; - // } - - // private set sharingDoc(value: Doc | undefined) { - // this.targetDoc && (this.targetDoc[SharingKey] = value); - // } - constructor(props: {}) { super(props); SharingManager.Instance = this; @@ -152,7 +132,6 @@ export default class SharingManager extends React.Component<{}> { Doc.GetProto(target)[ACL] = permission; group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]); - // group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List).push(target) : group.docsShared = new List([target]); users.forEach(({ notificationDoc }) => { DocListCastAsync(notificationDoc[storage]).then(resolved => { @@ -171,7 +150,6 @@ export default class SharingManager extends React.Component<{}> { DocListCastAsync(user.notificationDoc[storage]).then(resolved => Doc.IndexOf(doc, resolved!) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc)); }); }); - // DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc)); } } @@ -184,7 +162,6 @@ export default class SharingManager extends React.Component<{}> { DocListCastAsync(user.notificationDoc[storage]).then(resolved => Doc.IndexOf(doc, resolved!) !== -1 && Doc.RemoveDocFromList(user.notificationDoc, storage, doc)); }); }); - // DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc)); } } @@ -208,14 +185,10 @@ export default class SharingManager extends React.Component<{}> { setInternalSharing = (recipient: ValidatedUser, permission: string) => { const { user, notificationDoc } = recipient; const target = this.targetDoc!; - // const manager = this.sharingDoc!; const key = user.email.replace('.', '_'); - // const key = user.userDocumentId; const ACL = `ACL-${key}`; - // const permissions: { [key: string]: number } = target[ACL] ? JSON.parse(StrCast(target[ACL])) : {}; - target[ACL] = permission; Doc.GetProto(target)[ACL] = permission; @@ -228,47 +201,12 @@ export default class SharingManager extends React.Component<{}> { } else { DocListCastAsync(notificationDoc[storage]).then(resolved => { - Doc.IndexOf(target, resolved!) === -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); + Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); }); } } - - // let metadata = await DocCastAsync(manager[key]); - // const permissions: { [key: string]: number } = metadata?.permissions ? JSON.parse(StrCast(metadata.permissions)) : {}; - // permissions[StrCast(group ? group.groupName : Doc.CurrentUserEmail)] = parseInt(HierarchyMapping.get(permission)!); - // const max = Math.max(...Object.values(permissions)); - - // switch (max) { - // case 0: - // // if (metadata) { - // // const sharedAlias = (await DocCastAsync(metadata.sharedAlias))!; - // // Doc.RemoveDocFromList(notificationDoc, storage, sharedAlias); - // // manager[key] = undefined; - // // } - // Doc.RemoveDocFromList(notificationDoc, storage, target); - // break; - - // case 1: case 2: case 3: - - // Doc.AddDocToList(notificationDoc, storage, target); - - // if (!metadata) { - // metadata = new Doc; - // const sharedAlias = Doc.MakeAlias(target); - // Doc.AddDocToList(notificationDoc, storage, target); - // metadata.sharedAlias = sharedAlias; - // manager[key] = metadata; - // } - // metadata.permissions = JSON.stringify(permissions); - // // metadata.usersShared = JSON.stringify(keys); - // break; - // } - - // if (metadata) metadata.maxPermission = HierarchyMapping.get(`${max}`); - - // private setExternalSharing = (permission: string) => { // const sharingDoc = this.sharingDoc; // if (!sharingDoc) { @@ -277,20 +215,20 @@ export default class SharingManager extends React.Component<{}> { // sharingDoc[PublicKey] = permission; // } - private get sharingUrl() { - if (!this.targetDoc) { - return undefined; - } - const baseUrl = Utils.prepend("/doc/" + this.targetDoc[Id]); - return `${baseUrl}?sharing=true`; - } + // private get sharingUrl() { + // if (!this.targetDoc) { + // return undefined; + // } + // const baseUrl = Utils.prepend("/doc/" + this.targetDoc[Id]); + // return `${baseUrl}?sharing=true`; + // } - copy = action(() => { - if (this.sharingUrl) { - Utils.CopyText(this.sharingUrl); - this.copied = true; - } - }); + // copy = action(() => { + // if (this.sharingUrl) { + // Utils.CopyText(this.sharingUrl); + // this.copied = true; + // } + // }); private get sharingOptions() { return Object.values(SharingPermissions).map(permission => { @@ -394,14 +332,7 @@ export default class SharingManager extends React.Component<{}> { const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { // can't use async here const userKey = user.email.replace('.', '_'); - // const userKey = user.userDocumentId; const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None); - // const color = ColorMapping.get(permissions); - - // console.log(manager); - // const metadata = manager[userKey] as Doc; - // const usersShared = StrCast(metadata?.usersShared, ""); - // console.log(usersShared) return permissions === SharingPermissions.None || user.email === this.targetDoc?.author ? null : (
{ className={"container"} > {user.email} - {/*
{usersShared}
*/}
this.setInternalGroupSharing(group, e.currentTarget.value)} > {this.sharingOptions} @@ -582,7 +509,6 @@ export default class SharingManager extends React.Component<{}> { } render() { - // console.log(this.sharingDoc); return ( (Docu !Doc.UserDoc().novice && helpItems.push({ description: "Show Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "layer-group" }); cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); - const existingAcls = cm.findByDescription("Privacy..."); - const aclItems: ContextMenuProps[] = existingAcls && "subitems" in existingAcls ? existingAcls.subitems : []; - aclItems.push({ description: "Make Add Only", event: () => this.setAcl("addOnly"), icon: "concierge-bell" }); - aclItems.push({ description: "Make Read Only", event: () => this.setAcl("readOnly"), icon: "concierge-bell" }); - aclItems.push({ description: "Make Private", event: () => this.setAcl("ownerOnly"), icon: "concierge-bell" }); - aclItems.push({ description: "Make Editable", event: () => this.setAcl("write"), icon: "concierge-bell" }); - aclItems.push({ description: "Test Private", event: () => this.testAcl("ownerOnly"), icon: "concierge-bell" }); - aclItems.push({ description: "Test Readonly", event: () => this.testAcl("readOnly"), icon: "concierge-bell" }); - !existingAcls && cm.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" }); - - cm.addItem({ description: `${getPlaygroundMode() ? "Disable" : "Enable"} playground mode`, event: togglePlaygroundMode, icon: "concierge-bell" }); + // const existingAcls = cm.findByDescription("Privacy..."); + // const aclItems: ContextMenuProps[] = existingAcls && "subitems" in existingAcls ? existingAcls.subitems : []; + // aclItems.push({ description: "Make Add Only", event: () => this.setAcl(SharingPermissions.Add), icon: "concierge-bell" }); + // aclItems.push({ description: "Make Read Only", event: () => this.setAcl(SharingPermissions.View), icon: "concierge-bell" }); + // aclItems.push({ description: "Make Private", event: () => this.setAcl(SharingPermissions.None), icon: "concierge-bell" }); + // aclItems.push({ description: "Make Editable", event: () => this.setAcl(SharingPermissions.Edit), icon: "concierge-bell" }); + // aclItems.push({ description: "Test Private", event: () => this.testAcl(SharingPermissions.None), icon: "concierge-bell" }); + // aclItems.push({ description: "Test Readonly", event: () => this.testAcl(SharingPermissions.View), icon: "concierge-bell" }); + // !existingAcls && cm.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" }); + + // cm.addItem({ description: `${getPlaygroundMode() ? "Disable" : "Enable"} playground mode`, event: togglePlaygroundMode, icon: "concierge-bell" }); // const recommender_subitems: ContextMenuProps[] = []; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 8ab4735a7..5dfc14a4a 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -109,7 +109,7 @@ const AclMap = new Map([ ]); export function fetchProto(doc: Doc) { - if (doc.author !== Doc.CurrentUserEmail) { // storing acls for groups needs to be extended here - AclSym should store a datastructure that stores information about permissions + if (doc.author !== Doc.CurrentUserEmail) { untracked(() => { const permissions: { [key: string]: symbol } = {}; -- cgit v1.2.3-70-g09d2 From 7543ca061700fda8286e6dd3f4374a877ccf929c Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Thu, 16 Jul 2020 13:00:12 +0530 Subject: can't change acl field to non-acl (through kvp) now + added playground mode button to settings --- src/client/util/SettingsManager.scss | 2 ++ src/client/util/SettingsManager.tsx | 13 +++++++++++-- src/client/util/SharingManager.tsx | 2 -- src/client/views/nodes/DocumentView.tsx | 2 +- src/fields/util.ts | 3 +++ 5 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index 6d394a38d..c1627e69f 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -52,6 +52,7 @@ .settings-body { display: flex; justify-content: space-between; + margin-top: -10; .settings-type { display: flex; @@ -105,6 +106,7 @@ text-transform: uppercase; letter-spacing: 2px; font-size: 120%; + margin-top: 0; } .container { diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index d54a39943..9d91568cf 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -14,8 +14,9 @@ import { Doc } from "../../fields/Doc"; import GroupManager from "./GroupManager"; import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; +import { togglePlaygroundMode } from "../../fields/util"; -library.add(fa.faWindowClose); +library.add(fa.faTimes); @observer export default class SettingsManager extends React.Component<{}> { @@ -26,6 +27,7 @@ export default class SettingsManager extends React.Component<{}> { @observable private settingsContent = "password"; @observable private errorText = ""; @observable private successText = ""; + @observable private playgroundMode = false; private curr_password_ref = React.createRef(); private new_password_ref = React.createRef(); private new_confirm_ref = React.createRef(); @@ -95,19 +97,26 @@ export default class SettingsManager extends React.Component<{}> { HypothesisAuthenticationManager.Instance.fetchAccessToken(true) } + @action + togglePlaygroundMode = () => { + togglePlaygroundMode(); + this.playgroundMode = !this.playgroundMode; + } + private get settingsInterface() { return (

settings

- +
+ ; + return {StrCast(this.layoutDoc.toolTip)}
}> + + ; } } \ No newline at end of file diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 9890ef2c1..3c7c58126 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -319,7 +319,7 @@ export default class RichTextMenu extends AntimodeMenu { } destroy() { - !this.TextView.props.isSelected(false) && this.fadeOut(true); + !this.TextView?.props.isSelected(false) && this.fadeOut(true); } @action @@ -657,7 +657,7 @@ export default class RichTextMenu extends AntimodeMenu { @action toggleColorDropdown() { this.showColorDropdown = !this.showColorDropdown; } @action setActiveColor(color: string) { this.activeFontColor = color; } - get TextView() { return (this.view as any).TextView as FormattedTextBox; } + get TextView() { return (this.view as any)?.TextView as FormattedTextBox; } createColorButton() { const self = this; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 7aa1d528d..3ad9f4e41 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -899,9 +899,12 @@ export namespace Doc { } export function getDocTemplate(doc?: Doc) { - return doc?.isTemplateDoc ? doc : - Cast(doc?.dragFactory, Doc, null)?.isTemplateDoc ? doc?.dragFactory : - Cast(doc?.layout, Doc, null)?.isTemplateDoc ? doc?.layout : undefined; + return !doc ? undefined : + doc.isTemplateDoc ? doc : + Cast(doc.dragFactory, Doc, null)?.isTemplateDoc ? doc.dragFactory : + Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc ? + (Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc ? Doc.Layout(doc).proto : Doc.Layout(doc)) : + undefined; } export function matchFieldValue(doc: Doc, key: string, value: any): boolean { -- cgit v1.2.3-70-g09d2 From 7b7d83f6f7070334fdfc4dd7cca03699b8e21078 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 20 Jul 2020 19:21:54 +0530 Subject: fixed some addonly stuff + added annotations to playground fields + recursively distributes acls + some modal stuff --- src/client/apis/GoogleAuthenticationManager.tsx | 7 +-- .../apis/HypothesisAuthenticationManager.tsx | 6 ++- src/client/util/GroupManager.scss | 2 +- src/client/util/GroupManager.tsx | 6 +-- src/client/util/SettingsManager.tsx | 4 +- src/client/util/SharingManager.tsx | 58 ++++++++++++++++++---- src/client/views/DocComponent.tsx | 26 ++++++++-- src/client/views/MainView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 25 +++++++++- src/fields/Doc.ts | 14 +++--- src/fields/util.ts | 21 ++++---- 11 files changed, 128 insertions(+), 43 deletions(-) (limited to 'src/fields') diff --git a/src/client/apis/GoogleAuthenticationManager.tsx b/src/client/apis/GoogleAuthenticationManager.tsx index 5a2bdb13b..117d1fa1e 100644 --- a/src/client/apis/GoogleAuthenticationManager.tsx +++ b/src/client/apis/GoogleAuthenticationManager.tsx @@ -146,7 +146,7 @@ export default class GoogleAuthenticationManager extends React.Component<{}> { private get dialogueBoxStyle() { const borderColor = this.success === undefined ? "black" : this.success ? "green" : "red"; - return { borderColor, transition: "0.2s borderColor ease" }; + return { borderColor, transition: "0.2s borderColor ease", zIndex: 1002 }; } render() { @@ -155,9 +155,10 @@ export default class GoogleAuthenticationManager extends React.Component<{}> { isDisplayed={this.openState} interactive={true} contents={this.renderPrompt} - overlayDisplayedOpacity={0.9} + // overlayDisplayedOpacity={0.9} dialogueBoxStyle={this.dialogueBoxStyle} - closeOnExternalClick={() => this.isOpen = false} + overlayStyle={{ zIndex: 1001 }} + closeOnExternalClick={action(() => this.isOpen = false)} /> ); } diff --git a/src/client/apis/HypothesisAuthenticationManager.tsx b/src/client/apis/HypothesisAuthenticationManager.tsx index a7fcf86a4..c3e8d2fff 100644 --- a/src/client/apis/HypothesisAuthenticationManager.tsx +++ b/src/client/apis/HypothesisAuthenticationManager.tsx @@ -138,7 +138,7 @@ export default class HypothesisAuthenticationManager extends React.Component<{}> private get dialogueBoxStyle() { const borderColor = this.success === undefined ? "black" : this.success ? "green" : "red"; - return { borderColor, transition: "0.2s borderColor ease" }; + return { borderColor, transition: "0.2s borderColor ease", zIndex: 1002 }; } render() { @@ -147,8 +147,10 @@ export default class HypothesisAuthenticationManager extends React.Component<{}> isDisplayed={this.openState} interactive={true} contents={this.renderPrompt} - overlayDisplayedOpacity={0.9} + // overlayDisplayedOpacity={0.9} dialogueBoxStyle={this.dialogueBoxStyle} + overlayStyle={{ zIndex: 1001 }} + closeOnExternalClick={action(() => this.isOpen = false)} /> ); } diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss index 34d4f40f8..51e4fa9e2 100644 --- a/src/client/util/GroupManager.scss +++ b/src/client/util/GroupManager.scss @@ -1,5 +1,5 @@ .group-interface { - width: 550px; + width: 380px; height: 300px; .dialogue-box { diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 12951f2ab..2e5ecc543 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -354,7 +354,7 @@ export default class GroupManager extends React.Component<{}> { isDisplayed={this.createGroupModalOpen} interactive={true} contents={contents} - dialogueBoxStyle={{ width: "70%", height: "70%" }} + dialogueBoxStyle={{ width: "90%", height: "70%" }} closeOnExternalClick={action(() => this.createGroupModalOpen = false)} /> ); @@ -424,8 +424,8 @@ export default class GroupManager extends React.Component<{}> { contents={this.groupInterface} isDisplayed={this.isOpen} interactive={true} - dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity} - overlayDisplayedOpacity={this.overlayOpacity} + dialogueBoxStyle={{ zIndex: 1002 }} + overlayStyle={{ zIndex: 1001 }} closeOnExternalClick={this.close} /> ); diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index fc5fdd869..90d59aa51 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -119,10 +119,10 @@ export default class SettingsManager extends React.Component<{}> { + -
{this.settingsContent === "password" ?
@@ -155,8 +155,6 @@ export default class SettingsManager extends React.Component<{}> { contents={this.settingsInterface} isDisplayed={this.isOpen} interactive={true} - dialogueBoxDisplayedOpacity={this.dialogueBoxOpacity} - overlayDisplayedOpacity={this.overlayOpacity} closeOnExternalClick={this.close} /> ); diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index fe7324d5c..8b3ac2613 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,13 +1,12 @@ import { observable, runInAction, action } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; -import { Doc, Opt, DocListCastAsync } from "../../fields/Doc"; +import { Doc, Opt, DocListCastAsync, DataSym, DocListCast } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; import { Utils } from "../../Utils"; import "./SharingManager.scss"; -import { Id } from "../../fields/FieldSymbols"; import { observer } from "mobx-react"; import { library } from '@fortawesome/fontawesome-svg-core'; import * as fa from '@fortawesome/free-solid-svg-icons'; @@ -82,6 +81,7 @@ export default class SharingManager extends React.Component<{}> { this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; + this.permissions = SharingPermissions.Edit; })); } @@ -127,9 +127,11 @@ export default class SharingManager extends React.Component<{}> { const target = this.targetDoc!; const ACL = `ACL-${StrCast(group.groupName)}`; + // fix this - not needed (here and setinternalsharing and removegroup) + // target[ACL] = permission; + // Doc.GetProto(target)[ACL] = permission; - target[ACL] = permission; - Doc.GetProto(target)[ACL] = permission; + this.distributeAcls(ACL, permission as SharingPermissions); group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]); @@ -170,7 +172,9 @@ export default class SharingManager extends React.Component<{}> { DocListCastAsync(group.docsShared).then(resolved => { resolved?.forEach(doc => { const ACL = `ACL-${StrCast(group.groupName)}`; - doc[ACL] = "Not Shared"; + // doc[ACL] = doc[DataSym][ACL] = "Not Shared"; + + this.distributeAcls(ACL, SharingPermissions.None, doc); const members: string[] = JSON.parse(StrCast(group.members)); const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); @@ -189,8 +193,10 @@ export default class SharingManager extends React.Component<{}> { const ACL = `ACL-${key}`; - target[ACL] = permission; - Doc.GetProto(target)[ACL] = permission; + // target[ACL] = permission; + // Doc.GetProto(target)[ACL] = permission; + + this.distributeAcls(ACL, permission as SharingPermissions); if (permission !== SharingPermissions.None) { DocListCastAsync(notificationDoc[storage]).then(resolved => { @@ -202,6 +208,40 @@ export default class SharingManager extends React.Component<{}> { Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); }); } + } + + @action + distributeAcls = (key: string, acl: SharingPermissions, doc?: Doc) => { + const target = doc ? doc : this.targetDoc!; + const dataDoc = target[DataSym]; + target[key] = acl; + if (dataDoc) dataDoc[key] = acl; + // dataDoc[key] = target[key] = acl; + // next line distributes the acl to all children of the target + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { + if (d.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, d); + d[key] = acl; + } + const data = d[DataSym]; + if (data && data.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, data); + data[key] = acl; + } + }); + + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { + if (d.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, d); + d[key] = acl; + } + const data = d[DataSym]; + if (data && data.author === Doc.CurrentUserEmail) { + this.distributeAcls(key, acl, data); + data[key] = acl; + } + console.log(d, d[DataSym]); + }); } @@ -308,9 +348,9 @@ export default class SharingManager extends React.Component<{}> { const groupList = GroupManager.Instance?.getAllGroups() || []; const sortedUsers = this.users.sort(this.sortUsers) - .map(({ user: { email } }) => ({ label: email, value: "!indType/" + email })); + .map(({ user: { email } }) => ({ label: email, value: indType + email })); const sortedGroups = groupList.sort(this.sortGroups) - .map(({ groupName }) => ({ label: StrCast(groupName), value: "!groupType/" + StrCast(groupName) })); + .map(({ groupName }) => ({ label: StrCast(groupName), value: groupType + StrCast(groupName) })); const options: GroupOptions[] = GroupManager.Instance ? [ diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index eb58d8a3e..8740d17c2 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc, Opt, DataSym, DocListCast, AclReadonly, AclAddonly } from '../../fields/Doc'; +import { Doc, Opt, DataSym, DocListCast, AclReadonly, AclAddonly, AclPrivate, AclEdit, AclSym } from '../../fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast, BoolCast, ScriptCast } from '../../fields/Types'; @@ -7,7 +7,8 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { List } from '../../fields/List'; import { DateField } from '../../fields/DateField'; import { ScriptField } from '../../fields/ScriptField'; -import { GetEffectiveAcl } from '../../fields/util'; +import { GetEffectiveAcl, getPlaygroundMode } from '../../fields/util'; +import { SharingPermissions } from '../util/SharingManager'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -92,6 +93,13 @@ export function ViewBoxAnnotatableComponent

([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit] + ]); + lookupField = (field: string) => ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result; styleFromLayoutString = (scale: number) => { @@ -139,11 +147,21 @@ export function ViewBoxAnnotatableComponent

!docList.includes(d)); const effectiveAcl = GetEffectiveAcl(this.dataDoc); + + if (this.props.Document[AclSym]) { + added.forEach(d => { + const dataDoc = d[DataSym]; + dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + dataDoc[key] = d[key] = this.AclMap.get(value); + } + }); + } if (added.length) { - if (effectiveAcl === AclReadonly) { + if (effectiveAcl === AclReadonly && !getPlaygroundMode()) { return false; } else if (effectiveAcl === AclAddonly) { - added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); + added.map(doc => console.log(Doc.AddDocToList(targetDataDoc, this.annotationKey, doc))); } else { added.map(doc => doc.context = this.props.Document); targetDataDoc[this.annotationKey] = new List([...docList, ...added]); diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5c6781f4c..61d2246db 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -91,7 +91,7 @@ export class MainView extends React.Component { public isPointerDown = false; componentDidMount() { - DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus"]); // can play with these fields on someone else's + DocServer.setPlaygroundFields(["dataTransition", "_viewTransition", "_panX", "_panY", "_viewScale", "_viewType", "_chromeStatus", "data-annotations"]); // can play with these fields on someone else's const tag = document.createElement('script'); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 50d66c567..17567ea73 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -8,7 +8,7 @@ import * as React from 'react'; import Lightbox from 'react-image-lightbox-with-rotate'; import 'react-image-lightbox-with-rotate/style.css'; // This only needs to be imported once in your app import { DateField } from '../../../fields/DateField'; -import { AclAddonly, AclReadonly, DataSym, Doc, DocListCast, Field, Opt, AclEdit } from '../../../fields/Doc'; +import { AclAddonly, AclReadonly, DataSym, Doc, DocListCast, Field, Opt, AclEdit, AclSym, AclPrivate } from '../../../fields/Doc'; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; import { ObjectField } from '../../../fields/ObjectField'; @@ -48,6 +48,7 @@ import { CollectionTimeView } from './CollectionTimeView'; import { CollectionTreeView } from "./CollectionTreeView"; import './CollectionView.scss'; import CollectionMenu from './CollectionMenu'; +import { SharingPermissions } from '../../util/SharingManager'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -106,6 +107,13 @@ export class CollectionView extends Touchable([ + [AclPrivate, SharingPermissions.None], + [AclReadonly, SharingPermissions.View], + [AclAddonly, SharingPermissions.Add], + [AclEdit, SharingPermissions.Edit] + ]); + get collectionViewType(): CollectionViewType | undefined { const viewField = StrCast(this.props.Document._viewType); if (CollectionView._safeMode) { @@ -128,11 +136,26 @@ export class CollectionView extends Touchable !docList.includes(d)); const effectiveAcl = GetEffectiveAcl(this.props.Document); + if (this.props.Document[AclSym]) { + // change so it only adds if more restrictive + added.forEach(d => { + console.log(d[Id]); + const dataDoc = d[DataSym]; + console.log(dataDoc[Id]); + for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + dataDoc[key] = d[key] = this.AclMap.get(value); + } + dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + + }); + } + if (added.length) { if (effectiveAcl === AclReadonly && !getPlaygroundMode()) { return false; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5dfc14a4a..ef57171bf 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -109,15 +109,15 @@ const AclMap = new Map([ ]); export function fetchProto(doc: Doc) { - if (doc.author !== Doc.CurrentUserEmail) { - untracked(() => { - const permissions: { [key: string]: symbol } = {}; + // if (doc.author !== Doc.CurrentUserEmail) { + untracked(() => { + const permissions: { [key: string]: symbol } = {}; - Object.keys(doc).filter(key => key.startsWith("ACL")).forEach(key => permissions[key] = AclMap.get(StrCast(doc[key]))!); + Object.keys(doc).filter(key => key.startsWith("ACL")).forEach(key => permissions[key] = AclMap.get(StrCast(doc[key]))!); - if (Object.keys(permissions).length) doc[AclSym] = permissions; - }); - } + if (Object.keys(permissions).length) doc[AclSym] = permissions; + }); + // } if (doc.proto instanceof Promise) { doc.proto.then(fetchProto); diff --git a/src/fields/util.ts b/src/fields/util.ts index 6d2d715bd..ee01f6213 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -129,28 +129,31 @@ export function setGroups(groups: string[]) { export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclEdit; - const HierarchyMapping = new Map([ - [AclPrivate, 0], - [AclReadonly, 1], - [AclAddonly, 2], - [AclEdit, 3] - ]); - if (!target[AclSym] && target instanceof Doc) { fetchProto(target); } + if (target[AclSym] && Object.keys(target[AclSym]).length) { - if (target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit; + // console.log(target[AclSym]); + + if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit; if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; - if (target[AclSym].ACL) return target[AclSym].ACL; + // if (target[AclSym].ACL) return target[AclSym].ACL; let effectiveAcl = AclPrivate; let aclPresent = false; + const HierarchyMapping = new Map([ + [AclPrivate, 0], + [AclReadonly, 1], + [AclAddonly, 2], + [AclEdit, 3] + ]); + for (const [key, value] of Object.entries(target[AclSym])) { if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) { if (HierarchyMapping.get(value as symbol)! >= HierarchyMapping.get(effectiveAcl)!) { -- cgit v1.2.3-70-g09d2 From a8251abdaf57a3f02de46b434126caeb83df96ec Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 20 Jul 2020 10:35:33 -0400 Subject: added standard static ScriptFields to avoid extra compiles --- src/client/util/CurrentUserUtils.ts | 52 ++++++++++++++++++++++++------------- src/fields/ScriptField.ts | 23 +++++++++++++++- 2 files changed, 56 insertions(+), 19 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 58d3848a3..4b8c342f1 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -4,7 +4,7 @@ import { Utils } from "../../Utils"; import { DocServer } from "../DocServer"; import { Docs, DocumentOptions, DocUtils } from "../documents/Documents"; import { UndoManager } from "./UndoManager"; -import { Doc, DocListCast, DocListCastAsync } from "../../fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, DataSym } from "../../fields/Doc"; import { List } from "../../fields/List"; import { listSpec } from "../../fields/Schema"; import { ScriptField, ComputedField } from "../../fields/ScriptField"; @@ -91,29 +91,29 @@ export class CurrentUserUtils { } if (doc["template-button-description"] === undefined) { - const descriptionTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created - Doc.GetProto(descriptionTemplate).layout = + const descriptionTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header")); // text needs to be a space to allow templateText to be created + descriptionTemplate[DataSym].layout = "

" + " " + " " + "
"; - descriptionTemplate.isTemplateDoc = makeTemplate(descriptionTemplate, true, "descriptionView"); + (descriptionTemplate.proto as Doc).isTemplateDoc = makeTemplate(descriptionTemplate.proto as Doc, true, "descriptionView"); doc["template-button-description"] = CurrentUserUtils.ficon({ - onDragStart: ScriptField.MakeFunction('makeDelegate(this.dragFactory)'), + onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: new PrefetchProxy(descriptionTemplate) as any as Doc, removeDropProperties: new List(["dropAction"]), title: "description view", icon: "window-maximize" }); } if (doc["template-button-link"] === undefined) { // set _backgroundColor to transparent to prevent link dot from obscuring document it's attached to. - const linkTemplate = Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header"); // text needs to be a space to allow templateText to be created + const linkTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _height: 100 }, "header")); // text needs to be a space to allow templateText to be created Doc.GetProto(linkTemplate).layout = "
" + " " + " " + "
"; - linkTemplate.isTemplateDoc = makeTemplate(linkTemplate, true, "linkView"); + (linkTemplate.proto as Doc).isTemplateDoc = makeTemplate(linkTemplate.proto as Doc, true, "linkView"); const rtf2 = { doc: { @@ -146,7 +146,7 @@ export class CurrentUserUtils { linkTemplate.header = new RichTextField(JSON.stringify(rtf2), ""); doc["template-button-link"] = CurrentUserUtils.ficon({ - onDragStart: ScriptField.MakeFunction('makeDelegate(this.dragFactory)'), + onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: new PrefetchProxy(linkTemplate) as any as Doc, removeDropProperties: new List(["dropAction"]), title: "link view", icon: "window-maximize" }); @@ -390,6 +390,21 @@ export class CurrentUserUtils { if (doc.emptyScript === undefined) { doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script" }); } + if (doc.emptyScreenshot === undefined) { + doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" }); + } + if (doc.emptyAudio === undefined) { + doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "ready to record audio" }); + } + if (doc.emptyImage === undefined) { + doc.emptyImage = Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth: 250, title: "an image of a cat" }); + } + if (doc.emptyButton === undefined) { + doc.emptyButton = Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title: "Button" }); + } + if (doc.emptySearch === undefined) { + doc.emptySearch = Docs.Create.QueryDocument({ _width: 200, title: "empty search" }); + } if (doc.emptyDocHolder === undefined) { doc.emptyDocHolder = Docs.Create.DocumentDocument( ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]") as any, @@ -404,14 +419,15 @@ export class CurrentUserUtils { return [ { toolTip: "Drag a collection", title: "Col", icon: "folder", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyCollection as Doc }, { toolTip: "Drag a web page", title: "Web", icon: "globe-asia", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyWebpage as Doc }, - { toolTip: "Drag a cat image", title: "Image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { _width: 250, _nativeWidth:250, title: "an image of a cat" })' }, + { toolTip: "Drag a cat image", title: "Image", icon: "cat", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyImage as Doc }, { toolTip: "Drag a comparison box", title: "Comp", icon: "columns", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyComparison as Doc }, - { toolTip: "Drag a screengrabber", title: "Grab", icon: "photo-video", ignoreClick: true, drag: 'Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot" })' }, + { toolTip: "Drag a screengrabber", title: "Grab", icon: "photo-video", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScreenshot as Doc }, // { title: "Drag a webcam", title: "Cam", icon: "video", ignoreClick: true, drag: 'Docs.Create.WebCamDocument("", { _width: 400, _height: 400, title: "a test cam" })' }, - { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", ignoreClick: true, drag: `Docs.Create.AudioDocument("${nullAudio}", { _width: 200, title: "ready to record audio" })` }, - { toolTip: "Drag a button", title: "Button", icon: "bolt", ignoreClick: true, drag: 'Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding:10, _yPadding: 10, title: "Button" })' }, - { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory,true)`, dragFactory: doc.emptyPresentation as Doc }, - { toolTip: "Drag a search box", title: "Query", icon: "search", ignoreClick: true, drag: 'Docs.Create.QueryDocument({ _width: 200, title: "an image of a cat" })' }, + { toolTip: "Drag a audio recorder", title: "Audio", icon: "microphone", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyAudio as Doc }, + { toolTip: "Drag a button", title: "Button", icon: "bolt", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyButton as Doc }, + + { toolTip: "Drag a presentation view", title: "Prezi", icon: "tv", click: 'openOnRight(Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true))', drag: `Doc.UserDoc().activePresentation = getCopy(this.dragFactory, true)`, dragFactory: doc.emptyPresentation as Doc }, + { toolTip: "Drag a search box", title: "Query", icon: "search", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptySearch as Doc }, { toolTip: "Drag a scripting box", title: "Script", icon: "terminal", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyScript as Doc }, // { title: "Drag an import folder", title: "Load", icon: "cloud-upload-alt", ignoreClick: true, drag: 'Docs.Create.DirectoryImportDocument({ title: "Directory Import", _width: 400, _height: 400 })' }, { toolTip: "Drag a mobile view", title: "Phone", icon: "mobile", click: 'openOnRight(Doc.UserDoc().activeMobileMenu)', drag: 'this.dragFactory', dragFactory: doc.activeMobileMenu as Doc }, @@ -421,7 +437,7 @@ export class CurrentUserUtils { // { title: "use stamp", icon: "stamp", click: 'activateStamp(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this)', backgroundColor: "orange", ischecked: `sameDocs(this.activeInkPen, this)`, activeInkPen: doc }, // { title: "use eraser", icon: "eraser", click: 'activateEraser(this.activeInkPen = sameDocs(this.activeInkPen, this) ? undefined : this);', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "pink", activeInkPen: doc }, // { title: "use drag", icon: "mouse-pointer", click: 'deactivateInk();this.activeInkPen = this;', ischecked: `sameDocs(this.activeInkPen, this)`, backgroundColor: "white", activeInkPen: doc }, - { toolTip: "Drag a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory,true)', dragFactory: doc.emptyDocHolder as Doc }, + { toolTip: "Drag a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory, true)', dragFactory: doc.emptyDocHolder as Doc }, { toolTip: "Toggle a Calculator REPL", title: "repl", icon: "calculator", click: 'addOverlayWindow("ScriptingRepl", { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" })' }, ]; @@ -599,7 +615,7 @@ export class CurrentUserUtils { _width: 35, _height: 25, title: "Tools", _fontSize: "10pt", letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: toolsStack, - onDragStart: ScriptField.MakeFunction('getAlias(this.dragFactory, true)'), + onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: toolsStack, removeDropProperties: new List(["lockedPosition"]), stayInCollection: true, @@ -664,12 +680,12 @@ export class CurrentUserUtils { _width: 50, _height: 25, title: "Library", _fontSize: "10pt", targetDropAction: "same", letterSpacing: "0px", textTransform: "unset", borderRounding: "5px 5px 0px 0px", boxShadow: "3px 3px 0px rgb(34, 34, 34)", sourcePanel: libraryStack, - onDragStart: ScriptField.MakeFunction('getAlias(this.dragFactory, true)'), + onDragStart: ScriptField.MakeFunction('getCopy(this.dragFactory, true)'), dragFactory: libraryStack, removeDropProperties: new List(["lockedPosition"]), stayInCollection: true, targetContainer: new PrefetchProxy(sidebarContainer) as any as Doc, - onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel;") + onClick: ScriptField.MakeScript("this.targetContainer.proto = this.sourcePanel") })); } return doc["tabs-button-library"] as Doc; diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 11b3b0524..ebca19430 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -3,7 +3,7 @@ import { CompiledScript, CompileScript, scriptingGlobal, ScriptOptions, CompileE import { Copy, ToScriptString, ToString, Parent, SelfProxy } from "./FieldSymbols"; import { serializable, createSimpleSchema, map, primitive, object, deserialize, PropSchema, custom, SKIP } from "serializr"; import { Deserializable, autoObject } from "../client/util/SerializationHelper"; -import { Doc, Field } from "./Doc"; +import { Doc, Field, Opt } from "./Doc"; import { Plugins, setter } from "./util"; import { computedFn } from "mobx-utils"; import { ProxyField } from "./Proxy"; @@ -38,6 +38,22 @@ const scriptSchema = createSimpleSchema({ }); async function deserializeScript(script: ScriptField) { + if (script.script.originalScript === 'getCopy(this.dragFactory, true)') { + return (script as any).script = (ScriptField.GetCopyOfDragFactory ?? (ScriptField.GetCopyOfDragFactory = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')))?.script; + } + if (script.script.originalScript === 'links(self)') { + return (script as any).script = (ScriptField.LinksSelf ?? (ScriptField.LinksSelf = ComputedField.MakeFunction('links(self)')))?.script; + } + if (script.script.originalScript === 'openOnRight(getCopy(this.dragFactory, true))') { + return (script as any).script = (ScriptField.OpenOnRight ?? (ScriptField.OpenOnRight = ComputedField.MakeFunction('openOnRight(getCopy(this.dragFactory, true))')))?.script; + } + if (script.script.originalScript === 'deiconifyView(self)') { + return (script as any).script = (ScriptField.DeiconifyView ?? (ScriptField.DeiconifyView = ComputedField.MakeFunction('deiconifyView(self)')))?.script; + } + if (script.script.originalScript === 'convertToButtons(dragData)') { + return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)')))?.script; + } + console.log(script.script.originalScript); const captures: ProxyField = (script as any).captures; if (captures) { const doc = (await captures.value())!; @@ -65,6 +81,11 @@ export class ScriptField extends ObjectField { @serializable(autoObject()) private captures?: ProxyField; + public static GetCopyOfDragFactory: Opt; + public static LinksSelf: Opt; + public static OpenOnRight: Opt; + public static DeiconifyView: Opt; + public static ConvertToButtons: Opt; constructor(script: CompiledScript, setterscript?: CompiledScript) { super(); -- cgit v1.2.3-70-g09d2 From e613f4ebc268bb9d8a0bd1ea2f07fef73a870199 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 20 Jul 2020 17:01:39 -0400 Subject: fixed noAutoscroll functionality for creator icons --- src/client/documents/Documents.ts | 1 + src/client/util/CurrentUserUtils.ts | 7 +++---- src/client/util/DragManager.ts | 2 +- src/client/views/nodes/FontIconBox.scss | 3 ++- src/fields/ScriptField.ts | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src/fields') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 8e7d125b0..2d74c462d 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -69,6 +69,7 @@ export interface DocumentOptions { _showTitle?: string; // which field to display in the title area. leave empty to have no title _showCaption?: string; // which field to display in the caption area. leave empty to have no caption _scrollTop?: number; // scroll location for pdfs + _noAutoscroll?: boolean;// whether collectoins autoscroll when this item is dragged _chromeStatus?: string; _viewType?: string; // sub type of a collection _gridGap?: number; // gap between items in masonry view diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 4b8c342f1..d53a6fcdb 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -466,6 +466,7 @@ export class CurrentUserUtils { onClick: click ? ScriptField.MakeScript(click) : undefined, ischecked: ischecked ? ComputedField.MakeFunction(ischecked) : undefined, activeInkPen, + _noAutoscroll: true, backgroundColor, removeDropProperties: new List(["dropAction"]), dragFactory, @@ -735,15 +736,13 @@ export class CurrentUserUtils { } static blist = (opts: DocumentOptions, docs: Doc[]) => new PrefetchProxy(Docs.Create.LinearDocument(docs, { - ...opts, - _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true, + ...opts, _noAutoscroll: true, _gridGap: 5, _xMargin: 5, _yMargin: 5, _height: 42, _width: 100, boxShadow: "0 0", forceActive: true, dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }), backgroundColor: "black", treeViewPreventOpen: true, lockedPosition: true, _chromeStatus: "disabled", linearViewIsExpanded: true })) as any as Doc static ficon = (opts: DocumentOptions) => new PrefetchProxy(Docs.Create.FontIconDocument({ - ...opts, - dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100 + ...opts, _noAutoscroll: true, dropAction: "alias", removeDropProperties: new List(["dropAction"]), _nativeWidth: 100, _nativeHeight: 100, _width: 100, _height: 100 })) as any as Doc /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 6a3108157..007336190 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -435,7 +435,7 @@ export namespace DragManager { const complete = new DragCompleteEvent(false, dragData); - if (target && !options?.noAutoscroll) { + if (target && !options?.noAutoscroll && !dragData.draggedDocuments?.some((d: any) => d._noAutoscroll)) { target.dispatchEvent( new CustomEvent("dashDragging", { bubbles: true, diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss index fe0f067ad..5b85d8b0b 100644 --- a/src/client/views/nodes/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox.scss @@ -11,7 +11,6 @@ .fontIconBox-label { background: gray; color:white; - margin-left: -10px; border-radius: 8px; width:100%; position: absolute; @@ -19,6 +18,8 @@ font-size: 8px; margin-top:4px; letter-spacing: normal; + left: 0; + overflow: hidden; } svg { diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index ebca19430..4604a2132 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -51,7 +51,7 @@ async function deserializeScript(script: ScriptField) { return (script as any).script = (ScriptField.DeiconifyView ?? (ScriptField.DeiconifyView = ComputedField.MakeFunction('deiconifyView(self)')))?.script; } if (script.script.originalScript === 'convertToButtons(dragData)') { - return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)')))?.script; + return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)', { dragData: "DocumentDragData" })))?.script; } console.log(script.script.originalScript); const captures: ProxyField = (script as any).captures; -- cgit v1.2.3-70-g09d2 From c4499c610f377be4b80cf2999d25f97b619d4727 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Tue, 21 Jul 2020 17:17:47 +0530 Subject: distributing acls shifted to util.ts --- src/client/util/SharingManager.tsx | 47 +++------------ src/client/views/DocComponent.tsx | 34 ++++++----- src/client/views/collections/CollectionView.tsx | 76 +++++++++++++------------ src/fields/util.ts | 46 ++++++++++++++- 4 files changed, 109 insertions(+), 94 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 8b3ac2613..d3bc84770 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,4 +1,4 @@ -import { observable, runInAction, action } from "mobx"; +import { observable, runInAction, action, computed } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; import { Doc, Opt, DocListCastAsync, DataSym, DocListCast } from "../../fields/Doc"; @@ -20,6 +20,7 @@ import GroupMemberView from "./GroupMemberView"; import Select from "react-select"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { List } from "../../fields/List"; +import { distributeAcls } from "../../fields/util"; library.add(fa.faCopy, fa.faTimes); @@ -131,7 +132,7 @@ export default class SharingManager extends React.Component<{}> { // target[ACL] = permission; // Doc.GetProto(target)[ACL] = permission; - this.distributeAcls(ACL, permission as SharingPermissions); + distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!); group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List).push(target)) : group.docsShared = new List([target]); @@ -174,7 +175,7 @@ export default class SharingManager extends React.Component<{}> { const ACL = `ACL-${StrCast(group.groupName)}`; // doc[ACL] = doc[DataSym][ACL] = "Not Shared"; - this.distributeAcls(ACL, SharingPermissions.None, doc); + distributeAcls(ACL, SharingPermissions.None, doc); const members: string[] = JSON.parse(StrCast(group.members)); const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); @@ -186,6 +187,7 @@ export default class SharingManager extends React.Component<{}> { } } + // @action setInternalSharing = (recipient: ValidatedUser, permission: string) => { const { user, notificationDoc } = recipient; const target = this.targetDoc!; @@ -196,7 +198,7 @@ export default class SharingManager extends React.Component<{}> { // target[ACL] = permission; // Doc.GetProto(target)[ACL] = permission; - this.distributeAcls(ACL, permission as SharingPermissions); + distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!); if (permission !== SharingPermissions.None) { DocListCastAsync(notificationDoc[storage]).then(resolved => { @@ -210,40 +212,6 @@ export default class SharingManager extends React.Component<{}> { } } - @action - distributeAcls = (key: string, acl: SharingPermissions, doc?: Doc) => { - const target = doc ? doc : this.targetDoc!; - const dataDoc = target[DataSym]; - target[key] = acl; - if (dataDoc) dataDoc[key] = acl; - // dataDoc[key] = target[key] = acl; - // next line distributes the acl to all children of the target - DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail) { - this.distributeAcls(key, acl, d); - d[key] = acl; - } - const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail) { - this.distributeAcls(key, acl, data); - data[key] = acl; - } - }); - - DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { - if (d.author === Doc.CurrentUserEmail) { - this.distributeAcls(key, acl, d); - d[key] = acl; - } - const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail) { - this.distributeAcls(key, acl, data); - data[key] = acl; - } - console.log(d, d[DataSym]); - }); - - } // private setExternalSharing = (permission: string) => { // const sharingDoc = this.sharingDoc; @@ -344,7 +312,6 @@ export default class SharingManager extends React.Component<{}> { } private get sharingInterface() { - const groupList = GroupManager.Instance?.getAllGroups() || []; const sortedUsers = this.users.sort(this.sortUsers) @@ -368,7 +335,7 @@ export default class SharingManager extends React.Component<{}> { const users = this.individualSort === "ascending" ? this.users.sort(this.sortUsers) : this.individualSort === "descending" ? this.users.sort(this.sortUsers).reverse() : this.users; const groups = this.groupSort === "ascending" ? groupList.sort(this.sortGroups) : this.groupSort === "descending" ? groupList.sort(this.sortGroups).reverse() : groupList; - const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { // can't use async here + const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { const userKey = user.email.replace('.', '_'); const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 2519360da..655be80ef 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -150,24 +150,28 @@ export function ViewBoxAnnotatableComponent

!docList.includes(d)); const effectiveAcl = GetEffectiveAcl(this.dataDoc); - if (this.props.Document[AclSym]) { - added.forEach(d => { - const dataDoc = d[DataSym]; - dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; - for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - dataDoc[key] = d[key] = this.AclMap.get(value); - } - }); - } if (added.length) { if (effectiveAcl === AclReadonly && !getPlaygroundMode()) { return false; - } else if (effectiveAcl === AclAddonly) { - added.map(doc => console.log(Doc.AddDocToList(targetDataDoc, this.annotationKey, doc))); - } else { - added.map(doc => doc.context = this.props.Document); - targetDataDoc[this.annotationKey] = new List([...docList, ...added]); - targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + } + else { + if (this.props.Document[AclSym]) { + added.forEach(d => { + const dataDoc = d[DataSym]; + dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + dataDoc[key] = d[key] = this.AclMap.get(value); + } + }); + } + if (effectiveAcl === AclAddonly) { + added.map(doc => console.log(Doc.AddDocToList(targetDataDoc, this.annotationKey, doc))); + } + else { + added.map(doc => doc.context = this.props.Document); + targetDataDoc[this.annotationKey] = new List([...docList, ...added]); + targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + } } } return true; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 17567ea73..5cef6c44e 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,7 +17,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from '../../../fields/util'; +import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, distributeAcls } from '../../../fields/util'; import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -142,46 +142,48 @@ export class CollectionView extends Touchable !docList.includes(d)); const effectiveAcl = GetEffectiveAcl(this.props.Document); - if (this.props.Document[AclSym]) { - // change so it only adds if more restrictive - added.forEach(d => { - console.log(d[Id]); - const dataDoc = d[DataSym]; - console.log(dataDoc[Id]); - for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - dataDoc[key] = d[key] = this.AclMap.get(value); - } - dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; - - }); - } if (added.length) { if (effectiveAcl === AclReadonly && !getPlaygroundMode()) { return false; - } else if (effectiveAcl === AclAddonly) { - added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); - } else { - added.map(doc => { - const context = Cast(doc.context, Doc, null); - if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) { - const pushpin = Docs.Create.FontIconDocument({ - title: "pushpin", - icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7", - _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null) - }); - pushpin.isPushpin = true; - Doc.GetProto(pushpin).annotationOn = doc.annotationOn; - Doc.SetInPlace(doc, "annotationOn", undefined, true); - Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin); - const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", ""); - doc.displayTimecode = undefined; - } - doc.context = this.props.Document; - }); - added.map(add => Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); - targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); - targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + } + else { + if (this.props.Document[AclSym]) { + // change so it only adds if more restrictive + added.forEach(d => { + const dataDoc = d[DataSym]; + for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d); + } + dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + }); + } + + if (effectiveAcl === AclAddonly) { + added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); + } + else { + added.map(doc => { + const context = Cast(doc.context, Doc, null); + if (context && (context.type === DocumentType.VID || context.type === DocumentType.WEB || context.type === DocumentType.PDF || context.type === DocumentType.IMG)) { + const pushpin = Docs.Create.FontIconDocument({ + title: "pushpin", + icon: "map-pin", x: Cast(doc.x, "number", null), y: Cast(doc.y, "number", null), _backgroundColor: "#0000003d", color: "#ACCEF7", + _width: 15, _height: 15, _xPadding: 0, isLinkButton: true, displayTimecode: Cast(doc.displayTimecode, "number", null) + }); + pushpin.isPushpin = true; + Doc.GetProto(pushpin).annotationOn = doc.annotationOn; + Doc.SetInPlace(doc, "annotationOn", undefined, true); + Doc.AddDocToList(context, Doc.LayoutFieldKey(context) + "-annotations", pushpin); + const pushpinLink = DocUtils.MakeLink({ doc: pushpin }, { doc: doc }, "pushpin", ""); + doc.displayTimecode = undefined; + } + doc.context = this.props.Document; + }); + added.map(add => Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); + targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); + targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + } } } return true; diff --git a/src/fields/util.ts b/src/fields/util.ts index ee01f6213..a714b01e3 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -1,5 +1,5 @@ import { UndoManager } from "../client/util/UndoManager"; -import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, fetchProto } from "./Doc"; +import { Doc, FieldResult, UpdatingFromServer, LayoutSym, AclPrivate, AclEdit, AclReadonly, AclAddonly, AclSym, fetchProto, DataSym, DocListCast } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField, PrefetchProxy } from "./Proxy"; import { RefField } from "./RefField"; @@ -8,7 +8,8 @@ import { action, trace } from "mobx"; import { Parent, OnUpdate, Update, Id, SelfProxy, Self } from "./FieldSymbols"; import { DocServer } from "../client/DocServer"; import { ComputedField } from "./ScriptField"; -import { ScriptCast } from "./Types"; +import { ScriptCast, StrCast } from "./Types"; +import { SharingPermissions } from "../client/util/SharingManager"; function _readOnlySetter(): never { @@ -168,6 +169,47 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) return AclEdit; } +export function distributeAcls(key: string, acl: SharingPermissions, target: Doc) { + + const HierarchyMapping = new Map([ + ["Not Shared", 0], + ["Can View", 1], + ["Can Add", 2], + ["Can Edit", 3] + ]); + + const dataDoc = target[DataSym]; + + if (!target[key] || HierarchyMapping.get(StrCast(target[key]))! < HierarchyMapping.get(acl)!) target[key] = acl; + + if (dataDoc && (!dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! < HierarchyMapping.get(acl)!)) { + dataDoc[key] = acl; + + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { + if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) { + distributeAcls(key, acl, d); + d[key] = acl; + } + const data = d[DataSym]; + if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) { + distributeAcls(key, acl, data); + data[key] = acl; + } + }); + + DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { + if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) { + distributeAcls(key, acl, d); + d[key] = acl; + } + const data = d[DataSym]; + if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) { + distributeAcls(key, acl, data); + data[key] = acl; + } + }); + } +} const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", "chromeStatus", "viewType", "gridGap", "xMargin", "yMargin", "autoHeight"]; -- cgit v1.2.3-70-g09d2 From 3d06cdd362d58dfbc8d6efdcd9dc59250ab003a4 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Tue, 21 Jul 2020 23:16:49 +0530 Subject: distributeAcls only changes if container is more restrictive --- src/client/util/SharingManager.tsx | 14 +++++--------- src/client/views/DocComponent.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 6 +++--- src/client/views/nodes/DocumentView.tsx | 5 +++-- src/fields/util.ts | 18 +++++++----------- 5 files changed, 19 insertions(+), 26 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index d3bc84770..9c857a7c0 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,7 +1,7 @@ -import { observable, runInAction, action, computed } from "mobx"; +import { observable, runInAction, action } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; -import { Doc, Opt, DocListCastAsync, DataSym, DocListCast } from "../../fields/Doc"; +import { Doc, Opt, DocListCastAsync } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; @@ -41,9 +41,9 @@ interface GroupOptions { options: UserOptions[]; } -const SharingKey = "sharingPermissions"; -const PublicKey = "publicLinkPermissions"; -const DefaultColor = "black"; +// const SharingKey = "sharingPermissions"; +// const PublicKey = "publicLinkPermissions"; +// const DefaultColor = "black"; const groupType = "!groupType/"; const indType = "!indType/"; @@ -192,12 +192,8 @@ export default class SharingManager extends React.Component<{}> { const { user, notificationDoc } = recipient; const target = this.targetDoc!; const key = user.email.replace('.', '_'); - const ACL = `ACL-${key}`; - // target[ACL] = permission; - // Doc.GetProto(target)[ACL] = permission; - distributeAcls(ACL, permission as SharingPermissions, this.targetDoc!); if (permission !== SharingPermissions.None) { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 655be80ef..95c1bcda8 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -165,7 +165,7 @@ export function ViewBoxAnnotatableComponent

console.log(Doc.AddDocToList(targetDataDoc, this.annotationKey, doc))); + added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } else { added.map(doc => doc.context = this.props.Document); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5cef6c44e..9b04deff5 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -151,11 +151,11 @@ export class CollectionView extends Touchable { - const dataDoc = d[DataSym]; + // const dataDoc = d[DataSym]; for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d); + distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); } - dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + // dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; }); } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 803720417..0b5bd707b 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -4,7 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import * as rp from "request-promise"; -import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclPrivate, AclReadonly } from "../../../fields/Doc"; +import { Doc, DocListCast, HeightSym, Opt, WidthSym, DataSym, AclPrivate, AclEdit } from "../../../fields/Doc"; import { Document } from '../../../fields/documentSchemas'; import { Id } from '../../../fields/FieldSymbols'; import { InkTool } from '../../../fields/InkField'; @@ -707,6 +707,7 @@ export class DocumentView extends DocComponent(Docu if (data && data.author === Doc.CurrentUserEmail) data.ACL = acl; }); } + @undoBatch @action testAcl = (acl: SharingPermissions) => { @@ -806,7 +807,7 @@ export class DocumentView extends DocComponent(Docu }); moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); } - moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" }); + GetEffectiveAcl(this.props.Document) === AclEdit && moreItems.push({ description: "Delete", event: this.deleteClicked, icon: "trash" }); moreItems.push({ description: "Share", event: () => SharingManager.Instance.open(this), icon: "external-link-alt" }); !more && cm.addItem({ description: "More...", subitems: moreItems, icon: "hand-point-right" }); cm.moveAfter(cm.findByDescription("More...")!, cm.findByDescription("OnClick...")!); diff --git a/src/fields/util.ts b/src/fields/util.ts index a714b01e3..81ccbf6d9 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -137,14 +137,10 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) if (target[AclSym] && Object.keys(target[AclSym]).length) { - // console.log(target[AclSym]); - if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit; if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; - // if (target[AclSym].ACL) return target[AclSym].ACL; - let effectiveAcl = AclPrivate; let aclPresent = false; @@ -169,7 +165,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) return AclEdit; } -export function distributeAcls(key: string, acl: SharingPermissions, target: Doc) { +export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) { const HierarchyMapping = new Map([ ["Not Shared", 0], @@ -180,30 +176,30 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc const dataDoc = target[DataSym]; - if (!target[key] || HierarchyMapping.get(StrCast(target[key]))! < HierarchyMapping.get(acl)!) target[key] = acl; + if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) target[key] = acl; - if (dataDoc && (!dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! < HierarchyMapping.get(acl)!)) { + if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { dataDoc[key] = acl; DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) { + if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, d); d[key] = acl; } const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) { + if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, data); data[key] = acl; } }); DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { - if (d.author === Doc.CurrentUserEmail && d[key] && HierarchyMapping.get(StrCast(d[key]))! < HierarchyMapping.get(acl)!) { + if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, d); d[key] = acl; } const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail && data[key] && HierarchyMapping.get(StrCast(data[key]))! < HierarchyMapping.get(acl)!) { + if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, data); data[key] = acl; } -- cgit v1.2.3-70-g09d2 From 9d530f8fc7ca9621274a38260faebe797f66dd60 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 21 Jul 2020 23:57:55 -0400 Subject: fixed problem where adding to a collection would cause a remote synchronized collection to erase and redraw since all of its list items got replaced. the fix was to update the 'cache' field of ProxyFields when they are deserialized to use an existing cached value if available. --- src/fields/Proxy.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/fields') diff --git a/src/fields/Proxy.ts b/src/fields/Proxy.ts index 555faaad0..62734d3d2 100644 --- a/src/fields/Proxy.ts +++ b/src/fields/Proxy.ts @@ -9,7 +9,12 @@ import { Id, Copy, ToScriptString, ToString } from "./FieldSymbols"; import { scriptingGlobal } from "../client/util/Scripting"; import { Plugins } from "./util"; -@Deserializable("proxy") +function deserializeProxy(field: any) { + if (!field.cache) { + field.cache = DocServer.GetCachedRefField(field.fieldId) as any; + } +} +@Deserializable("proxy", deserializeProxy) export class ProxyField extends ObjectField { constructor(); constructor(value: T); @@ -17,6 +22,7 @@ export class ProxyField extends ObjectField { constructor(value?: T | string) { super(); if (typeof value === "string") { + this.cache = DocServer.GetCachedRefField(value) as any; this.fieldId = value; } else if (value) { this.cache = value; -- cgit v1.2.3-70-g09d2 From 828a28e112db3357f52d3923987070129fd64b21 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 22 Jul 2020 11:33:28 -0400 Subject: restored download document. fixed clone() to clone to be async and handles lists properly. --- src/client/util/CurrentUserUtils.ts | 6 +++++ src/client/util/LinkManager.ts | 12 ++------- src/client/util/Scripting.ts | 10 +++----- src/client/views/GlobalKeyHandler.ts | 4 +-- src/client/views/PreviewCursor.tsx | 4 +-- .../collections/collectionFreeForm/MarqueeView.tsx | 8 +++--- src/client/views/linking/LinkEditor.tsx | 4 +-- src/client/views/linking/LinkMenuItem.tsx | 3 ++- src/client/views/nodes/DocumentView.tsx | 14 ++++------ src/client/views/nodes/LinkDocPreview.tsx | 9 +------ .../formattedText/FormattedTextBoxComment.tsx | 2 ++ .../views/nodes/formattedText/RichTextMenu.tsx | 4 ++- src/fields/Doc.ts | 30 +++++++++++----------- src/server/ApiManagers/DownloadManager.ts | 12 +++------ src/server/ApiManagers/UploadManager.ts | 14 +++------- 15 files changed, 56 insertions(+), 80 deletions(-) (limited to 'src/fields') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 03a75381a..23b8f09de 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -22,6 +22,7 @@ import { DocumentType } from "../documents/DocumentTypes"; import { SchemaHeaderField } from "../../fields/SchemaHeaderField"; import { DimUnit } from "../views/collections/collectionMulticolumn/CollectionMulticolumnView"; import { LabelBox } from "../views/nodes/LabelBox"; +import { LinkManager } from "./LinkManager"; export class CurrentUserUtils { private static curr_id: string; @@ -888,3 +889,8 @@ export class CurrentUserUtils { Scripting.addGlobal(function createNewWorkspace() { return MainView.Instance.createNewWorkspace(); }, "creates a new workspace when called"); + +Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, + "returns all the links to the document or its annotations", "(doc: any)"); +Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); }, + "returns all the links directly to the document", "(doc: any)"); diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 974744344..223f0e7ef 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -2,8 +2,6 @@ import { Doc, DocListCast, Opt } from "../../fields/Doc"; import { List } from "../../fields/List"; import { listSpec } from "../../fields/Schema"; import { Cast, StrCast } from "../../fields/Types"; -import { Scripting } from "./Scripting"; -import { undoBatch } from "./UndoManager"; /* * link doc: @@ -25,12 +23,12 @@ export class LinkManager { private static _instance: LinkManager; - public static currentLink: Opt; public static get Instance(): LinkManager { return this._instance || (this._instance = new this()); } + private constructor() { } @@ -53,7 +51,6 @@ export class LinkManager { return false; } - @undoBatch public deleteLink(linkDoc: Doc): boolean { if (LinkManager.Instance.LinkManagerDoc && linkDoc instanceof Doc) { Doc.RemoveDocFromList(LinkManager.Instance.LinkManagerDoc, "data", linkDoc); @@ -210,9 +207,4 @@ export class LinkManager { if (Doc.AreProtosEqual(anchor, a2)) return a1; if (Doc.AreProtosEqual(anchor, linkDoc)) return linkDoc; } -} - -Scripting.addGlobal(function links(doc: any) { return new List(LinkManager.Instance.getAllRelatedLinks(doc)); }, - "returns all the links to the document or its annotations", "(doc: any)"); -Scripting.addGlobal(function directLinks(doc: any) { return new List(LinkManager.Instance.getAllDirectLinks(doc)); }, - "returns all the links directly to the document", "(doc: any)"); \ No newline at end of file +} \ No newline at end of file diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index e6cf50de3..f1e6155d2 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -10,8 +10,6 @@ export { ts }; // @ts-ignore import * as typescriptlib from '!!raw-loader!./type_decls.d'; import { Doc, Field } from '../../fields/Doc'; -import { Cast } from "../../fields/Types"; -import { listSpec } from "../../fields/Schema"; export interface ScriptSucccess { success: true; @@ -95,10 +93,10 @@ export namespace Scripting { export function removeGlobal(name: string) { if (getGlobals().includes(name)) { delete _scriptingGlobals[name]; - if (_scriptingDescriptions[name]){ + if (_scriptingDescriptions[name]) { delete _scriptingDescriptions[name]; } - if (_scriptingParams[name]){ + if (_scriptingParams[name]) { delete _scriptingParams[name]; } return true; @@ -123,11 +121,11 @@ export namespace Scripting { return _scriptingGlobals; } - export function getDescriptions(){ + export function getDescriptions() { return _scriptingDescriptions; } - export function getParameters(){ + export function getParameters() { return _scriptingParams; } } diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 4dfa7aec8..b63537b5f 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -309,13 +309,13 @@ export default class KeyManager { const targetDataDoc = Doc.GetProto(first.props.Document); const fieldKey = Doc.LayoutFieldKey(first.props.Document); const docList = DocListCast(targetDataDoc[fieldKey]); - docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { + docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => { count++; if (doc instanceof Doc) { list.push(doc); } if (count === docids.length) { - const added = list.filter(d => !docList.includes(d)).map(d => clone ? Doc.MakeClone(d) : d); + const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? await Doc.MakeClone(d) : d)); if (added.length) { added.map(doc => doc.context = targetDataDoc); undoBatch(() => { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 6583589f3..2d51403d7 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -69,11 +69,11 @@ export class PreviewCursor extends React.Component<{}> { const list: Doc[] = []; let first: Doc | undefined; - docids.map((did, i) => i && DocServer.GetRefField(did).then(doc => { + docids.map((did, i) => i && DocServer.GetRefField(did).then(async doc => { count++; if (doc instanceof Doc) { i === 1 && (first = doc); - const alias = clone ? Doc.MakeClone(doc) : doc; + const alias = clone ? await Doc.MakeClone(doc) : doc; const deltaX = NumCast(doc.x) - NumCast(first!.x) - ptx; const deltaY = NumCast(doc.y) - NumCast(first!.y) - pty; alias.x = newPoint[0] + deltaX; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 6db8c8992..84719b2c9 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -189,8 +189,8 @@ export class MarqueeView extends React.Component { this._downX = this._lastX = e.clientX; this._downY = this._lastY = e.clientY; - if (!(e as any).marqueeHit) { - (e as any).marqueeHit = true; + if (!(e.nativeEvent as any).marqueeHit) { + (e.nativeEvent as any).marqueeHit = true; // allow marquee if right click OR alt+left click OR space bar + left click if (e.button === 2 || (e.button === 0 && (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))))) { // if (e.altKey || (MarqueeView.DragMarquee && this.props.active(true))) { @@ -291,8 +291,8 @@ export class MarqueeView extends React.Component { //@observable description = this.props.linkDoc.description ? StrCast(this.props.linkDoc.description) : "DESCRIPTION"; + @undoBatch @action deleteLink = (): void => { LinkManager.Instance.deleteLink(this.props.linkDoc); @@ -422,8 +424,6 @@ export class LinkEditor extends React.Component {

Editing Link to: { destination.proto?.title ?? destination.title ?? "untitled"}

- {/* */}
Show more link information
} placement="top">
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index 0e847632b..d8ba39f09 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -17,6 +17,7 @@ import { DocumentLinksButton } from '../nodes/DocumentLinksButton'; import { LinkDocPreview } from '../nodes/LinkDocPreview'; import { Tooltip } from '@material-ui/core'; import { DocumentType } from '../../documents/DocumentTypes'; +import { undoBatch } from '../../util/UndoManager'; library.add(faEye, faEdit, faTimes, faArrowRight, faChevronDown, faChevronUp, faPencilAlt, faEyeSlash); @@ -163,10 +164,10 @@ export class LinkMenuItem extends React.Component { } } + @undoBatch @action deleteLink = (): void => { LinkManager.Instance.deleteLink(this.props.linkDoc); - //this.props.showLinks(); LinkDocPreview.LinkInfo = undefined; DocumentLinksButton.EditLink = undefined; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 0b5bd707b..12d9890c9 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -794,16 +794,12 @@ export class DocumentView extends DocComponent(Docu } moreItems.push({ description: "Download document", icon: "download", event: async () => { - const response = await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), { - qs: { q: 'world', fq: 'NOT baseProto_b:true AND NOT deleted:true', start: '0', rows: '100', hl: true, 'hl.fl': '*' } - }); - console.log(response ? JSON.parse(response) : undefined); + const a = document.createElement("a"); + const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); + a.href = url; + a.download = `DocExport-${this.props.Document[Id]}.zip`; + a.click(); } - // const a = document.createElement("a"); - // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); - // a.href = url; - // a.download = `DocExport-${this.props.Document[Id]}.zip`; - // a.click(); }); moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); } diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx index 1caa82380..ebb916307 100644 --- a/src/client/views/nodes/LinkDocPreview.tsx +++ b/src/client/views/nodes/LinkDocPreview.tsx @@ -15,6 +15,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { LinkManager } from '../../util/LinkManager'; import { DocumentLinksButton } from './DocumentLinksButton'; import { ContextMenu } from '../ContextMenu'; +import { undoBatch } from '../../util/UndoManager'; interface Props { linkDoc?: Doc; @@ -31,14 +32,6 @@ export class LinkDocPreview extends React.Component { @observable _toolTipText = ""; _editRef = React.createRef(); - @action - deleteLink = (): void => { - this.props.linkDoc ? LinkManager.Instance.deleteLink(this.props.linkDoc) : null; - //this.props.showLinks(); - LinkDocPreview.LinkInfo = undefined; - DocumentLinksButton.EditLink = undefined; - } - @action onContextMenu = (e: React.MouseEvent) => { DocumentLinksButton.EditLink = undefined; diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx index 3687d5513..6f3984f39 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx @@ -22,6 +22,7 @@ import { LinkManager } from "../../../util/LinkManager"; import { LinkDocPreview } from "../LinkDocPreview"; import { DocumentLinksButton } from "../DocumentLinksButton"; import { Tooltip } from "@material-ui/core"; +import { undoBatch } from "../../../util/UndoManager"; export let formattedTextBoxCommentPlugin = new Plugin({ view(editorView) { return new FormattedTextBoxComment(editorView); } @@ -143,6 +144,7 @@ export class FormattedTextBoxComment { } } + @undoBatch @action deleteLink = () => { FormattedTextBoxComment.linkDoc ? LinkManager.Instance.deleteLink(FormattedTextBoxComment.linkDoc) : null; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 2e0b0e659..47a4911b8 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -23,7 +23,7 @@ import { updateBullets } from "./ProsemirrorExampleTransfer"; import "./RichTextMenu.scss"; import { schema } from "./schema_rts"; import { TraceMobx } from "../../../../fields/util"; -import { UndoManager } from "../../../util/UndoManager"; +import { UndoManager, undoBatch } from "../../../util/UndoManager"; import { Tooltip } from "@material-ui/core"; const { toggleMark } = require("prosemirror-commands"); @@ -831,6 +831,8 @@ export default class RichTextMenu extends AntimodeMenu { ((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRight", "", target); } + @undoBatch + @action deleteLink = () => { if (this.view) { const link = this.view.state.selection.$from.nodeAfter?.marks.find(m => m.type === this.view!.state.schema.marks.linkAnchor); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 2f3b7025e..16ade5912 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -483,25 +483,25 @@ export namespace Doc { return alias; } - - - export function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[]): Doc { + export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[]): Promise { if (Doc.IsBaseProto(doc)) return doc; if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!; const copy = new Doc(undefined, true); cloneMap.set(doc[Id], copy); if (LinkManager.Instance.getAllLinks().includes(doc) && LinkManager.Instance.getAllLinks().indexOf(copy) === -1) LinkManager.Instance.addLink(copy); - const exclude = Cast(doc.excludeFields, listSpec("string"), []); - Object.keys(doc).forEach(key => { - if (exclude.includes(key)) return; + const filter = Cast(doc.cloneFieldFilter, listSpec("string"), exclusions); + Object.keys(doc).forEach(async key => { + if (filter.includes(key)) return; const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const field = ProxyField.WithoutProxy(() => doc[key]); - const copyObjectField = (field: ObjectField) => { - const list = Cast(doc[key], listSpec(Doc)); - if (list !== undefined && !(list instanceof Promise)) { - copy[key] = new List(list.filter(d => d instanceof Doc).map(d => Doc.makeClone(d as Doc, cloneMap, rtfs))); + const copyObjectField = async (field: ObjectField) => { + const list = await Cast(doc[key], listSpec(Doc)); + const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc); + if (docs !== undefined && docs.length) { + const clones = docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions)); + copy[key] = new List(await Promise.all(clones)); } else if (doc[key] instanceof Doc) { - copy[key] = key.includes("layout[") ? undefined : Doc.makeClone(doc[key] as Doc, cloneMap, rtfs); // reference documents except copy documents that are expanded teplate fields + copy[key] = key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions); // reference documents except copy documents that are expanded teplate fields } else { copy[key] = ObjectField.MakeCopy(field); if (field instanceof RichTextField) { @@ -513,7 +513,7 @@ export namespace Doc { }; if (key === "proto") { if (doc[key] instanceof Doc) { - copy[key] = Doc.makeClone(doc[key]!, cloneMap, rtfs); + copy[key] = await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions); } } else { if (field instanceof RefField) { @@ -535,10 +535,10 @@ export namespace Doc { cloneMap.set(doc[Id], copy); return copy; } - export function MakeClone(doc: Doc): Doc { + export async function MakeClone(doc: Doc): Promise { const cloneMap = new Map(); const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = []; - const copy = Doc.makeClone(doc, cloneMap, rtfMap); + const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"]); rtfMap.map(({ copy, key, field }) => { const replacer = (match: any, attr: string, id: string, offset: any, string: any) => { const mapped = cloneMap.get(id); @@ -657,7 +657,7 @@ export namespace Doc { export function MakeCopy(doc: Doc, copyProto: boolean = false, copyProtoId?: string): Doc { const copy = new Doc(copyProtoId, true); - const exclude = Cast(doc.excludeFields, listSpec("string"), []); + const exclude = Cast(doc.cloneFieldFilter, listSpec("string"), []); Object.keys(doc).forEach(key => { if (exclude.includes(key)) return; const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); diff --git a/src/server/ApiManagers/DownloadManager.ts b/src/server/ApiManagers/DownloadManager.ts index c5f3ca717..0d4472fdc 100644 --- a/src/server/ApiManagers/DownloadManager.ts +++ b/src/server/ApiManagers/DownloadManager.ts @@ -80,20 +80,14 @@ async function getDocs(id: string) { } const ids: string[] = []; for (const key in doc.fields) { - if (!doc.fields.hasOwnProperty(key)) { - continue; - } + if (!doc.fields.hasOwnProperty(key)) { continue; } const field = doc.fields[key]; - if (field === undefined || field === null) { - continue; - } + if (field === undefined || field === null) { continue; } if (field.__type === "proxy" || field.__type === "prefetch_proxy") { ids.push(field.fieldId); } else if (field.__type === "script" || field.__type === "computed") { - if (field.captures) { - ids.push(field.captures.fieldId); - } + field.captures && ids.push(field.captures.fieldId); } else if (field.__type === "list") { ids.push(...fn(field)); } else if (typeof field === "string") { diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 55ceab9fb..0b9e999ac 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -139,13 +139,9 @@ export default class UploadManager extends ApiManager { doc.id = getId(doc.id); } for (const key in doc.fields) { - if (!doc.fields.hasOwnProperty(key)) { - continue; - } + if (!doc.fields.hasOwnProperty(key)) { continue; } const field = doc.fields[key]; - if (field === undefined || field === null) { - continue; - } + if (field === undefined || field === null) { continue; } if (field.__type === "proxy" || field.__type === "prefetch_proxy") { field.fieldId = getId(field.fieldId); @@ -208,11 +204,7 @@ export default class UploadManager extends ApiManager { } catch (e) { console.log(e); } unlink(path_2, () => { }); } - if (id) { - res.send(JSON.stringify(getId(id))); - } else { - res.send(JSON.stringify("error")); - } + res.send(JSON.stringify(id ? getId(id) : "error")); } catch (e) { console.log(e); } resolve(); }); -- cgit v1.2.3-70-g09d2 From 8f95d52ed2b93930716ab6ed0ba9aab5c438876c Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Wed, 22 Jul 2020 20:16:53 -0400 Subject: fixed document download/import to capture links as well. --- package-lock.json | 56 ++++++++++++ package.json | 3 + src/client/views/GlobalKeyHandler.ts | 2 +- src/client/views/PreviewCursor.tsx | 2 +- .../collectionFreeForm/CollectionFreeFormView.tsx | 7 ++ src/client/views/nodes/DocHolderBox.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 12 +-- src/fields/Doc.ts | 101 ++++++++++++++++----- src/server/ApiManagers/UploadManager.ts | 2 + 9 files changed, 155 insertions(+), 32 deletions(-) (limited to 'src/fields') diff --git a/package-lock.json b/package-lock.json index 1b39905cf..698bd60cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -711,6 +711,12 @@ "express-validator": "*" } }, + "@types/file-saver": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.1.tgz", + "integrity": "sha512-g1QUuhYVVAamfCifK7oB7G3aIl4BbOyzDOqVyUfEr4tfBKrXfeH+M+Tg7HKCXSrbzxYdhyCP7z9WbKo0R2hBCw==", + "dev": true + }, "@types/formidable": { "version": "1.0.31", "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz", @@ -6069,6 +6075,11 @@ } } }, + "file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -7280,6 +7291,11 @@ } } }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", @@ -8160,6 +8176,33 @@ "promise": "^7.0.1" } }, + "jszip": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.5.0.tgz", + "integrity": "sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==", + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "set-immediate-shim": "~1.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, "jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -8300,6 +8343,14 @@ } } }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -15142,6 +15193,11 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", diff --git a/package.json b/package.json index cb083020f..6c466825e 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@types/express-flash": "0.0.0", "@types/express-session": "^1.15.16", "@types/express-validator": "^3.0.0", + "@types/file-saver": "^2.0.1", "@types/formidable": "^1.0.31", "@types/google-maps-react": "^2.0.5", "@types/jquery": "^3.5.0", @@ -154,6 +155,7 @@ "express-session": "^1.17.0", "express-validator": "^5.3.1", "expressjs": "^1.0.1", + "file-saver": "^2.0.2", "find-in-files": "^0.5.0", "fit-curve": "^0.1.7", "flexlayout-react": "^0.3.11", @@ -172,6 +174,7 @@ "image-size-stream": "^1.1.0", "js-datepicker": "^4.6.6", "jsonschema": "^1.2.5", + "jszip": "^3.5.0", "libxmljs": "^0.19.7", "lodash": "^4.17.15", "material-ui": "^0.20.2", diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index b63537b5f..086085db5 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -315,7 +315,7 @@ export default class KeyManager { list.push(doc); } if (count === docids.length) { - const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? await Doc.MakeClone(d) : d)); + const added = await Promise.all(list.filter(d => !docList.includes(d)).map(async d => clone ? (await Doc.MakeClone(d)).clone : d)); if (added.length) { added.map(doc => doc.context = targetDataDoc); undoBatch(() => { diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx index 2d51403d7..b4116e980 100644 --- a/src/client/views/PreviewCursor.tsx +++ b/src/client/views/PreviewCursor.tsx @@ -73,7 +73,7 @@ export class PreviewCursor extends React.Component<{}> { count++; if (doc instanceof Doc) { i === 1 && (first = doc); - const alias = clone ? await Doc.MakeClone(doc) : doc; + const alias = clone ? (await Doc.MakeClone(doc)).clone : doc; const deltaX = NumCast(doc.x) - NumCast(first!.x) - ptx; const deltaY = NumCast(doc.y) - NumCast(first!.y) - pty; alias.x = newPoint[0] + deltaX; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 412f91417..bee9e7009 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -46,6 +46,8 @@ import "./CollectionFreeFormView.scss"; import MarqueeOptionsMenu from "./MarqueeOptionsMenu"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); +import { SearchUtil } from "../../../util/SearchUtil"; +import { LinkManager } from "../../../util/LinkManager"; library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload); @@ -1276,6 +1278,11 @@ export class CollectionFreeFormView extends CollectionSubView { + SearchUtil.Search(`{!join from=id to=proto_i}id:link*`, true, {}).then(docs => { + docs.docs.forEach(d => LinkManager.Instance.addLink(d)); + }) + }, 2000); // need to give solr some time to update so that this query will find any link docs we've added. } } } diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx index 0cf5505cc..0c4242172 100644 --- a/src/client/views/nodes/DocHolderBox.tsx +++ b/src/client/views/nodes/DocHolderBox.tsx @@ -180,7 +180,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent(Docu } moreItems.push({ description: "Download document", icon: "download", event: async () => { - const a = document.createElement("a"); - const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); - a.href = url; - a.download = `DocExport-${this.props.Document[Id]}.zip`; - a.click(); + Doc.Zip(this.props.Document); + // const a = document.createElement("a"); + // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); + // a.href = url; + // a.download = `DocExport-${this.props.Document[Id]}.zip`; + // a.click(); } }); moreItems.push({ description: "Copy ID", event: () => Utils.CopyText(Utils.prepend("/doc/" + this.props.Document[Id])), icon: "fingerprint" }); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 16ade5912..917a6853c 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1,6 +1,6 @@ import { action, computed, observable, ObservableMap, runInAction, untracked } from "mobx"; import { computedFn } from "mobx-utils"; -import { alias, map, serializable } from "serializr"; +import { alias, map, serializable, list } from "serializr"; import { DocServer } from "../client/DocServer"; import { DocumentType } from "../client/documents/DocumentTypes"; import { Scripting, scriptingGlobal } from "../client/util/Scripting"; @@ -14,12 +14,16 @@ import { ObjectField } from "./ObjectField"; import { PrefetchProxy, ProxyField } from "./Proxy"; import { FieldId, RefField } from "./RefField"; import { RichTextField } from "./RichTextField"; +import { ImageField, VideoField, WebField, AudioField, PdfField } from "./URLField"; +import { DateField } from "./DateField"; import { listSpec } from "./Schema"; import { ComputedField } from "./ScriptField"; import { Cast, FieldValue, NumCast, StrCast, ToConstructor } from "./Types"; import { deleteProperty, getField, getter, makeEditable, makeReadOnly, setter, updateFunction, GetEffectiveAcl } from "./util"; import { LinkManager } from "../client/util/LinkManager"; import { SharingPermissions } from "../client/util/SharingManager"; +import JSZip = require("jszip"); +import { saveAs } from "file-saver"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -93,6 +97,7 @@ export const WidthSym = Symbol("Width"); export const HeightSym = Symbol("Height"); export const DataSym = Symbol("Data"); export const LayoutSym = Symbol("Layout"); +export const FieldsSym = Symbol("Fields"); export const AclSym = Symbol("Acl"); export const AclPrivate = Symbol("AclOwnerOnly"); export const AclReadonly = Symbol("AclReadOnly"); @@ -180,7 +185,6 @@ export class Doc extends RefField { } @observable - //{ [key: string]: Field | FieldWaiting | undefined } private ___fields: any = {}; private [UpdatingFromServer]: boolean = false; @@ -191,6 +195,7 @@ export class Doc extends RefField { private [Self] = this; private [SelfProxy]: any; + public [FieldsSym] = () => this.___fields; public [AclSym]: { [key: string]: symbol }; public [WidthSym] = () => NumCast(this[SelfProxy]._width); public [HeightSym] = () => NumCast(this[SelfProxy]._height); @@ -483,27 +488,28 @@ export namespace Doc { return alias; } - export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[]): Promise { + export async function makeClone(doc: Doc, cloneMap: Map, rtfs: { copy: Doc, key: string, field: RichTextField }[], exclusions: string[], dontCreate: boolean): Promise { if (Doc.IsBaseProto(doc)) return doc; if (cloneMap.get(doc[Id])) return cloneMap.get(doc[Id])!; - const copy = new Doc(undefined, true); + const copy = dontCreate ? doc : new Doc(undefined, true); cloneMap.set(doc[Id], copy); if (LinkManager.Instance.getAllLinks().includes(doc) && LinkManager.Instance.getAllLinks().indexOf(copy) === -1) LinkManager.Instance.addLink(copy); const filter = Cast(doc.cloneFieldFilter, listSpec("string"), exclusions); - Object.keys(doc).forEach(async key => { + await Promise.all(Object.keys(doc).map(async key => { if (filter.includes(key)) return; + const assignKey = (val: any) => !dontCreate && (copy[key] = val); const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key])); const field = ProxyField.WithoutProxy(() => doc[key]); const copyObjectField = async (field: ObjectField) => { const list = await Cast(doc[key], listSpec(Doc)); const docs = list && (await DocListCastAsync(list))?.filter(d => d instanceof Doc); if (docs !== undefined && docs.length) { - const clones = docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions)); - copy[key] = new List(await Promise.all(clones)); + const clones = await Promise.all(docs.map(async d => await Doc.makeClone(d as Doc, cloneMap, rtfs, exclusions, dontCreate))); + !dontCreate && assignKey(new List(clones)); } else if (doc[key] instanceof Doc) { - copy[key] = key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions); // reference documents except copy documents that are expanded teplate fields + assignKey(key.includes("layout[") ? undefined : key.startsWith("layout") ? doc[key] as Doc : await Doc.makeClone(doc[key] as Doc, cloneMap, rtfs, exclusions, dontCreate)); // reference documents except copy documents that are expanded teplate fields } else { - copy[key] = ObjectField.MakeCopy(field); + assignKey(ObjectField.MakeCopy(field)); if (field instanceof RichTextField) { if (field.Data.includes('"docid":') || field.Data.includes('"targetId":') || field.Data.includes('"linkId":')) { rtfs.push({ copy, key, field }); @@ -513,32 +519,34 @@ export namespace Doc { }; if (key === "proto") { if (doc[key] instanceof Doc) { - copy[key] = await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions); + assignKey(await Doc.makeClone(doc[key]!, cloneMap, rtfs, exclusions, dontCreate)); } } else { if (field instanceof RefField) { - copy[key] = field; + assignKey(field); } else if (cfield instanceof ComputedField) { - copy[key] = ComputedField.MakeFunction(cfield.script.originalScript); - (key === "links" && field instanceof ObjectField) && copyObjectField(field); + !dontCreate && assignKey(ComputedField.MakeFunction(cfield.script.originalScript)); + (key === "links" && field instanceof ObjectField) && await copyObjectField(field); } else if (field instanceof ObjectField) { - copyObjectField(field); + await copyObjectField(field); } else if (field instanceof Promise) { debugger; //This shouldn't happend... } else { - copy[key] = field; + assignKey(field); } } - }); - Doc.SetInPlace(copy, "title", "CLONE: " + doc.title, true); - copy.cloneOf = doc; - cloneMap.set(doc[Id], copy); + })); + if (!dontCreate) { + Doc.SetInPlace(copy, "title", "CLONE: " + doc.title, true); + copy.cloneOf = doc; + cloneMap.set(doc[Id], copy); + } return copy; } - export async function MakeClone(doc: Doc): Promise { + export async function MakeClone(doc: Doc, dontCreate: boolean = false) { const cloneMap = new Map(); const rtfMap: { copy: Doc, key: string, field: RichTextField }[] = []; - const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"]); + const copy = await Doc.makeClone(doc, cloneMap, rtfMap, ["context", "annotationOn", "cloneOf"], dontCreate); rtfMap.map(({ copy, key, field }) => { const replacer = (match: any, attr: string, id: string, offset: any, string: any) => { const mapped = cloneMap.get(id); @@ -552,9 +560,56 @@ export namespace Doc { const re = new RegExp(regex, "g"); copy[key] = new RichTextField(field.Data.replace(/("docid":|"targetId":|"linkId":)"([^"]+)"/g, replacer).replace(re, replacer2), field.Text); }); - return copy; - } + return { clone: copy, map: cloneMap }; + } + + export async function Zip(doc: Doc) { + const { clone, map } = await Doc.MakeClone(doc, true); + function replacer(key: any, value: any) { + console.log("Checkin: " + key); + if (["cloneOf", "context", "cursors"].includes(key)) return undefined; + else if (value instanceof Doc) { + if (key !== "field" && Number.isNaN(Number(key))) { + const __fields = value[FieldsSym](); + return { id: value[Id], __type: "Doc", fields: __fields }; + } else { + return { fieldId: value[Id], __type: "proxy" }; + } + } + else if (value instanceof RichTextField) return { Data: value.Data, Text: value.Text, __type: "RichTextField" }; + else if (value instanceof ImageField) return { url: value.url.href, __type: "image" }; + else if (value instanceof PdfField) return { url: value.url.href, __type: "pdf" }; + else if (value instanceof AudioField) return { url: value.url.href, __type: "audio" }; + else if (value instanceof VideoField) return { url: value.url.href, __type: "video" }; + else if (value instanceof WebField) return { url: value.url.href, __type: "web" }; + else if (value instanceof DateField) return { date: value.toString(), __type: "date" }; + else if (value instanceof ProxyField) return { fieldId: value.fieldId, __type: "proxy" }; + else if (value instanceof Array && key !== "fields") return { fields: value, __type: "list" }; + else if (value instanceof ComputedField) return { script: value.script, __type: "computed" }; + else return value; + } + + const docs: { [id: string]: any } = {}; + Array.from(map.entries()).forEach(f => docs[f[0]] = f[1]); + const docString = JSON.stringify({ id: doc[Id], docs }, replacer); + + var zip = new JSZip(); + zip.file("doc.json", docString); + + // // Generate a directory within the Zip file structure + // var img = zip.folder("images"); + + // // Add a file to the directory, in this case an image with data URI as contents + // img.file("smile.gif", imgData, {base64: true}); + + // Generate the zip file asynchronously + zip.generateAsync({ type: "blob" }) + .then((content: any) => { + // Force down of the Zip file + saveAs(content, "download.zip"); + }); + } // // Determines whether the layout needs to be expanded (as a template). // template expansion is rquired when the layout is a template doc/field and there's a datadoc which isn't equal to the layout template diff --git a/src/server/ApiManagers/UploadManager.ts b/src/server/ApiManagers/UploadManager.ts index 0b9e999ac..4455d11eb 100644 --- a/src/server/ApiManagers/UploadManager.ts +++ b/src/server/ApiManagers/UploadManager.ts @@ -16,6 +16,7 @@ const imageDataUri = require('image-data-uri'); import { isWebUri } from "valid-url"; import { launch } from "puppeteer"; import { Opt } from "../../fields/Doc"; +import { SolrManager } from "./SearchManager"; export enum Directory { parsed_files = "parsed_files", @@ -204,6 +205,7 @@ export default class UploadManager extends ApiManager { } catch (e) { console.log(e); } unlink(path_2, () => { }); } + SolrManager.update(); res.send(JSON.stringify(id ? getId(id) : "error")); } catch (e) { console.log(e); } resolve(); -- cgit v1.2.3-70-g09d2 From 0ea3c5b643a50de9cea673b769f5514fcef5d86b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 23 Jul 2020 10:25:00 -0400 Subject: fixed very slow resize performance caused by fetchinProto when there are no acl's. made images not be natively draggable. --- src/client/views/nodes/ImageBox.tsx | 9 +++++---- src/fields/util.ts | 5 ----- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'src/fields') diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 4eba21eab..5f689624c 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -158,6 +158,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent this.layoutDoc.isBackground = true, icon: "expand-arrows-alt" }); if (!Doc.UserDoc().noviceMode) { funcs.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" }); funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" }); @@ -315,7 +316,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent { const remoteUrl = this.dataDoc.googlePhotosUrl; - return !remoteUrl ? (null) : ( { @@ -415,7 +416,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent @@ -423,7 +424,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent
} diff --git a/src/fields/util.ts b/src/fields/util.ts index 81ccbf6d9..20b072786 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -130,11 +130,6 @@ export function setGroups(groups: string[]) { export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclEdit; - if (!target[AclSym] && target instanceof Doc) { - fetchProto(target); - } - - if (target[AclSym] && Object.keys(target[AclSym]).length) { if (target.__fields?.author === Doc.CurrentUserEmail || target.author === Doc.CurrentUserEmail || currentUserGroups.includes("admin")) return AclEdit; -- cgit v1.2.3-70-g09d2 From 3bcc0e3a8ce4ab67dff4b3d62191c346764aa351 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 23 Jul 2020 11:56:05 -0400 Subject: got rid of lots of console.logs(). fixed fonticon box to show a 'label' if defined otherwise 'title'. if neither, then it shows no tooltip. --- src/client/ClientRecommender.tsx | 2 -- src/client/apis/IBM_Recommender.ts | 2 -- .../apis/google_docs/GooglePhotosClientUtils.ts | 2 -- src/client/cognitive_services/CognitiveServices.ts | 2 -- src/client/documents/Documents.ts | 3 ++- src/client/util/CurrentUserUtils.ts | 1 - src/client/util/DictationManager.ts | 2 +- src/client/util/InteractionUtils.tsx | 2 -- src/client/util/ScriptManager.ts | 10 --------- src/client/util/SearchUtil.ts | 1 - src/client/util/SelectionManager.ts | 1 - src/client/views/EditableView.tsx | 1 - src/client/views/GestureOverlay.tsx | 1 - src/client/views/KeyphraseQueryView.tsx | 1 - src/client/views/ScriptBox.tsx | 2 +- src/client/views/SearchDocBox.tsx | 9 -------- src/client/views/Touchable.tsx | 3 --- src/client/views/animationtimeline/Keyframe.tsx | 4 ---- src/client/views/animationtimeline/Timeline.tsx | 1 - src/client/views/animationtimeline/Track.tsx | 4 ---- .../views/collections/CollectionCarousel3DView.tsx | 3 --- .../views/collections/CollectionCarouselView.tsx | 2 -- .../collections/CollectionMasonryViewFieldRow.tsx | 1 - src/client/views/collections/CollectionMenu.tsx | 2 +- .../views/collections/CollectionSchemaCells.tsx | 12 ----------- .../views/collections/CollectionSchemaView.tsx | 1 - src/client/views/collections/CollectionSubView.tsx | 2 -- .../views/collections/CollectionTreeView.tsx | 4 ---- src/client/views/collections/CollectionView.tsx | 2 +- src/client/views/collections/SchemaTable.tsx | 3 +-- .../collectionFreeForm/CollectionFreeFormView.tsx | 2 -- .../collections/collectionFreeForm/MarqueeView.tsx | 3 --- src/client/views/linking/LinkMenu.tsx | 1 - src/client/views/linking/LinkMenuItem.tsx | 5 ----- src/client/views/nodes/DocumentContentsView.tsx | 2 +- src/client/views/nodes/DocumentLinksButton.tsx | 2 -- src/client/views/nodes/DocumentView.tsx | 1 - src/client/views/nodes/FontIconBox.tsx | 24 ++++++++++++---------- src/client/views/nodes/PresBox.tsx | 1 - src/client/views/nodes/RadialMenu.tsx | 1 - src/client/views/nodes/ScreenshotBox.tsx | 2 +- src/client/views/nodes/ScriptingBox.tsx | 1 - src/client/views/nodes/VideoBox.tsx | 2 +- src/client/views/nodes/WebBox.tsx | 2 +- .../views/nodes/formattedText/DashDocView.tsx | 2 +- .../views/nodes/formattedText/RichTextSchema.tsx | 2 +- src/client/views/search/FilterBox.tsx | 1 - src/client/views/search/SearchBox.tsx | 5 +---- src/client/views/search/ToggleBar.tsx | 1 - src/fields/Doc.ts | 1 - src/fields/ScriptField.ts | 1 - src/fields/util.ts | 1 - src/server/Recommender.ts | 4 ---- src/server/downsize.ts | 2 +- 54 files changed, 28 insertions(+), 127 deletions(-) (limited to 'src/fields') diff --git a/src/client/ClientRecommender.tsx b/src/client/ClientRecommender.tsx index d18669b02..3f875057e 100644 --- a/src/client/ClientRecommender.tsx +++ b/src/client/ClientRecommender.tsx @@ -50,7 +50,6 @@ export class ClientRecommender extends React.Component { @observable private corr_matrix = [[0, 0], [0, 0]]; // for testing constructor(props: RecommenderProps) { - //console.log("creating client recommender..."); super(props); if (!ClientRecommender.Instance) ClientRecommender.Instance = this; ClientRecommender.Instance.docVectors = new Set(); @@ -383,7 +382,6 @@ export class ClientRecommender extends React.Component { case 200: const title_vals: string[] = []; const url_vals: string[] = []; - //console.log(result); if (xml) { const titles = xml.getElementsByTagName("title"); let counter = 1; diff --git a/src/client/apis/IBM_Recommender.ts b/src/client/apis/IBM_Recommender.ts index 480b9cb1c..e6265fcb5 100644 --- a/src/client/apis/IBM_Recommender.ts +++ b/src/client/apis/IBM_Recommender.ts @@ -29,10 +29,8 @@ // export const analyze = async (_parameters: any): Promise> => { // try { // const response = await naturalLanguageUnderstanding.analyze(_parameters); -// console.log(response); // return (JSON.stringify(response, null, 2)); // } catch (err) { -// console.log('error: ', err); // return undefined; // } // }; diff --git a/src/client/apis/google_docs/GooglePhotosClientUtils.ts b/src/client/apis/google_docs/GooglePhotosClientUtils.ts index 13bfb3a91..92eaf2e73 100644 --- a/src/client/apis/google_docs/GooglePhotosClientUtils.ts +++ b/src/client/apis/google_docs/GooglePhotosClientUtils.ts @@ -156,8 +156,6 @@ export namespace GooglePhotos { const values = Object.values(ContentCategories).filter(value => value !== ContentCategories.NONE); for (const value of values) { const searched = (await ContentSearch({ included: [value] }))?.mediaItems?.map(({ id }) => id); - console.log("Searching " + value); - console.log(searched); searched?.forEach(async id => { const image = await Cast(idMapping[id], Doc); if (image) { diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index 6b0b3e029..80961af14 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -377,7 +377,6 @@ export namespace CognitiveServices { console.log("successful vectorization!"); const vectorValues = new List(); indices.forEach((ind: any) => { - //console.log(wordvec.word); vectorValues.push(wordvecs[ind]); }); ClientRecommender.Instance.processVector(vectorValues, dataDoc, mainDoc); @@ -385,7 +384,6 @@ export namespace CognitiveServices { else { console.log("unsuccessful :( word(s) not in vocabulary"); } - //console.log(vectorValues.size); } ); } diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index e2569ec70..cd2792226 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -92,6 +92,7 @@ export interface DocumentOptions { layoutKey?: string; type?: string; title?: string; + label?: string; toolTip?: string; // tooltip to display on hover style?: string; page?: number; @@ -494,7 +495,7 @@ export namespace Docs { Doc.Get.FromJson({ data: device, appendToExisting: { targetDoc: Doc.GetProto(doc) } }); Doc.AddDocToList(parentProto, "data", doc); } else if (errors) { - console.log(errors); + console.log("Documents:" + errors); } else { alert("A Buxton document import was completely empty (??)"); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 23b8f09de..b47cfb33a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -487,7 +487,6 @@ export class CurrentUserUtils { // Sets up mobile menu if it is undefined creates a new one, otherwise returns existing menu static setupActiveMobileMenu(doc: Doc) { if (doc.activeMobileMenu === undefined) { - console.log("undefined"); doc.activeMobileMenu = this.setupMobileMenu(); } return doc.activeMobileMenu as Doc; diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts index 28b1ca6cf..540540642 100644 --- a/src/client/util/DictationManager.ts +++ b/src/client/util/DictationManager.ts @@ -121,7 +121,7 @@ export namespace DictationManager { const listenImpl = (options?: Partial) => { if (!recognizer) { - console.log(unsupported); + console.log("DictationManager:" + unsupported); return unsupported; } if (isListening) { diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 473d4a263..8b3614ea7 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -161,7 +161,6 @@ export namespace InteractionUtils { // return ( // InkOptionsMenu.Instance.getColors().map(color => { // const id1 = "arrowStartTest" + color; - // console.log(color); // // // ; @@ -383,7 +382,6 @@ export namespace InteractionUtils { // let dist12 = TwoPointEuclidist(pt1, pt2); // let dist23 = TwoPointEuclidist(pt2, pt3); // let dist13 = TwoPointEuclidist(pt1, pt3); - // console.log(`distances: ${dist12}, ${dist23}, ${dist13}`); // let dist12close = dist12 < leniency; // let dist23close = dist23 < leniency; // let dist13close = dist13 < leniency; diff --git a/src/client/util/ScriptManager.ts b/src/client/util/ScriptManager.ts index 785e63d9a..94806a7ba 100644 --- a/src/client/util/ScriptManager.ts +++ b/src/client/util/ScriptManager.ts @@ -32,24 +32,17 @@ export class ScriptManager { } public addScript(scriptDoc: Doc): boolean { - - console.log("in add script method"); - const scriptList = this.getAllScripts(); scriptList.push(scriptDoc); if (ScriptManager.Instance.ScriptManagerDoc) { ScriptManager.Instance.ScriptManagerDoc.data = new List(scriptList); ScriptManager.addScriptToGlobals(scriptDoc); - console.log("script added"); return true; } return false; } public deleteScript(scriptDoc: Doc): boolean { - - console.log("in delete script method"); - if (scriptDoc.name) { Scripting.removeGlobal(StrCast(scriptDoc.name)); } @@ -70,7 +63,6 @@ export class ScriptManager { Scripting.removeGlobal(StrCast(scriptDoc.name)); const params = Cast(scriptDoc["data-params"], listSpec("string"), []); - console.log(params); const paramNames = params.reduce((o: string, p: string) => { if (params.indexOf(p) === params.length - 1) { o = o + p.split(":")[0].trim(); @@ -82,8 +74,6 @@ export class ScriptManager { const f = new Function(paramNames, StrCast(scriptDoc.script)); - console.log(scriptDoc.script); - Object.defineProperty(f, 'name', { value: StrCast(scriptDoc.name), writable: false }); let parameters = "("; diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 1ac68480e..0a01d8ac7 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -128,7 +128,6 @@ export namespace SearchUtil { }); const result: IdSearchResult = JSON.parse(response); const { ids, numFound, highlighting } = result; - //console.log(ids.length); const docMap = await DocServer.GetRefFields(ids); const docs: Doc[] = []; for (const id of ids) { diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 9a968aeda..20d881961 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -22,7 +22,6 @@ export namespace SelectionManager { } manager.SelectedDocuments.set(docView, true); - // console.log(manager.SelectedDocuments); docView.props.whenActiveChanged(true); } else if (!ctrlPressed && Array.from(manager.SelectedDocuments.entries()).length > 1) { Array.from(manager.SelectedDocuments.keys()).map(dv => dv !== docView && dv.props.whenActiveChanged(false)); diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx index 25a87ab56..ad61d3f91 100644 --- a/src/client/views/EditableView.tsx +++ b/src/client/views/EditableView.tsx @@ -73,7 +73,6 @@ export class EditableView extends React.Component { // // this is done because when autosuggest is turned on, the suggestions are passed in as a prop, // // so when the suggestions are passed in, and no editing prop is passed in, it used to set it // // to false. this will no longer do so -syip - // console.log("props editing = " + nextProps.editing); // if (nextProps.editing && nextProps.editing !== this._editing) { // this._editing = nextProps.editing; // EditableView.loadId = ""; diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index b0b0d72b1..2e588ceb5 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -160,7 +160,6 @@ export default class GestureOverlay extends Touchable { if (nts.nt.length === 1) { // -- radial menu code -- this._holdTimer = setTimeout(() => { - console.log("hold"); const target = document.elementFromPoint(te.changedTouches?.item(0).clientX, te.changedTouches?.item(0).clientY); const pt: any = te.touches[te.touches?.length - 1]; if (nts.nt.length === 1 && pt.radiusX > 1 && pt.radiusY > 1) { diff --git a/src/client/views/KeyphraseQueryView.tsx b/src/client/views/KeyphraseQueryView.tsx index 1dc156968..13d52db88 100644 --- a/src/client/views/KeyphraseQueryView.tsx +++ b/src/client/views/KeyphraseQueryView.tsx @@ -11,7 +11,6 @@ export interface KP_Props { export class KeyphraseQueryView extends React.Component{ constructor(props: KP_Props) { super(props); - console.log("FIRST KEY PHRASE: ", props.keyphrases[0]); } render() { diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index 888f84dfa..2c185be86 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -39,7 +39,7 @@ export class ScriptBox extends React.Component { @action onError = (error: string) => { - console.log(error); + console.log("ScriptBox: " + error); } overlayDisposer?: () => void; diff --git a/src/client/views/SearchDocBox.tsx b/src/client/views/SearchDocBox.tsx index e038d8213..084f952a3 100644 --- a/src/client/views/SearchDocBox.tsx +++ b/src/client/views/SearchDocBox.tsx @@ -60,8 +60,6 @@ export class SearchDocBox extends React.Component { componentDidMount() { runInAction(() => { - console.log("didit" - ); this.query = StrCast(this.props.Document.searchText); this.content = (Docs.Create.TreeDocument(DocListCast(Doc.GetProto(this.props.Document).data), { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query })); @@ -83,12 +81,9 @@ export class SearchDocBox extends React.Component { if (newKey.length > 1) { const newdocs = await this.getAllResults(this.query); const things = newdocs.docs; - console.log(things); - console.log(this.content); runInAction(() => { this.content = Docs.Create.TreeDocument(things, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs:` + this.query }); }); - console.log(this.content); } @@ -150,12 +145,9 @@ export class SearchDocBox extends React.Component { } enter = async (e: React.KeyboardEvent) => { - console.log(e.key); if (e.key === "Enter") { const newdocs = await this.getAllResults(this.query); - console.log(newdocs.docs); this.content = Docs.Create.TreeDocument(newdocs.docs, { _width: 200, _height: 400, _chromeStatus: "disabled", title: `Search Docs: "Results"` }); - } } @@ -256,7 +248,6 @@ export class SearchDocBox extends React.Component { startDragCollection = async () => { const res = await this.getAllResults(FilterBox.Instance.getFinalQuery(this._searchString)); const filtered = FilterBox.Instance.filterDocsByType(res.docs); - // console.log(this._results) const docs = filtered.map(doc => { const isProto = Doc.GetT(doc, "isPrototype", "boolean", true); if (isProto) { diff --git a/src/client/views/Touchable.tsx b/src/client/views/Touchable.tsx index 5e48d5ffb..c4cae7e8d 100644 --- a/src/client/views/Touchable.tsx +++ b/src/client/views/Touchable.tsx @@ -54,7 +54,6 @@ export abstract class Touchable extends React.Component { } }); - // console.log(ptsToDelete.length); ptsToDelete.forEach(pt => this.prevPoints.delete(pt)); if (this.prevPoints.size) { @@ -86,7 +85,6 @@ export abstract class Touchable extends React.Component { // if we're not actually moving a lot, don't consider it as dragging yet if (!InteractionUtils.IsDragging(this.prevPoints, myTouches, 5) && !this._touchDrag) return; this._touchDrag = true; - // console.log(myTouches.length); switch (myTouches.length) { case 1: this.handle1PointerMove(te, me); @@ -107,7 +105,6 @@ export abstract class Touchable extends React.Component { @action protected onTouchEnd = (e: Event, me: InteractionUtils.MultiTouchEvent): void => { - // console.log(InteractionUtils.GetMyTargetTouches(e, this.prevPoints).length + " up"); // remove all the touches associated with the event const te = me.touchEvent; for (const pt of me.changedTouches) { diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index 3a7182a94..1b81c544a 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -527,10 +527,6 @@ export class Keyframe extends React.Component { */ //154, 206, 223 render() { - trace(); - console.log(this.props.RegionData.position); - console.log(this.regiondata.position); - console.log(this.pixelPosition); return (
{ //TODO: remove undefineds and duplicates } }); - // console.log(longestTime); return longestTime; } diff --git a/src/client/views/animationtimeline/Track.tsx b/src/client/views/animationtimeline/Track.tsx index 4987006e7..25c2e68e7 100644 --- a/src/client/views/animationtimeline/Track.tsx +++ b/src/client/views/animationtimeline/Track.tsx @@ -134,7 +134,6 @@ export class Track extends React.Component { autoCreateKeyframe = () => { const objects = this.objectWhitelist.map(key => this.props.node[key]); intercept(this.props.node, change => { - console.log(change); return change; }); return reaction(() => { @@ -174,7 +173,6 @@ export class Track extends React.Component { if (regiondata) { this.props.node.hidden = false; // if (!this._autoKfReaction) { - // // console.log("creating another reaction"); // // this._autoKfReaction = this.autoCreateKeyframe(); // } this.timeChange(); @@ -204,7 +202,6 @@ export class Track extends React.Component { } }); } else { - console.log("reverting state"); //this.revertState(); } }); @@ -229,7 +226,6 @@ export class Track extends React.Component { const rightkf: (Doc | undefined) = await KeyframeFunc.calcMinRight(regiondata, this.time); //right keyframe, if it exists const currentkf: (Doc | undefined) = await this.calcCurrent(regiondata); //if the scrubber is on top of the keyframe if (currentkf) { - console.log("is current"); await this.applyKeys(currentkf); this.saveStateKf = currentkf; this.saveStateRegion = regiondata; diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index 8e9970ada..0f3b6f212 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -86,7 +86,6 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume interval?: number; startAutoScroll = (direction: number) => { this.interval = window.setInterval(() => { - console.log(this.interval, this.scrollSpeed); this.changeSlide(direction); }, this.scrollSpeed); } @@ -113,13 +112,11 @@ export class CollectionCarousel3DView extends CollectionSubView(Carousel3DDocume onPointerDown = (e: React.PointerEvent) => { this._downX = e.clientX; this._downY = e.clientY; - console.log("CAROUSEL down"); document.addEventListener("pointerup", this.onpointerup); } private _lastTap: number = 0; private _doubleTap = false; onpointerup = (e: PointerEvent) => { - console.log("CAROUSEL up"); this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2); this._lastTap = Date.now(); } diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx index 404dc0daa..27aea4b99 100644 --- a/src/client/views/collections/CollectionCarouselView.tsx +++ b/src/client/views/collections/CollectionCarouselView.tsx @@ -91,13 +91,11 @@ export class CollectionCarouselView extends CollectionSubView(CarouselDocument) onPointerDown = (e: React.PointerEvent) => { this._downX = e.clientX; this._downY = e.clientY; - console.log("CAROUSEL down"); document.addEventListener("pointerup", this.onpointerup); } private _lastTap: number = 0; private _doubleTap = false; onpointerup = (e: PointerEvent) => { - console.log("CAROUSEL up"); this._doubleTap = (Date.now() - this._lastTap < 300 && e.button === 0 && Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2); this._lastTap = Date.now(); } diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx index 627b22417..9a7ea2c93 100644 --- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx +++ b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx @@ -84,7 +84,6 @@ export class CollectionMasonryViewFieldRow extends React.Component { - console.log("masronry row drop"); this._createAliasSelected = false; if (de.complete.docDragData) { (this.props.parent.Document.dropConverter instanceof ScriptField) && diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 5d95b214a..992c1f600 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -462,7 +462,7 @@ export class CollectionFreeFormViewChrome extends React.Component -
+
diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index d76b6d204..eecaf7672 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -151,7 +151,6 @@ export class CollectionSchemaCell extends React.Component { // let field = this.props.rowProps.original[this.props.rowProps.column.id as string]; // let doc = FieldValue(Cast(field, Doc)); - // console.log("Expanding doc", StrCast(doc!.title)); // this.props.setPreviewDoc(doc!); // // this.props.changeFocusedCellByIndex(this.props.row, this.props.col); @@ -265,7 +264,6 @@ export class CollectionSchemaCell extends React.Component { return "0"; } else { const cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey])); - console.log(cfield); if (type === "number") { return StrCast(cfield); } @@ -286,7 +284,6 @@ export class CollectionSchemaCell extends React.Component { const script = CompileScript(value, { requiredType: type, typecheck: false, editable: true, addReturn: true, params: { this: Doc.name, $r: "number", $c: "number", $: "any" } }); if (script.compiled) { retVal = this.applyToDoc(props.Document, this.props.row, this.props.col, script.run); - console.log("compiled"); } } @@ -350,17 +347,13 @@ export class CollectionSchemaDateCell extends CollectionSchemaCell { @action handleChange = (date: any) => { - console.log(date); this._date = date; // const script = CompileScript(date.toString(), { requiredType: "Date", addReturn: true, params: { this: Doc.name } }); // if (script.compiled) { - // console.log("scripting"); // this.applyToDoc(this._document, this.props.row, this.props.col, script.run); // } else { - console.log(DateCast(date)); // ^ DateCast is always undefined for some reason, but that is what the field should be set to this._document[this.props.rowProps.column.id as string] = date as Date; - console.log(this._document[this.props.rowProps.column.id as string]); //} } @@ -425,8 +418,6 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell { const results = script.compiled && script.run(); if (results && results.success) { - - console.log(results.result); this._doc = results.result; this._document[this.prop.fieldKey] = results.result; this._docTitle = this._doc?.title; @@ -457,10 +448,8 @@ export class CollectionSchemaDocCell extends CollectionSchemaCell { this._preview = false; } else { if (bool) { - console.log("show doc"); this.props.showDoc(this._doc, this.prop.DataDoc, e.clientX, e.clientY); } else { - console.log("no doc"); this.props.showDoc(undefined); } } @@ -675,7 +664,6 @@ export class CollectionSchemaListCell extends CollectionSchemaCell { @action toggleOpened(open: boolean) { - console.log("open: " + open); this._opened = open; } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 3c42a2f1c..5553bbbb7 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -332,7 +332,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action openHeader = (col: any, screenx: number, screeny: number) => { - console.log("header opening"); this._col = col; this._headerOpen = !this._headerOpen; this._pointerX = screenx; diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index a147b06a3..8480a56cc 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -340,7 +340,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: // if ((matches = /(https:\/\/)?photos\.google\.com\/(u\/3\/)?album\/([^\\]+)/g.exec(text)) !== null) { // const albumId = matches[3]; // const mediaItems = await GooglePhotos.Query.AlbumSearch(albumId); - // console.log(mediaItems); // return; // } } @@ -381,7 +380,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: file?.type && files.push(file); file?.type === "application/json" && Utils.readUploadedFileAsText(file).then(result => { - console.log(result); const json = JSON.parse(result as string); this.addDocument(Docs.Create.TreeDocument( json["rectangular-puzzle"].crossword.clues[0].clue.map((c: any) => { diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 96a2e23c9..651357e5d 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -796,9 +796,6 @@ export class CollectionTreeView extends CollectionSubView; } - onKeyPress = (e: React.KeyboardEvent) => { - console.log(e); - } onChildClick = () => { return this.props.onChildClick?.() || ScriptCast(this.doc.onChildClick); } @@ -819,7 +816,6 @@ export class CollectionTreeView extends CollectionSubView this._mainEle && this._mainEle.scrollHeight > this._mainEle.clientHeight && e.stopPropagation()} onDrop={this.onTreeDrop} ref={this.createTreeDropTarget}> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 53fd83f26..e2f78d6f9 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -167,7 +167,7 @@ export class CollectionView extends Touchable { @action changeSorting = (col: any) => { - console.log(col.heading); if (col.desc === undefined) { // no sorting this.props.changeColumnSort(col, true); @@ -149,7 +148,7 @@ export class SchemaTable extends React.Component { } @action - changeTitleMode = () => { console.log("header clicked"); this._showTitleDropdown = !this._showTitleDropdown; } + changeTitleMode = () => this._showTitleDropdown = !this._showTitleDropdown; @computed get borderWidth() { return Number(COLLECTION_BORDER_WIDTH); } @computed get tableColumns(): Column[] { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 3b19a2ab8..979b21321 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -497,10 +497,8 @@ export class CollectionFreeFormView extends CollectionSubView p.X)), Math.min(...ge.points.map(p => p.Y))); this._inkToTextStartX = start[0]; this._inkToTextStartY = start[1]; - console.log("start"); break; case GestureUtils.Gestures.EndBracket: - console.log("end"); if (this._inkToTextStartX && this._inkToTextStartY) { const end = this.getTransform().transformPoint(Math.max(...ge.points.map(p => p.X)), Math.max(...ge.points.map(p => p.Y))); const setDocs = this.getActiveDocuments().filter(s => s.proto?.type === "rtf" && s.color); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 84719b2c9..aa9a3b4ae 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -434,8 +434,6 @@ export class MarqueeView extends React.Component { // const wordResults = results.filter((r: any) => r.category === "inkWord"); - // console.log(wordResults); - // console.log(results); // for (const word of wordResults) { // const indices: number[] = word.strokeIds; // indices.forEach(i => { @@ -476,7 +474,6 @@ export class MarqueeView extends React.Component r.category === "line"); - console.log(lines); const text = lines.map((l: any) => l.recognizedText).join("\r\n"); this.props.addDocument(Docs.Create.TextDocument(text, { _width: this.Bounds.width, _height: this.Bounds.height, x: this.Bounds.left + this.Bounds.width, y: this.Bounds.top, title: text })); }); diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx index 2d151e9bc..7b5fb0127 100644 --- a/src/client/views/linking/LinkMenu.tsx +++ b/src/client/views/linking/LinkMenu.tsx @@ -46,7 +46,6 @@ export class LinkMenu extends React.Component { if (this._linkMenuRef && !this._linkMenuRef.current?.contains(e.target as any)) { if (this._editorRef && !this._editorRef.current?.contains(e.target as any)) { - console.log("outside click"); DocumentLinksButton.EditLink = undefined; } } diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx index d8ba39f09..d1c839c3b 100644 --- a/src/client/views/linking/LinkMenuItem.tsx +++ b/src/client/views/linking/LinkMenuItem.tsx @@ -81,10 +81,7 @@ export class LinkMenuItem extends React.Component { @action toggleShowMore(e: React.PointerEvent) { e.stopPropagation(); this._showMore = !this._showMore; } onEdit = (e: React.PointerEvent): void => { - - console.log("Edit"); LinkManager.currentLink = this.props.linkDoc; - console.log(this.props.linkDoc); setupMoveUpEvents(this, e, this.editMoved, emptyFunction, () => this.props.showEditor(this.props.linkDoc)); } @@ -119,7 +116,6 @@ export class LinkMenuItem extends React.Component { document.addEventListener("pointerup", this.onLinkButtonUp); if (this._buttonRef && !!!this._buttonRef.current?.contains(e.target as any)) { - console.log("outside click"); LinkDocPreview.LinkInfo = undefined; } } @@ -153,7 +149,6 @@ export class LinkMenuItem extends React.Component { @action.bound async followDefault() { - console.log("FOLLOWWW"); DocumentLinksButton.EditLink = undefined; LinkDocPreview.LinkInfo = undefined; diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index f2f8ada68..47dc0a773 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -200,7 +200,7 @@ export class DocumentContentsView extends React.Component { console.log(test); }} + onError={(test: any) => { console.log("DocumentContentsView:" + test); }} />; } } \ No newline at end of file diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx index 13bec5d7f..b17accfd6 100644 --- a/src/client/views/nodes/DocumentLinksButton.tsx +++ b/src/client/views/nodes/DocumentLinksButton.tsx @@ -68,8 +68,6 @@ export class DocumentLinksButton extends React.Component Doc.BrushDoc(this.props.View.Document)); DocumentLinksButton.StartLink = this.props.View; } else if (!this.props.InMenu) { - console.log("editing"); - this.props.View ? console.log("view") : null; DocumentLinksButton.EditLink = this.props.View; DocumentLinksButton.EditLinkLoc = [e.clientX + 10, e.clientY]; } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9e492650b..998c6798e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -910,7 +910,6 @@ export class DocumentView extends DocComponent(Docu if (!ClientRecommender.Instance) new ClientRecommender({ title: "Client Recommender" }); const documents: Doc[] = []; const allDocs = await SearchUtil.GetAllDocs(); - // allDocs.forEach(doc => console.log(doc.title)); // clears internal representation of documents as vectors ClientRecommender.Instance.reset_docs(); //ClientRecommender.Instance.arxivrequest("electrons"); diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx index a4d16fe0e..ab34e13b0 100644 --- a/src/client/views/nodes/FontIconBox.tsx +++ b/src/client/views/nodes/FontIconBox.tsx @@ -61,16 +61,18 @@ export class FontIconBox extends DocComponent( render() { const referenceDoc = (this.layoutDoc.dragFactory instanceof Doc ? this.layoutDoc.dragFactory : this.layoutDoc); const refLayout = Doc.Layout(referenceDoc); - return {StrCast(this.layoutDoc.toolTip)}
}> - - ; + const button = ; + return !this.layoutDoc.toolTip ? button : + {StrCast(this.layoutDoc.toolTip)}
}> + {button} + ; } } \ No newline at end of file diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 8818d375e..a304ced18 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -297,7 +297,6 @@ export class PresBox extends ViewBoxBaseComponent (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) render() { - // console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus); // const presOrderedDocs = DocListCast(this.rootDoc.presOrderedDocs); // if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) { // this.rootDoc.presOrderedDocs = new List(this.childDocs.slice()); diff --git a/src/client/views/nodes/RadialMenu.tsx b/src/client/views/nodes/RadialMenu.tsx index a3ac09a11..7f0956e51 100644 --- a/src/client/views/nodes/RadialMenu.tsx +++ b/src/client/views/nodes/RadialMenu.tsx @@ -89,7 +89,6 @@ export class RadialMenu extends React.Component { @action componentDidMount = () => { - console.log(this._pageX); document.addEventListener("pointerdown", this.onPointerDown); document.addEventListener("pointerup", this.onPointerUp); this.previewcircle(); diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index f7dee0896..1cd29d795 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -112,7 +112,7 @@ export class ScreenshotBox extends ViewBoxBaseComponent([]); } catch (e) { - console.log("Error in URL :" + this._url); + console.log("WebBox URL error:" + this._url); } } diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx index 5c3f3dcc9..212da3f3d 100644 --- a/src/client/views/nodes/formattedText/DashDocView.tsx +++ b/src/client/views/nodes/formattedText/DashDocView.tsx @@ -209,7 +209,7 @@ export class DashDocView extends React.Component { 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" })); } catch (e) { - console.log(e); + console.log("DashDocView:" + e); } } diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx index 7a50ec3af..33a080fe4 100644 --- a/src/client/views/nodes/formattedText/RichTextSchema.tsx +++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx @@ -170,7 +170,7 @@ export class DashDocView { } } } catch (e) { - console.log(e); + console.log("RichTextSchema: " + e); } } }; diff --git a/src/client/views/search/FilterBox.tsx b/src/client/views/search/FilterBox.tsx index 4b53963a5..eb61f9a14 100644 --- a/src/client/views/search/FilterBox.tsx +++ b/src/client/views/search/FilterBox.tsx @@ -352,7 +352,6 @@ export class FilterBox extends React.Component { getDataStatus() { return this._deletedDocsStatus; } getActiveFilters() { - console.log(this._authorFieldStatus, this._titleFieldStatus, this._dataFieldStatus); return (
{!this._basicWordStatus ?
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index c9d29e485..99fa6da21 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -125,7 +125,7 @@ export class SearchBox extends React.Component { return returnedUri; } catch (e) { - console.log(e); + console.log("SearchBox:" + e); } } @@ -582,7 +582,6 @@ export class SearchBox extends React.Component { } expandSection(thing: string) { - console.log("expand"); const element = document.getElementById(thing)!; // get the height of the element's inner content, regardless of its actual size const sectionHeight = element.scrollHeight; @@ -593,7 +592,6 @@ export class SearchBox extends React.Component { // when the next css transition finishes (which should be the one we just triggered) element.addEventListener('transitionend', function handler(e) { // remove this event listener so it only gets triggered once - console.log("autoset"); element.removeEventListener('transitionend', handler); // remove "height" from the element's inline styles, so it can return to its initial value @@ -608,7 +606,6 @@ export class SearchBox extends React.Component { autoset(thing: string) { const element = document.getElementById(thing)!; - console.log("autoset"); element.removeEventListener('transitionend', function (e) { }); // remove "height" from the element's inline styles, so it can return to its initial value diff --git a/src/client/views/search/ToggleBar.tsx b/src/client/views/search/ToggleBar.tsx index e4d7f2fd5..466822eba 100644 --- a/src/client/views/search/ToggleBar.tsx +++ b/src/client/views/search/ToggleBar.tsx @@ -58,7 +58,6 @@ export class ToggleBar extends React.Component{ this._forwardTimeline.play(); this._forwardTimeline.reverse(); this.props.handleChange(); - console.log(this.props.getStatus()); } @action.bound diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 917a6853c..7e91a7761 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -566,7 +566,6 @@ export namespace Doc { export async function Zip(doc: Doc) { const { clone, map } = await Doc.MakeClone(doc, true); function replacer(key: any, value: any) { - console.log("Checkin: " + key); if (["cloneOf", "context", "cursors"].includes(key)) return undefined; else if (value instanceof Doc) { if (key !== "field" && Number.isNaN(Number(key))) { diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 4604a2132..bd08b2f32 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -53,7 +53,6 @@ async function deserializeScript(script: ScriptField) { if (script.script.originalScript === 'convertToButtons(dragData)') { return (script as any).script = (ScriptField.ConvertToButtons ?? (ScriptField.ConvertToButtons = ComputedField.MakeFunction('convertToButtons(dragData)', { dragData: "DocumentDragData" })))?.script; } - console.log(script.script.originalScript); const captures: ProxyField = (script as any).captures; if (captures) { const doc = (await captures.value())!; diff --git a/src/fields/util.ts b/src/fields/util.ts index 20b072786..ef66d9633 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -35,7 +35,6 @@ export namespace Plugins { } const _setterImpl = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { - //console.log("-set " + target[SelfProxy].title + "(" + target[SelfProxy][prop] + ")." + prop.toString() + " = " + value); if (SerializationHelper.IsSerializing()) { target[prop] = value; return true; diff --git a/src/server/Recommender.ts b/src/server/Recommender.ts index 423ce9b46..935ec3871 100644 --- a/src/server/Recommender.ts +++ b/src/server/Recommender.ts @@ -21,7 +21,6 @@ // private choice: string = ""; // Tensorflow or Word2Vec // constructor() { -// console.log("creating recommender..."); // Recommender.Instance = this; // } @@ -70,7 +69,6 @@ // if (this._model) { // if (this.choice === "WV") { // let similarity = this._model.similarity('father', 'mother'); -// console.log(similarity); // } // else if (this.choice === "TF") { // const model = this._model as use.UniversalSentenceEncoder; @@ -119,7 +117,6 @@ // } // // public async trainModel() { -// // console.log("phrasing..."); // // w2v.word2vec("./node_modules/word2vec/examples/eng_news-typical_2016_1M-sentences.txt", './node_modules/word2vec/examples/my_phrases.txt', { // // cbow: 1, // // size: 200, @@ -131,7 +128,6 @@ // // iter: 200, // // minCount: 2 // // }); -// // console.log("phrased!!!"); // // } // } diff --git a/src/server/downsize.ts b/src/server/downsize.ts index cd0d83812..5cd709fa3 100644 --- a/src/server/downsize.ts +++ b/src/server/downsize.ts @@ -7,7 +7,7 @@ const jpgTypes = ["jpg", "JPG", "jpeg", "JPEG"]; const smallResizer = sharp().resize(100); fs.readdir(folder, async (err, files) => { if (err) { - console.log(err); + console.log("readdir:" + err); return; } // files.forEach(file => { -- cgit v1.2.3-70-g09d2