From 88593faa4777b622ed5a3208f6462cf7b307b83a Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Tue, 26 May 2020 23:09:56 -0700 Subject: pulled from master --- src/client/util/CurrentUserUtils.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 496099557..377f908e9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -444,6 +444,10 @@ export class CurrentUserUtils { }); } + static setupMobileMenu(userDoc: Doc) { + return CurrentUserUtils.setupWorkspaces(userDoc); + } + static setupMobileInkingDoc(userDoc: Doc) { return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white" }); } -- cgit v1.2.3-70-g09d2 From 662ab0537e6b7b3d15fd44b6e2695052025ed83b Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Sun, 31 May 2020 15:34:51 -0700 Subject: removed unecessary imports --- src/client/util/CurrentUserUtils.ts | 12 ++++++------ src/mobile/ImageUpload.tsx | 1 - src/mobile/MobileInterface.tsx | 26 +++++++++++++++++--------- 3 files changed, 23 insertions(+), 16 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 377f908e9..1cce81ce6 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -614,12 +614,12 @@ export class CurrentUserUtils { /// sets up the default list of buttons to be shown in the expanding button menu at the bottom of the Dash window static setupDockedButtons(doc: Doc) { - if (doc["dockedBtn-pen"] === undefined) { - doc["dockedBtn-pen"] = CurrentUserUtils.ficon({ - onClick: ScriptField.MakeScript("activatePen(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this, this.inkWidth, this.backgroundColor)"), - author: "systemTemplates", title: "ink mode", icon: "pen-nib", ischecked: ComputedField.MakeFunction(`sameDocs(this.activePen.inkPen, this)`), activePen: doc - }); - } + // if (doc["dockedBtn-pen"] === undefined) { + doc["dockedBtn-pen"] = CurrentUserUtils.ficon({ + onClick: ScriptField.MakeScript("activatePen(this.activePen.inkPen = sameDocs(this.activePen.inkPen, this) ? undefined : this, this.inkWidth, this.backgroundColor)"), + author: "systemTemplates", title: "ink mode", icon: "pen-nib", ischecked: ComputedField.MakeFunction(`sameDocs(this.activePen.inkPen, this)`), activePen: doc + }); + // } if (doc["dockedBtn-undo"] === undefined) { doc["dockedBtn-undo"] = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("undo()"), title: "undo button", icon: "undo-alt" }); } diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 2552e2112..fb0e444b5 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -12,7 +12,6 @@ import { observer } from 'mobx-react'; import { observable } from 'mobx'; import { Utils } from '../Utils'; import { Networking } from '../client/Network'; -import { MobileDocumentUploadContent } from '../server/Message'; export interface ImageUploadProps { Document: Doc; diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 9b28d066c..4c36fdb9b 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -7,7 +7,7 @@ import { observer } from 'mobx-react'; import * as ReactDOM from "react-dom"; import * as rp from 'request-promise'; import { CurrentUserUtils } from '../client/util/CurrentUserUtils'; -import { FieldValue, Cast, StrCast } from '../fields/Types'; +import { FieldValue, Cast, StrCast, BoolCast } from '../fields/Types'; import { Doc, DocListCast, Opt } from '../fields/Doc'; import { Docs } from '../client/documents/Documents'; import { CollectionView } from '../client/views/collections/CollectionView'; @@ -34,20 +34,21 @@ import RichTextMenu from '../client/views/nodes/formattedText/RichTextMenu'; import { MainView } from '../client/views/MainView'; import SettingsManager from '../client/util/SettingsManager'; import { Uploader } from "./ImageUpload"; -import { Upload } from '../server/SharedMediaTypes'; import { createTypePredicateNodeWithModifier } from 'typescript'; import { AudioBox } from '../client/views/nodes/AudioBox'; import { List } from '../fields/List'; +import { ScriptField, ComputedField } from '../fields/ScriptField'; library.add(faLongArrowAltLeft); library.add(faHome); @observer -export class MobileInterface extends React.Component { +export default class MobileInterface extends React.Component { @observable static Instance: MobileInterface; @computed private get userDoc() { return Doc.UserDoc(); } @computed private get mainContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } @computed private get activeContainer() { return this.userDoc ? FieldValue(Cast(this.userDoc.activeMobile, Doc)) : CurrentUserUtils.GuestMobile; } + private get darkScheme() { return BoolCast(Cast(this.userDoc?.activeWorkspace, Doc, null)?.darkScheme); } // @observable private currentView: "main" | "ink" | "upload" = "main"; @observable private mainDoc: any = CurrentUserUtils.setupMobileMenu(this.userDoc); @observable private renderView?: () => JSX.Element; @@ -301,6 +302,9 @@ export class MobileInterface extends React.Component {
SettingsManager.Instance.open()}> Settings
+
CurrentUserUtils.setupDockedButtons(this._activeDoc)}> + Ink +
@@ -333,6 +337,9 @@ export class MobileInterface extends React.Component {
{buttons}
+
CurrentUserUtils.setupDockedButtons(this.userDoc)}> + Ink +
Home
@@ -493,6 +500,7 @@ export class MobileInterface extends React.Component { e.stopPropagation(); } + render() { // const content = this.currentView === "main" ? this.mainContent : // this.currentView === "ink" ? this.inkContent : @@ -505,19 +513,19 @@ export class MobileInterface extends React.Component { */} {/* */} - {this.displayWorkspaces()} + + {this.displayWorkspaces()} + {this.renderDefaultContent()} + {/* */} {/* */} {/* */} -
- {this.renderDefaultContent()} -
{/* */} {/* */} - {/* - */} + + {/* */} {/* */} -- cgit v1.2.3-70-g09d2 From 5b4b916b2700da746c12754ba3238eb1f3bbf5f7 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 15 Aug 2020 01:42:57 +0530 Subject: many changes to acls, aliases, sharing sidebar etc --- src/client/documents/Documents.ts | 2 +- src/client/util/CurrentUserUtils.ts | 2 +- src/client/util/SharingManager.tsx | 20 ++++++------ src/client/views/PropertiesButtons.tsx | 12 ++++--- .../collectionFreeForm/PropertiesView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 3 +- src/fields/util.ts | 37 ++++++++++++---------- 7 files changed, 42 insertions(+), 36 deletions(-) (limited to 'src/client/util') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 42ba4d2c4..c424c2bef 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -575,7 +575,7 @@ export namespace Docs { // without this, if a doc has no annotations but the user has AddOnly privileges, they won't be able to add an annotation because they would have needed to create the field's list which they don't have permissions to do. dataDoc[fieldKey + "-annotations"] = new List(); - dataDoc.aliases = new List(); + dataDoc.aliases = new List([viewDoc]); proto.links = ComputedField.MakeFunction("links(self)"); diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 68d02cd94..907b42327 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -846,7 +846,7 @@ export class CurrentUserUtils { // Sharing sidebar is where shared documents are contained static setupSharingSidebar(doc: Doc) { if (doc["sidebar-sharing"] === undefined) { - doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias", system: true })); + doc["sidebar-sharing"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Shared Documents", childDropAction: "alias", system: true, _yMargin: 30, _showTitle: "title", ignoreClick: true, lockedPosition: true })); } } diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 48a3c023f..9d79188a3 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -155,16 +155,17 @@ export default class SharingManager extends React.Component<{}> { const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); const target = targetDoc || this.targetDoc!; - const ACL = `ACL-${StrCast(group.groupName)}`; + const key = StrCast(group.groupName).replace(".", "_"); + const ACL = `ACL-${key}`; - target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); + GetEffectiveAcl(target) === AclAdmin && distributeAcls(ACL, permission as SharingPermissions, target); // if documents have been shared, add the target to that list if it doesn't already exist, otherwise create a new list with the target group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List).push(target) : group.docsShared = new List([target]); - users.forEach(({ notificationDoc }) => { + users.forEach(({ user, notificationDoc }) => { if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); // add the target to the notificationDoc if it hasn't already been added - else Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists }); } @@ -231,14 +232,11 @@ export default class SharingManager extends React.Component<{}> { const key = user.email.replace('.', '_'); const ACL = `ACL-${key}`; - target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); + GetEffectiveAcl(target) === AclAdmin && distributeAcls(ACL, permission as SharingPermissions, target); + + if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); - if (permission !== SharingPermissions.None) { - Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); - } - else { - Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); - } } diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 35d4f7f6e..dfedc9ccc 100644 --- a/src/client/views/PropertiesButtons.tsx +++ b/src/client/views/PropertiesButtons.tsx @@ -3,7 +3,7 @@ import { faArrowAltCircleDown, faArrowAltCircleRight, faArrowAltCircleUp, faChec import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { Doc } from "../../fields/Doc"; +import { Doc, DataSym, AclEdit, AclAdmin } from "../../fields/Doc"; import { RichTextField } from '../../fields/RichTextField'; import { Cast, NumCast, BoolCast } from "../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from "../../Utils"; @@ -30,6 +30,7 @@ import { undoBatch, UndoManager } from '../util/UndoManager'; import { DocumentType } from '../documents/DocumentTypes'; import { InkField } from '../../fields/InkField'; import { PresBox } from './nodes/PresBox'; +import { GetEffectiveAcl } from '../../fields/util'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; @@ -710,6 +711,7 @@ export class PropertiesButtons extends React.Component<{}, {}> { const isCollection = this.selectedDoc.type === DocumentType.COL ? true : false; const isFreeForm = this.selectedDoc._viewType === "freeform" ? true : false; const hasContext = this.selectedDoc.context ? true : false; + const collectionAcl = GetEffectiveAcl(this.selectedDocumentView?.props.ContainingCollectionDoc?.[DataSym]); return
@@ -733,9 +735,11 @@ export class PropertiesButtons extends React.Component<{}, {}> {
{this.downloadButton}
-
- {this.deleteButton} -
+ {collectionAcl === AclAdmin || collectionAcl === AclEdit ? +
+ {this.deleteButton} +
+ : (null)}
{this.onClickButton}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 57e968aa7..b38eed495 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -403,7 +403,7 @@ export class PropertiesView extends React.Component { // }) // shifts the current user and the owner to the top of the doc. - tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : StrCast(this.selectedDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]))); + tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); return
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index d92dc0ec2..3986a21e8 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -763,7 +763,8 @@ export class DocumentView extends DocComponent(Docu Doc.AreProtosEqual(this.props.Document, Doc.UserDoc()) && moreItems.push({ description: "Toggle Always Show Link End", event: () => Doc.UserDoc()["documentLinksButton-hideEnd"] = !Doc.UserDoc()["documentLinksButton-hideEnd"], icon: "eye" }); } - moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" }); + const collectionAcl = GetEffectiveAcl(this.props.ContainingCollectionDoc?.[DataSym]); + if (collectionAcl === AclAdmin || collectionAcl === AclEdit) moreItems.push({ description: "Close", event: this.deleteClicked, icon: "times" }); !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 3d832636f..561d505e3 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -154,14 +154,16 @@ export enum SharingPermissions { /** * Calculates the effective access right to a document for the current user. */ -export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number): symbol { +export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number, user?: string): symbol { if (!target) return AclPrivate; if (in_prop === UpdatingFromServer || target[UpdatingFromServer]) return AclAdmin; if (target[AclSym] && Object.keys(target[AclSym]).length) { + const userChecked = user || Doc.CurrentUserEmail; + // if the current user is the author of the document / the current user is a member of the admin group - if (Doc.CurrentUserEmail === (target.__fields?.author || target.author) || currentUserGroups.includes("admin")) return AclAdmin; + if (userChecked === (target.__fields?.author || target.author) || currentUserGroups.includes("admin")) return AclAdmin; // if the ACL is being overriden or the property being modified is one of the playground fields (which can be freely modified) if (_overrideAcl || (in_prop && DocServer.PlaygroundFields?.includes(in_prop.toString()))) return AclEdit; @@ -178,7 +180,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) for (const [key, value] of Object.entries(target[AclSym])) { // there are issues with storing fields with . in the name, so they are replaced with _ during creation // as a result we need to restore them again during this comparison. - if (currentUserGroups.includes(key.substring(4)) || Doc.CurrentUserEmail === key.substring(4).replace("_", ".")) { + if (currentUserGroups.includes(key.substring(4).replace("_", ".")) || userChecked === key.substring(4).replace("_", ".")) { if (HierarchyMapping.get(value as symbol)! > HierarchyMapping.get(effectiveAcl)!) { effectiveAcl = value as symbol; if (effectiveAcl === AclAdmin) break; @@ -208,52 +210,53 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); - let changed = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) + let layoutDocChanged = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) + let dataDocChanged = false; const dataDoc = target[DataSym]; // if it is inheriting from a collection, it only inherits if A) the key doesn't already exist or B) the right being inherited is more restrictive if (!inheritingFromCollection || !target[key] || HierarchyMapping.get(StrCast(target[key]))! > HierarchyMapping.get(acl)!) { target[key] = acl; - changed = true; + layoutDocChanged = true; + } + + if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { + dataDoc[key] = acl; + dataDocChanged = true; // maps over the aliases of the document - const aliases = DocListCast(target.aliases); + const aliases = DocListCast(dataDoc.aliases); if (aliases.length) { aliases.map(alias => { alias !== target && distributeAcls(key, acl, alias, inheritingFromCollection); }); } - } - - if (dataDoc && (!inheritingFromCollection || !dataDoc[key] || HierarchyMapping.get(StrCast(dataDoc[key]))! > HierarchyMapping.get(acl)!)) { - dataDoc[key] = acl; - changed = true; - // maps over the children of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { + if (GetEffectiveAcl(d) === AclAdmin && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, d, inheritingFromCollection); } const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { + if (data && GetEffectiveAcl(data) === AclAdmin && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, data, inheritingFromCollection); } }); // maps over the annotations of the document DocListCast(dataDoc[Doc.LayoutFieldKey(dataDoc) + "-annotations"]).map(d => { - if (d.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { + if (GetEffectiveAcl(d) === AclAdmin && (!inheritingFromCollection || !d[key] || HierarchyMapping.get(StrCast(d[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, d, inheritingFromCollection); } const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { + if (data && GetEffectiveAcl(data) === AclAdmin && (!inheritingFromCollection || !data[key] || HierarchyMapping.get(StrCast(data[key]))! > HierarchyMapping.get(acl)!)) { distributeAcls(key, acl, data, inheritingFromCollection); } }); } - changed && fetchProto(target); // updates target[AclSym] when changes to acls have been made + layoutDocChanged && fetchProto(target); // updates target[AclSym] when changes to acls have been made + dataDocChanged && fetchProto(dataDoc); } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", -- cgit v1.2.3-70-g09d2 From 291d2fb28fa878eff190daf813854d9c0477ccb6 Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 14 Aug 2020 17:29:55 -0400 Subject: cleaned up invocation of RichTextMenu --- src/client/util/CurrentUserUtils.ts | 2 +- src/client/views/AntimodeMenu.tsx | 4 ++- src/client/views/DocumentDecorations.tsx | 4 +-- src/client/views/MainView.tsx | 1 - src/client/views/collections/CollectionMenu.tsx | 8 ++--- .../views/collections/CollectionSchemaCells.tsx | 5 ++-- .../collectionFreeForm/FormatShapePane.tsx | 4 +-- .../collectionFreeForm/MarqueeOptionsMenu.tsx | 4 +-- .../views/nodes/formattedText/FormattedTextBox.tsx | 13 +++++---- .../views/nodes/formattedText/RichTextMenu.tsx | 34 +++++++++------------- src/client/views/pdf/PDFMenu.tsx | 4 +-- 11 files changed, 40 insertions(+), 43 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 68d02cd94..bd22b8e9d 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -451,7 +451,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: "Tap to create a document previewer in a new pane, drag for a document previewer", title: "Prev", icon: "expand", click: 'openOnRight(getCopy(this.dragFactory, true))', drag: 'getCopy(this.dragFactory,true)', dragFactory: doc.emptyDocHolder as Doc }, + { toolTip: "Tap to create a document previewer in a new pane, drag for 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" })' }, { toolTip: "Connect a Google Account", title: "Google Account", icon: "external-link-alt", click: 'GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(true)' }, ]; diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx index 68ccefcb5..9f16d0fe1 100644 --- a/src/client/views/AntimodeMenu.tsx +++ b/src/client/views/AntimodeMenu.tsx @@ -1,12 +1,14 @@ import React = require("react"); import { observable, action } from "mobx"; import "./AntimodeMenu.scss"; +export interface AntimodeMenuProps { +} /** * This is an abstract class that serves as the base for a PDF-style or Marquee-style * menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example. */ -export default abstract class AntimodeMenu extends React.Component { +export default abstract class AntimodeMenu extends React.Component { protected _offsetY: number = 0; protected _offsetX: number = 0; protected _mainCont: React.RefObject = React.createRef(); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 03746a1d2..3f16dd7e7 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -659,8 +659,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (bounds.y > bounds.b) { bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight); } - var offset = 0; - let useRotation = seldoc.rootDoc.type === DocumentType.INK; + let offset = 0; + const useRotation = seldoc.rootDoc.type === DocumentType.INK; return (
{this.search} -
{LinkDescriptionPopup.descriptionPopup ? : null} {DocumentLinksButton.EditLink ? : (null)} diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 5119ff6c9..0b3be8739 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -21,7 +21,7 @@ import { CurrentUserUtils } from "../../util/CurrentUserUtils"; import { DragManager } from "../../util/DragManager"; import { SelectionManager } from "../../util/SelectionManager"; import { undoBatch } from "../../util/UndoManager"; -import AntimodeMenu from "../AntimodeMenu"; +import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu"; import { EditableView } from "../EditableView"; import GestureOverlay from "../GestureOverlay"; import { ActiveFillColor, ActiveInkColor, SetActiveArrowEnd, SetActiveArrowStart, SetActiveBezierApprox, SetActiveFillColor, SetActiveInkColor, SetActiveInkWidth } from "../InkingStroke"; @@ -32,13 +32,13 @@ import "./CollectionMenu.scss"; import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView"; @observer -export default class CollectionMenu extends AntimodeMenu { +export default class CollectionMenu extends AntimodeMenu { static Instance: CollectionMenu; @observable SelectedCollection: DocumentView | undefined; @observable FieldKey: string; - constructor(props: Readonly<{}>) { + constructor(props: any) { super(props); this.FieldKey = ""; CollectionMenu.Instance = this; @@ -655,7 +655,7 @@ export class CollectionFreeFormViewChrome extends React.Component : (null) } - {this.isText ? : null} + {this.isText ? : null}
; } } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index 20ce6b76d..11470e940 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -82,9 +82,8 @@ export class CollectionSchemaCell extends React.Component { const doc = Doc.GetProto(this.props.rowProps.original); const aliasdoc = await SearchUtil.GetAliasesOfDocument(doc); if (aliasdoc.length > 0) { - const targetContext = Cast(aliasdoc[0].context, Doc) as Doc; - console.log(StrCast(targetContext.title)); - runInAction(() => this.contents = StrCast(targetContext.title)); + const targetContext = Cast(aliasdoc[0].context, Doc, null); + targetContext && runInAction(() => this.contents = StrCast(targetContext.title)); } } diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx index 1ffa2fbed..a7f44bbbf 100644 --- a/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx +++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.tsx @@ -9,13 +9,13 @@ import { InkField } from "../../../../fields/InkField"; import { BoolCast, Cast, NumCast } from "../../../../fields/Types"; import { DocumentType } from "../../../documents/DocumentTypes"; import { SelectionManager } from "../../../util/SelectionManager"; -import AntimodeMenu from "../../AntimodeMenu"; +import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu"; import "./FormatShapePane.scss"; import { undoBatch } from "../../../util/UndoManager"; import { ColorState, SketchPicker } from 'react-color'; @observer -export default class FormatShapePane extends AntimodeMenu { +export default class FormatShapePane extends AntimodeMenu { static Instance: FormatShapePane; private _lastFill = "#D0021B"; diff --git a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx index f1df7998b..2cfe0183c 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeOptionsMenu.tsx @@ -1,5 +1,5 @@ import React = require("react"); -import AntimodeMenu from "../../AntimodeMenu"; +import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { unimplementedFunction } from "../../../../Utils"; @@ -7,7 +7,7 @@ import { undoBatch } from "../../../util/UndoManager"; import { Tooltip } from "@material-ui/core"; @observer -export default class MarqueeOptionsMenu extends AntimodeMenu { +export default class MarqueeOptionsMenu extends AntimodeMenu { static Instance: MarqueeOptionsMenu; public createCollection: (e: KeyboardEvent | React.PointerEvent | undefined) => void = unimplementedFunction; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 8c05d3603..c31e7469f 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -34,7 +34,7 @@ import { DictationManager } from '../../../util/DictationManager'; import { DragManager } from "../../../util/DragManager"; import { makeTemplate } from '../../../util/DropConverter'; import buildKeymap, { updateBullets } from "./ProsemirrorExampleTransfer"; -import RichTextMenu from './RichTextMenu'; +import RichTextMenu, { RichTextMenuPlugin } from './RichTextMenu'; import { RichTextRules } from "./RichTextRules"; //import { DashDocView } from "./DashDocView"; @@ -1306,7 +1306,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp // jump rich text menu to this textbox const bounds = this._ref.current?.getBoundingClientRect(); - if (bounds && this.layoutDoc._chromeStatus !== "disabled") { + if (bounds && this.layoutDoc._chromeStatus !== "disabled" && RichTextMenu.Instance) { const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width); let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height); if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) { @@ -1410,11 +1410,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp } } + menuPlugin: any; + richTextMenuPlugin() { + const self = this; return new Plugin({ view(newView) { - RichTextMenu.Instance?.changeView(newView); - return RichTextMenu.Instance; + self.props.isSelected(true) && (RichTextMenu.Instance.view = newView); + return self.menuPlugin = new RichTextMenuPlugin({ editorProps: this.props }); } }); } @@ -1524,7 +1527,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1); const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : ""; const interactive = Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground; - setTimeout(() => this._editorView && RichTextMenu.Instance.updateFromDash(this._editorView, undefined, this.props), this.props.isSelected() ? 10 : 0); // need to make sure that we update a text box that is selected after updating the one that was deselected + setTimeout(() => this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props), this.props.isSelected() ? 10 : 0); // need to make sure that we update a text box that is selected after updating the one that was deselected if (!this.props.isSelected() && FormattedTextBoxComment.textBox === this) { setTimeout(() => FormattedTextBoxComment.Hide(), 0); } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index b683fb25d..25b0279ba 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -16,7 +16,7 @@ import { unimplementedFunction, Utils } from "../../../../Utils"; import { DocServer } from "../../../DocServer"; import { LinkManager } from "../../../util/LinkManager"; import { SelectionManager } from "../../../util/SelectionManager"; -import AntimodeMenu from "../../AntimodeMenu"; +import AntimodeMenu, { AntimodeMenuProps } from "../../AntimodeMenu"; import { FieldViewProps } from "../FieldView"; import { FormattedTextBox, FormattedTextBoxProps } from "./FormattedTextBox"; import { updateBullets } from "./ProsemirrorExampleTransfer"; @@ -31,11 +31,11 @@ library.add(faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSup @observer -export default class RichTextMenu extends AntimodeMenu { +export default class RichTextMenu extends AntimodeMenu { static Instance: RichTextMenu; public overMenu: boolean = false; // kind of hacky way to prevent selects not being selectable - private view?: EditorView; + public view?: EditorView; public editorProps: FieldViewProps & FormattedTextBoxProps | undefined; public _brushMap: Map> = new Map(); @@ -156,21 +156,7 @@ export default class RichTextMenu extends AntimodeMenu { public delayHide = () => this._delayHide = true; @action - changeView(view: EditorView) { - if ((view as any)?.TextView?.props.isSelected(true)) { - this.view = view; - } - } - - update(view: EditorView, lastState: EditorState | undefined) { - RichTextMenu.Instance.updateFromDash(view, lastState, this.editorProps); - } - - @action - public async updateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) { - RichTextMenu.Instance.finalUpdateFromDash(view, lastState, props); - } - public async finalUpdateFromDash(view: EditorView, lastState: EditorState | undefined, props: any) { + public updateMenu(view: EditorView, lastState: EditorState | undefined, props: any) { if (!view || !(view as any).TextView?.props.isSelected(true)) { return; } @@ -199,8 +185,7 @@ export default class RichTextMenu extends AntimodeMenu { this.activeHighlightColor = !activeHighlights.length ? "" : activeHighlights.length === 1 ? String(activeHighlights[0]) : "..."; // update link in current selection - const targetTitle = await this.getTextLinkTargetTitle(); - this.setCurrentLink(targetTitle); + this.getTextLinkTargetTitle().then(targetTitle => this.setCurrentLink(targetTitle)); } setMark = (mark: Mark, state: EditorState, dispatch: any, dontToggle: boolean = false) => { @@ -1070,4 +1055,13 @@ export class ButtonDropdown extends React.Component {
); } +} + + +interface RichTextMenuPluginProps { + editorProps: any; +} +export class RichTextMenuPlugin extends React.Component { + render() { return null; } + update(view: EditorView, lastState: EditorState | undefined) { RichTextMenu.Instance?.updateMenu(view, lastState, this.props.editorProps); } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 7bea8d01b..bee282d9b 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -4,14 +4,14 @@ import { observable, action, computed, } from "mobx"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { unimplementedFunction, returnFalse, Utils } from "../../../Utils"; -import AntimodeMenu from "../AntimodeMenu"; +import AntimodeMenu, { AntimodeMenuProps } from "../AntimodeMenu"; import { Doc, Opt } from "../../../fields/Doc"; import { ColorState } from "react-color"; import { ButtonDropdown } from "../nodes/formattedText/RichTextMenu"; @observer -export default class PDFMenu extends AntimodeMenu { +export default class PDFMenu extends AntimodeMenu { static Instance: PDFMenu; private _commentCont = React.createRef(); -- cgit v1.2.3-70-g09d2 From 0ba92fa5742040959a50770a8bc3ec767a44ab66 Mon Sep 17 00:00:00 2001 From: Lionel Han <47760119+IGoByJoe@users.noreply.github.com> Date: Fri, 14 Aug 2020 16:04:09 -0700 Subject: quick fix for mobile --- src/client/util/CurrentUserUtils.ts | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 153118083..02fcac15a 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -684,6 +684,10 @@ export class CurrentUserUtils { }); } + static setupLibrary(userDoc: Doc) { + return CurrentUserUtils.setupWorkspaces(userDoc); + } + // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker. // when clicked, this panel will be displayed in the target container (ie, sidebarContainer) static async setupToolsBtnPanel(doc: Doc) { -- cgit v1.2.3-70-g09d2 From 324f65bcfab0f239ba2cc9a8becd50a8a2572e7f Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 14 Aug 2020 20:13:39 -0400 Subject: tagged mobile docs as system --- src/client/util/CurrentUserUtils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 153118083..3702a2c36 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -668,19 +668,19 @@ export class CurrentUserUtils { } static setupMobileInkingDoc(userDoc: Doc) { - return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white" }); + return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white", system: true }); } static setupMobileUploadDoc(userDoc: Doc) { // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" }) const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", { - title: "Upload Images From the Web", _chromeStatus: "enabled", lockedPosition: true + title: "Upload Images From the Web", _chromeStatus: "enabled", lockedPosition: true, system: true }); const uploadDoc = Docs.Create.StackingDocument([], { - title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true + title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true, system: true }); return Docs.Create.StackingDocument([webDoc, uploadDoc], { - _width: screen.width, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray" + _width: screen.width, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true }); } -- cgit v1.2.3-70-g09d2 From ad095994f7b9bd18da1457c84cec678b4c054a1e Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 14 Aug 2020 20:59:49 -0400 Subject: added system flags to default documents --- src/client/documents/Documents.ts | 4 ++-- src/client/util/CurrentUserUtils.ts | 13 ++++++++----- src/client/views/collections/CollectionTreeView.tsx | 1 + src/client/views/collections/CollectionView.tsx | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src/client/util') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 42ba4d2c4..77f8d3d50 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -442,7 +442,7 @@ export namespace Docs { // whatever options pertain to this specific prototype const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) }; options.layout = layout.view?.LayoutString(layout.dataField); - const doc = Doc.assign(new Doc(prototypeId, true), { layoutKey: "layout", ...options }); + const doc = Doc.assign(new Doc(prototypeId, true), { system: true, layoutKey: "layout", ...options }); doc.layout_keyValue = KeyValueBox.LayoutString(""); return doc; } @@ -1179,7 +1179,7 @@ export namespace DocUtils { found._backgroundColor = enumeration._backgroundColor || found._backgroundColor; found._color = enumeration.color || found._color; } else { - Doc.AddDocToList(options, "data", Docs.Create.TextDocument(enumeration.title, enumeration)); + Doc.AddDocToList(options, "data", Docs.Create.TextDocument(enumeration.title, { ...enumeration, system: true })); } }); return optionsCollection; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index bd22b8e9d..099ca3f4e 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -96,6 +96,7 @@ export class CurrentUserUtils { if (doc["template-button-description"] === undefined) { const descriptionTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _height: 100, system: true }, "header")); // text needs to be a space to allow templateText to be created + descriptionTemplate.system = true; descriptionTemplate[DataSym].layout = "
" + " " + @@ -106,12 +107,13 @@ export class CurrentUserUtils { doc["template-button-description"] = CurrentUserUtils.ficon({ 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" + removeDropProperties: new List(["dropAction"]), title: "description view", icon: "window-maximize", system: true }); } if (doc["template-button-link"] === undefined) { // set _backgroundColor to transparent to prevent link dot from obscuring document it's attached to. const linkTemplate = Doc.MakeDelegate(Docs.Create.TextDocument(" ", { title: "header", _height: 100, system: true }, "header")); // text needs to be a space to allow templateText to be created + linkTemplate.system = true; Doc.GetProto(linkTemplate).layout = "
" + " " + @@ -152,7 +154,7 @@ export class CurrentUserUtils { doc["template-button-link"] = CurrentUserUtils.ficon({ 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" + removeDropProperties: new List(["dropAction"]), title: "link view", icon: "window-maximize", system: true }); } @@ -786,8 +788,8 @@ export class CurrentUserUtils { const sidebarContainer = new Doc(); sidebarContainer._chromeStatus = "disabled"; sidebarContainer.onClick = ScriptField.MakeScript("freezeSidebar()"); + sidebarContainer.system = true; doc.sidebar = new PrefetchProxy(sidebarContainer); - doc.system = true; } return doc.sidebar as Doc; } @@ -853,12 +855,12 @@ export class CurrentUserUtils { // Import sidebar is where shared documents are contained static setupImportSidebar(doc: Doc) { if (doc["sidebar-import-documents"] === undefined) { - doc["sidebar-import-documents"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Imported Documents", forceActive: true, _showTitle: "title", childDropAction: "alias", _autoHeight: true, _yMargin: 30, lockedPosition: true, _chromeStatus: "disabled" })); + doc["sidebar-import-documents"] = new PrefetchProxy(Docs.Create.StackingDocument([], { title: "Imported Documents", forceActive: true, _showTitle: "title", childDropAction: "alias", _autoHeight: true, _yMargin: 30, lockedPosition: true, _chromeStatus: "disabled", system: true })); } if (doc["sidebar-import"] === undefined) { const uploads = Cast(doc["sidebar-import-documents"], Doc, null); const newUpload = CurrentUserUtils.ficon({ onClick: ScriptField.MakeScript("importDocument()"), toolTip: "Import External document", _backgroundColor: "black", title: "Import", icon: "upload", system: true }); - doc["sidebar-import"] = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "Imported Documents", _yMargin: 20, ignoreClick: true, lockedPosition: true })); + doc["sidebar-import"] = new PrefetchProxy(Docs.Create.StackingDocument([newUpload, uploads], { title: "Imported Documents", _yMargin: 20, ignoreClick: true, lockedPosition: true, system: true })); } } @@ -912,6 +914,7 @@ export class CurrentUserUtils { } static async updateUserDocument(doc: Doc) { + doc.system = true; doc.noviceMode = doc.noviceMode === undefined ? "true" : doc.noviceMode; doc.title = Doc.CurrentUserEmail; doc.activeInkPen = doc; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index d096e7d66..f23fa8eb6 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -869,6 +869,7 @@ Scripting.addGlobal(function readFacetData(layoutDoc: Doc, dataDoc: Doc, dataKey }); const facetValueDocSet = (nonNumbers / facetValues.length > .1 ? facetValues.sort() : facetValues.sort((n1: string, n2: string) => Number(n1) - Number(n2))).map(facetValue => { const doc = new Doc(); + doc.system = true; doc.title = facetValue.toString(); doc.treeViewChecked = ComputedField.MakeFunction("determineCheckedState(layoutDoc, facetHeader, facetValue)", {}, { layoutDoc, facetHeader, facetValue }); return doc; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 6dd21ef7f..6bebf8258 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -480,6 +480,7 @@ export class CollectionView extends Touchable Date: Fri, 14 Aug 2020 21:39:18 -0400 Subject: fixed default documents that were missing the 'system' tag. fixed catalog to have default worksapce documents in it. --- src/client/util/CurrentUserUtils.ts | 3 --- src/client/views/DocumentDecorations.tsx | 9 ++++----- src/client/views/MainView.tsx | 8 ++++++-- src/client/views/search/SearchBox.tsx | 7 +++---- src/fields/ScriptField.ts | 1 + 5 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index aff80da75..8931495dc 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -861,9 +861,6 @@ export class CurrentUserUtils { title: "pres element template", backgroundColor: "transparent", _xMargin: 5, _height: 46, isTemplateDoc: true, isTemplateForField: "data", system: true })); } - if (doc.activePresentation === undefined) { - doc.activePresentation = Doc.MakeCopy(doc.emptyPresentation as Doc, true); - } } // Sharing sidebar is where shared documents are contained diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 3f16dd7e7..e546ca858 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -659,7 +659,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (bounds.y > bounds.b) { bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight); } - let offset = 0; const useRotation = seldoc.rootDoc.type === DocumentType.INK; return (
@@ -674,10 +673,10 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
{bounds.r - bounds.x < 15 && bounds.b - bounds.y < 15 ? (null) : <>
{maximizeIcon} {titleArea} diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 5a2488bb6..f7ff895a5 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -254,6 +254,8 @@ export class MainView extends React.Component { @action createNewWorkspace = async (id?: string) => { + const myCatalog = Doc.UserDoc().myCatalog as Doc; + const presentation = Doc.MakeCopy(Doc.UserDoc().emptyPresentation as Doc, true); const workspaces = Cast(this.userDoc.myWorkspaces, Doc) as Doc; const workspaceCount = DocListCast(workspaces.data).length + 1; const freeformOptions: DocumentOptions = { @@ -264,8 +266,10 @@ export class MainView extends React.Component { title: "Untitled Collection", }; const freeformDoc = CurrentUserUtils.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions); - const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [Doc.UserDoc().myCatalog as Doc] }], { title: `Workspace ${workspaceCount}` }, id, "row"); - + const workspaceDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600, path: [myCatalog] }], { title: `Workspace ${workspaceCount}` }, id, "row"); + Doc.AddDocToList(myCatalog, "data", freeformDoc); + Doc.AddDocToList(myCatalog, "data", presentation); + Doc.UserDoc().activePresentation = presentation; const toggleTheme = ScriptField.MakeScript(`self.darkScheme = !self.darkScheme`); const toggleComic = ScriptField.MakeScript(`toggleComicMode()`); const copyWorkspace = ScriptField.MakeScript(`copyWorkspace()`); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 770a03cb1..084449d04 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -604,13 +604,12 @@ export class SearchBox extends ViewBoxBaseComponent `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; // fq: type_t:collection OR {!join from=id to=proto_i}type_t:collection q:text_t:hello - const query = [baseExpr, includeDeleted, includeIcons, typeExpr].join(" AND ").replace(/AND $/, ""); + const query = [baseExpr, includeDeleted, typeExpr].join(" AND ").replace(/AND $/, ""); return query; } diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 9391f56ac..1fb71fefb 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -98,6 +98,7 @@ export class ScriptField extends ObjectField { if (script?.options.capturedVariables) { const doc = Doc.assign(new Doc, script.options.capturedVariables); + doc.system = true; this.captures = new ProxyField(doc); } this.setterscript = setterscript; -- cgit v1.2.3-70-g09d2 From 5ab3b1b20e4d483a0b3113739a6cb7ef88a9b03c Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 14 Aug 2020 22:22:37 -0400 Subject: fixed dragging aliases to remove _stayInColleciton flag. fixed warnings. --- src/client/util/CurrentUserUtils.ts | 5 +++-- src/client/views/MainView.tsx | 6 +++++- src/client/views/collections/CollectionSubView.tsx | 4 ++-- src/client/views/collections/CollectionView.tsx | 4 ++++ src/mobile/MobileInterface.tsx | 14 ++++++++------ 5 files changed, 22 insertions(+), 11 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 8931495dc..2c3a7cb66 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -722,9 +722,9 @@ export class CurrentUserUtils { } } - static setupWorkspaces(doc: Doc) { + static async setupWorkspaces(doc: Doc) { // setup workspaces library item - doc.myWorkspaces === undefined; + await doc.myWorkspaces; if (doc.myWorkspaces === undefined) { doc.myWorkspaces = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "WORKSPACES", _height: 100, forceActive: true, boxShadow: "0 0", lockedPosition: true, treeViewOpen: true, system: true @@ -743,6 +743,7 @@ export class CurrentUserUtils { lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true })) as any as Doc; } + return doc.myWorkspaces as any as Doc; } static setupCatalog(doc: Doc) { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index f7ff895a5..5a9d95aac 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -656,7 +656,11 @@ export class MainView extends React.Component { return !this._flyoutTranslate ? (
) : (null); } - addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); + addButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => { + const ret = flg && Doc.AddDocToList(Doc.UserDoc().dockedBtns as Doc, "data", doc); + ret && (doc._stayInCollection = undefined); + return ret; + }, true) remButtonDoc = (doc: Doc | Doc[]) => (doc instanceof Doc ? [doc] : doc).reduce((flg: boolean, doc) => flg && Doc.RemoveDocFromList(Doc.UserDoc().dockedBtns as Doc, "data", doc), true); moveButtonDoc = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => this.remButtonDoc(doc) && addDocument(doc); diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 3f2ad47a5..075be41fd 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -240,13 +240,13 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: Doc.AreProtosEqual(Cast(movedDocs[0].annotationOn, Doc, null), this.props.Document); added = docDragData.moveDocument(movedDocs, this.props.Document, canAdd ? this.addDocument : returnFalse); } else added = res; - !added && alert("You don't have permission to perform this move"); e.stopPropagation(); } else { ScriptCast(this.props.Document.dropConverter)?.script.run({ dragData: docDragData }); added = this.addDocument(docDragData.droppedDocuments); } - added && e.stopPropagation(); + !added && alert("You cannot perform this move"); + e.stopPropagation(); return added; } else if (de.complete.annoDragData) { diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 6bebf8258..3d2ad7363 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -139,6 +139,9 @@ export class CollectionView extends Touchable Doc.AreProtosEqual(doc, this.props.Document))) return false; const targetDataDoc = this.props.Document[DataSym]; const docList = DocListCast(targetDataDoc[this.props.fieldKey]); const added = docs.filter(d => !docList.includes(d)); @@ -177,6 +180,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx index 02993fdcb..c5e395d2f 100644 --- a/src/mobile/MobileInterface.tsx +++ b/src/mobile/MobileInterface.tsx @@ -50,7 +50,7 @@ library.add(faTasks, faReply, faQuoteLeft, faHandPointLeft, faFolderOpen, faAngl @observer export class MobileInterface extends React.Component { static Instance: MobileInterface; - private _library: Doc = CurrentUserUtils.setupLibrary(Doc.UserDoc()); // to access documents in Dash Web + private _library: Promise; private _mainDoc: any = CurrentUserUtils.setupActiveMobileMenu(Doc.UserDoc()); @observable private _sidebarActive: boolean = false; //to toggle sidebar display @observable private _imageUploadActive: boolean = false; //to toggle image upload @@ -67,6 +67,7 @@ export class MobileInterface extends React.Component { constructor(props: Readonly<{}>) { super(props); + this._library = CurrentUserUtils.setupLibrary(Doc.UserDoc()); // to access documents in Dash Web MobileInterface.Instance = this; } @@ -123,7 +124,7 @@ export class MobileInterface extends React.Component { * Method called when 'Library' button is pressed on the home screen */ switchToLibrary = async () => { - this.switchCurrentView(this._library); + this._library.then(library => this.switchCurrentView(library)); runInAction(() => this._homeMenu = false); this.toggleSidebar(); } @@ -138,7 +139,7 @@ export class MobileInterface extends React.Component { // Case 1: Parent document is 'workspaces' if (doc === Cast(this._library, Doc) as Doc) { this._child = null; - this.switchCurrentView(this._library); + this._library.then(library => this.switchCurrentView(library)); // Case 2: Parent document is the 'home' menu (root node) } else if (doc === Cast(this._homeDoc, Doc) as Doc) { this._homeMenu = true; @@ -177,7 +178,7 @@ export class MobileInterface extends React.Component { @action returnMain = () => { this._parents = [this._homeDoc]; - this.switchCurrentView(this._library); + this._library.then(library => this.switchCurrentView(library)); this._homeMenu = false; this._child = null; } @@ -286,8 +287,9 @@ export class MobileInterface extends React.Component { // Handles when user clicks on a document in the pathbar @action - handlePathClick = (doc: Doc, index: number) => { - if (doc === this._library) { + handlePathClick = async (doc: Doc, index: number) => { + const library = await this._library; + if (doc === library) { this._child = null; this.switchCurrentView(doc); this._parents.length = index; -- cgit v1.2.3-70-g09d2 From e7fd28e27e7389c67c22410ed1a3ff313556a153 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Sat, 15 Aug 2020 19:20:52 +0530 Subject: more alias stuff --- src/client/util/SharingManager.tsx | 4 ++-- src/client/views/collections/collectionFreeForm/PropertiesView.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 9d79188a3..30935c5dd 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -165,7 +165,7 @@ export default class SharingManager extends React.Component<{}> { users.forEach(({ user, notificationDoc }) => { if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); // add the target to the notificationDoc if it hasn't already been added - else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf((target.aliasOf as Doc || target), DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, (target.aliasOf as Doc || target)); // remove the target from the list if it already exists }); } @@ -235,7 +235,7 @@ export default class SharingManager extends React.Component<{}> { GetEffectiveAcl(target) === AclAdmin && distributeAcls(ACL, permission as SharingPermissions, target); if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); - else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); + else GetEffectiveAcl(target, undefined, user.email) === AclPrivate && Doc.IndexOf((target.aliasOf as Doc || target), DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, (target.aliasOf as Doc || target)); } diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 5c1ec1280..5b58d0ef4 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -403,7 +403,7 @@ export class PropertiesView extends React.Component { // }) // shifts the current user, owner, public to the top of the doc. - tableEntries.unshift(this.sharingItem("Public", effectiveAcl, AclMap.get(this.selectedDoc![AclSym]["ACL-Public"])!)) + tableEntries.unshift(this.sharingItem("Public", effectiveAcl, (AclMap.get(this.selectedDoc![AclSym]?.["ACL-Public"]) || SharingPermissions.None))); tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); -- cgit v1.2.3-70-g09d2 From e9f8804a68327c64e1ade13081cab0b3b6c0ce21 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sat, 15 Aug 2020 16:02:22 -0400 Subject: fixes for search -- need to rethink how to get a sortable string field (removed _s suffix for now). --- solr-8.3.1/server/solr/dash/conf/schema.xml | 7 ++++--- src/client/documents/Documents.ts | 1 + src/client/util/CurrentUserUtils.ts | 18 +++++++++--------- src/client/views/search/SearchBox.tsx | 6 +++--- src/server/Search.ts | 6 ++---- 5 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src/client/util') diff --git a/solr-8.3.1/server/solr/dash/conf/schema.xml b/solr-8.3.1/server/solr/dash/conf/schema.xml index a0496444b..4f6ae57b2 100644 --- a/solr-8.3.1/server/solr/dash/conf/schema.xml +++ b/solr-8.3.1/server/solr/dash/conf/schema.xml @@ -1,6 +1,7 @@ id + @@ -49,18 +50,18 @@ - + - + - + diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 77f8d3d50..e69c53260 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -185,6 +185,7 @@ export interface DocumentOptions { targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script searchFileTypes?: List; // file types allowed in a search query strokeWidth?: number; + cloneFieldFilter?: List; // fields not to copy when the document is cloned _stayInCollection?: boolean;// whether the document should remain in its collection when someone tries to drag and drop it elsewhere treeViewPreventOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expand/collapse state to be independent of other views of the same document in the tree view treeViewHideTitle?: boolean; // whether to hide the title of a tree view diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 2c3a7cb66..d77ac8fe9 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -398,36 +398,36 @@ export class CurrentUserUtils { } if (doc.emptyCollection === undefined) { doc.emptyCollection = Docs.Create.FreeformDocument([], - { _nativeWidth: undefined, _nativeHeight: undefined, _width: 150, _height: 100, title: "freeform", system: true }); + { _nativeWidth: undefined, _nativeHeight: undefined, _width: 150, _height: 100, title: "freeform", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyPane === undefined) { - doc.emptyPane = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, title: "Untitled Collection", system: true }); + doc.emptyPane = Docs.Create.FreeformDocument([], { _nativeWidth: undefined, _nativeHeight: undefined, title: "Untitled Collection", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyComparison === undefined) { - doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true }); + doc.emptyComparison = Docs.Create.ComparisonDocument({ title: "compare", _width: 300, _height: 300, system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyScript === undefined) { - doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script", system: true }); + doc.emptyScript = Docs.Create.ScriptingDocument(undefined, { _width: 200, _height: 250, title: "script", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyScreenshot === undefined) { - doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot", system: true }); + doc.emptyScreenshot = Docs.Create.ScreenshotDocument("", { _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyAudio === undefined) { - doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "ready to record audio", system: true }); + doc.emptyAudio = Docs.Create.AudioDocument(nullAudio, { _width: 200, title: "ready to record audio", system: true, cloneFieldFilter: new List(["system"]) }); } 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", system: true }); } if (doc.emptyButton === undefined) { - doc.emptyButton = Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title: "Button", system: true }); + doc.emptyButton = Docs.Create.ButtonDocument({ _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title: "Button", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyDocHolder === undefined) { doc.emptyDocHolder = Docs.Create.DocumentDocument( ComputedField.MakeFunction("selectedDocs(this,this.excludeCollections,[_last_])?.[0]") as any, - { _width: 250, _height: 250, title: "container", system: true }); + { _width: 250, _height: 250, title: "container", system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.emptyWebpage === undefined) { - doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, _nativeHeight: 962, _width: 400, UseCors: true, system: true }); + doc.emptyWebpage = Docs.Create.WebDocument("", { title: "webpage", _nativeWidth: 850, _nativeHeight: 962, _width: 400, UseCors: true, system: true, cloneFieldFilter: new List(["system"]) }); } if (doc.activeMobileMenu === undefined) { this.setupActiveMobileMenu(doc); diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index dbc30eeb6..99db78778 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -337,7 +337,7 @@ export class SearchBox extends ViewBoxBaseComponent `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; + const typeExpr = !types ? "" : `(type_t:* OR {!join from=id to=proto_i}type_t:*) ${types.map(type => `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; // fq: type_t:collection OR {!join from=id to=proto_i}type_t:collection q:text_t:hello const query = [baseExpr, includeDeleted, typeExpr].join(" AND ").replace(/AND $/, ""); return query; @@ -625,7 +625,7 @@ export class SearchBox extends ViewBoxBaseComponent { // happens at the beginning - this.realTotalResults = res.numFound; + this.realTotalResults = res.numFound <= 0 ? 0 : res.numFound; if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { this._numTotalResults = res.numFound; } diff --git a/src/server/Search.ts b/src/server/Search.ts index decd1f5b1..3869867cd 100644 --- a/src/server/Search.ts +++ b/src/server/Search.ts @@ -7,11 +7,10 @@ export namespace Search { export async function updateDocument(document: any) { try { - const res = await rp.post(pathTo("update"), { + return await rp.post(pathTo("update"), { headers: { 'content-type': 'application/json' }, body: JSON.stringify([document]) }); - return res; } catch (e) { // console.warn("Search error: " + e + document); } @@ -19,11 +18,10 @@ export namespace Search { export async function updateDocuments(documents: any[]) { try { - const res = await rp.post(pathTo("update"), { + return await rp.post(pathTo("update"), { headers: { 'content-type': 'application/json' }, body: JSON.stringify(documents) }); - return res; } catch (e) { // console.warn("Search error: ", e, documents); } -- cgit v1.2.3-70-g09d2 From ab45fb958e7dfd5828715249b7e2099d8df42592 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 16 Aug 2020 00:35:12 -0400 Subject: changed sidebar buttons to not 'stayincollection' but to 'alias' on drop to allow them to be copied easily to other button panels. --- src/client/util/CurrentUserUtils.ts | 3 ++- src/client/views/nodes/formattedText/FormattedTextBox.tsx | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d77ac8fe9..647efeec0 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -538,7 +538,8 @@ export class CurrentUserUtils { iconShape: "square", title, _backgroundColor: "black", - _stayInCollection: true, + dropAction: "alias", + removeDropProperties: new List(["dropAction"]), childDropAction: "same", _width: 60, _height: 60, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 54d79f4b8..9ac3ea847 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -408,8 +408,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp const lastSel = Math.min(flattened.length - 1, this._searchIndex); flattened.forEach((h: TextSelection, ind: number) => tr = tr.addMark(h.from, h.to, ind === lastSel ? activeMark : mark)); flattened[lastSel] && this._editorView.dispatch(tr.setSelection(new TextSelection(tr.doc.resolve(flattened[lastSel].from), tr.doc.resolve(flattened[lastSel].to))).scrollIntoView()); - - console.log(this._searchIndex); } } -- cgit v1.2.3-70-g09d2 From a248e49ddbabe1947a3883bba47e786e22e1158a Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 17 Aug 2020 16:21:12 +0530 Subject: added layoutdoc toggles --- src/client/util/SharingManager.scss | 21 +++++++++- src/client/util/SharingManager.tsx | 46 +++++++++++++--------- .../collectionFreeForm/PropertiesView.scss | 14 +++++++ .../collectionFreeForm/PropertiesView.tsx | 26 ++++++++---- 4 files changed, 79 insertions(+), 28 deletions(-) (limited to 'src/client/util') diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index 7912db74d..42c300712 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -62,6 +62,7 @@ input { height: 10px; + cursor: pointer; } label { @@ -69,11 +70,29 @@ font-style: italic; } } + + .layoutDoc-acls { + display: flex; + flex-direction: column; + float: right; + margin-right: 12; + margin-top: -15; + align-items: center; + + label { + font-weight: normal; + font-style: italic; + } + + input { + cursor: pointer; + } + } } .main-container { display: flex; - margin-top: -10px; + margin-top: -25px; .individual-container, .group-container { diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 30935c5dd..5a863c813 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -1,7 +1,7 @@ import { observable, runInAction, action } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; -import { Doc, Opt, AclAdmin, AclPrivate, DocListCast } from "../../fields/Doc"; +import { Doc, Opt, AclAdmin, AclPrivate, DocListCast, DataSym } from "../../fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../fields/Types"; import * as RequestPromise from "request-promise"; @@ -25,7 +25,6 @@ import { library } from "@fortawesome/fontawesome-svg-core"; library.add(fa.faInfoCircle, fa.faCaretUp, fa.faCaretRight, fa.faCaretDown); - export interface User { email: string; userDocumentId: string; @@ -47,6 +46,8 @@ interface GroupedOptions { const indType = "!indType/"; const groupType = "!groupType/"; +const storage = "data"; + /** * A user who also has a notificationDoc. */ @@ -55,7 +56,6 @@ interface ValidatedUser { notificationDoc: Doc; } -const storage = "data"; @observer export default class SharingManager extends React.Component<{}> { @@ -75,7 +75,8 @@ export default class SharingManager extends React.Component<{}> { // if both showUserOptions and showGroupOptions are false then both are displayed @observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component) @observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component) - private populating: boolean = false; + private populating: boolean = false; // whether the list of users is populating or not + @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used // private get linkVisible() { // return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false; @@ -176,7 +177,6 @@ export default class SharingManager extends React.Component<{}> { */ shareWithAddedMember = (group: Doc, emailId: string) => { const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!; - if (group.docsShared) DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc)); } @@ -184,9 +184,12 @@ export default class SharingManager extends React.Component<{}> { * Called from the properties sidebar to change permissions of a user. */ shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, target: Doc) => { - const user = this.users.find(({ user: { email } }) => email === (shareWith === "Me" ? Doc.CurrentUserEmail : shareWith)); - if (user) this.setInternalSharing(user, permission, target); - else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, target); + if (shareWith !== "Public") { + const user = this.users.find(({ user: { email } }) => email === (shareWith === "Me" ? Doc.CurrentUserEmail : shareWith)); + if (user) this.setInternalSharing(user, permission, target); + else this.setInternalGroupSharing(GroupManager.Instance.getGroup(shareWith)!, permission, target); + } + else if (GetEffectiveAcl(target) === AclAdmin) distributeAcls("ACL-Public", permission, target); } /** @@ -370,8 +373,8 @@ export default class SharingManager extends React.Component<{}> { * @returns the main interface of the SharingManager. */ private get sharingInterface() { - const groupList = GroupManager.Instance?.getAllGroups() || []; + const groupList = GroupManager.Instance?.getAllGroups() || []; const sortedUsers = this.users.slice().sort(this.sortUsers) .map(({ user: { email } }) => ({ label: email, value: indType + email })); const sortedGroups = groupList.slice().sort(this.sortGroups) @@ -404,17 +407,19 @@ 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 users = this.individualSort === "ascending" ? this.users.slice().sort(this.sortUsers) : this.individualSort === "descending" ? this.users.slice().sort(this.sortUsers).reverse() : this.users; + const groups = this.groupSort === "ascending" ? groupList.slice().sort(this.sortGroups) : this.groupSort === "descending" ? groupList.slice().sort(this.sortGroups).reverse() : groupList; - const effectiveAcl = this.targetDoc ? GetEffectiveAcl(this.targetDoc) : AclPrivate; + const targetDoc = this.layoutDocAcls ? this.targetDoc : this.targetDoc?.[DataSym]; + + const effectiveAcl = targetDoc ? GetEffectiveAcl(targetDoc) : AclPrivate; // the list of users shared with const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { const userKey = user.email.replace('.', '_'); - const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`]); + const permissions = StrCast(targetDoc?.[`ACL-${userKey}`]); - return !permissions || user.email === this.targetDoc?.author ? null : ( + return !permissions || user.email === targetDoc?.author ? (null) : (
{ key={"owner"} className={"container"} > - {this.targetDoc?.author === Doc.CurrentUserEmail ? "Me" : this.targetDoc?.author} + {targetDoc?.author === Doc.CurrentUserEmail ? "Me" : targetDoc?.author}
Owner @@ -454,7 +459,7 @@ export default class SharingManager extends React.Component<{}> {
), - this.targetDoc?.author !== Doc.CurrentUserEmail ? + targetDoc?.author !== Doc.CurrentUserEmail ? (
{ Me
- {this.targetDoc?.[`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]} + {targetDoc?.[`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`]}
@@ -472,7 +477,7 @@ export default class SharingManager extends React.Component<{}> { // the list of groups shared with const groupListContents = groups.map(group => { - const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`]); + const permissions = StrCast(targetDoc?.[`ACL-${StrCast(group.groupName)}`]); return !permissions ? null : (
{
*/}
-

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

+

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

@@ -569,6 +574,9 @@ export default class SharingManager extends React.Component<{}> { this.showUserOptions = !this.showUserOptions)} /> this.showGroupOptions = !this.showGroupOptions)} />
+
+ this.layoutDocAcls = !this.layoutDocAcls)} checked={this.layoutDocAcls} /> +
}
diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.scss b/src/client/views/collections/collectionFreeForm/PropertiesView.scss index ddaca7d42..535581f2e 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.scss +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.scss @@ -121,6 +121,19 @@ padding: 10px; margin-left: 5px; + .propertiesView-acls-checkbox { + float: right; + height: 20px; + margin-top: -20px; + margin-right: -15; + + .propertiesView-acls-checkbox-text { + font-size: 7px; + margin-top: -10px; + margin-left: 6px; + } + } + .change-buttons { display: flex; @@ -259,6 +272,7 @@ background-color: #ececec; max-height: 130px; overflow-y: scroll; + width: 92%; .propertiesView-sharingTable-item { diff --git a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx index 5b58d0ef4..85a1d7137 100644 --- a/src/client/views/collections/collectionFreeForm/PropertiesView.tsx +++ b/src/client/views/collections/collectionFreeForm/PropertiesView.tsx @@ -2,7 +2,7 @@ import React = require("react"); import { observer } from "mobx-react"; import "./PropertiesView.scss"; import { observable, action, computed, runInAction } from "mobx"; -import { Doc, Field, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt, DocCastAsync } from "../../../../fields/Doc"; +import { Doc, Field, WidthSym, HeightSym, AclSym, AclPrivate, AclReadonly, AclAddonly, AclEdit, AclAdmin, Opt, DocCastAsync, DataSym } from "../../../../fields/Doc"; import { ComputedField } from "../../../../fields/ScriptField"; import { EditableView } from "../../EditableView"; import { KeyValueBox } from "../../nodes/KeyValueBox"; @@ -73,6 +73,7 @@ export class PropertiesView extends React.Component { @observable openTransform: boolean = true; // @observable selectedUser: string = ""; // @observable addButtonPressed: boolean = false; + @observable layoutDocAcls: boolean = false; //Pres Trails booleans: @observable openPresTransitions: boolean = false; @@ -386,11 +387,12 @@ export class PropertiesView extends React.Component { const tableEntries = []; // DocCastAsync(Doc.UserDoc().sidebarUsersDisplayed).then(sidebarUsersDisplayed => { - if (this.selectedDoc![AclSym]) { - for (const [key, value] of Object.entries(this.selectedDoc![AclSym])) { + const target = this.layoutDocAcls ? this.selectedDoc! : this.selectedDoc![DataSym]; + if (target[AclSym]) { + for (const [key, value] of Object.entries(target[AclSym])) { const name = key.substring(4).replace("_", "."); - if (name !== Doc.CurrentUserEmail && name !== this.selectedDoc!.author && name !== "Public"/* && sidebarUsersDisplayed![name] !== false*/) { - tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value)!)); + if (name !== Doc.CurrentUserEmail && name !== target.author && name !== "Public"/* && sidebarUsersDisplayed![name] !== false*/) { + tableEntries.push(this.sharingItem(name, effectiveAcl, AclMap.get(value as symbol)!)); } } } @@ -403,9 +405,9 @@ export class PropertiesView extends React.Component { // }) // shifts the current user, owner, public to the top of the doc. - tableEntries.unshift(this.sharingItem("Public", effectiveAcl, (AclMap.get(this.selectedDoc![AclSym]?.["ACL-Public"]) || SharingPermissions.None))); - tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === this.selectedDoc!.author ? "Owner" : AclMap.get(effectiveAcl)!)); - if (Doc.CurrentUserEmail !== this.selectedDoc!.author) tableEntries.unshift(this.sharingItem(StrCast(this.selectedDoc!.author), effectiveAcl, "Owner")); + tableEntries.unshift(this.sharingItem("Public", effectiveAcl, (AclMap.get(target[AclSym]?.["ACL-Public"]) || SharingPermissions.None))); + tableEntries.unshift(this.sharingItem("Me", effectiveAcl, Doc.CurrentUserEmail === target.author ? "Owner" : AclMap.get(effectiveAcl)!)); + if (Doc.CurrentUserEmail !== target.author) tableEntries.unshift(this.sharingItem(StrCast(target.author), effectiveAcl, "Owner")); return
{tableEntries} @@ -867,6 +869,14 @@ export class PropertiesView extends React.Component {
{!this.openSharing ? (null) :
+
+ this.layoutDocAcls = !this.layoutDocAcls)} + checked={this.layoutDocAcls} + />; +
Layout
+
{this.sharingTable} {/*
// ); const positions = []; - let cfield = ComputedField.WithoutComputed(() => FieldValue(props.Document[props.fieldKey])); + let cfield = props.Document[props.fieldKey]; this.type = props.fieldKey; if (StrCast(this.props.Document._searchString).toLowerCase() !== "") { let term = Field.toString(cfield as Field); diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index a4b689e2f..be25bf9de 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -496,7 +496,6 @@ export class KeysDropdown extends React.Component { get ignoreFields() { return ["_docFilters", "_docRangeFilters"]; } @computed get scriptField() { - console.log("we kinda made it"); const scriptText = "setDocFilter(containingTreeView, heading, this.title, checked)"; const script = ScriptField.MakeScript(scriptText, { this: Doc.name, heading: "string", checked: "string", containingTreeView: Doc.name }); return script ? () => script : undefined; @@ -507,7 +506,7 @@ export class KeysDropdown extends React.Component { render() { return (
- { this.props.openHeader(this.props.col, e.clientX, e.clientY); }} icon={this.props.icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px", cursor: "hand" }} /> + { this.props.openHeader(this.props.col, e.clientX, e.clientY); e.stopPropagation(); }} icon={this.props.icon} size="lg" style={{ display: "inline", paddingBottom: "1px", paddingTop: "4px", cursor: "hand" }} /> {/* { runInAction(() => { this._isOpen === undefined ? this._isOpen = true : this._isOpen = !this._isOpen }) diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 6f8fb53ec..abaee0e16 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -328,7 +328,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action openHeader = (col: any, screenx: number, screeny: number) => { this._col = col; - this._headerOpen = !this._headerOpen; + this._headerOpen = true; this._pointerX = screenx; this._pointerY = screeny; } @@ -360,7 +360,6 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { @action onHeaderClick = (e: React.PointerEvent) => { - this.props.active(true); e.stopPropagation(); } @@ -499,6 +498,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { documentKeys={this.documentKeys} headerIsEditing={this._headerIsEditing} openHeader={this.openHeader} + onClick={e => { e.stopPropagation(); this.closeHeader(); }} onPointerDown={this.onTablePointerDown} onResizedChange={this.onResizedChange} setColumns={this.setColumns} @@ -527,8 +527,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (e.button === 0 && !e.altKey && !e.ctrlKey && !e.metaKey && this.props.isSelected(true)) { e.stopPropagation(); } - this._pointerY = e.screenY; - this._pointerX = e.screenX; + // this.closeHeader(); } onResizedChange = (newResized: Resize[], event: any) => { @@ -581,6 +580,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { if (this.props.Document._searchDoc !== undefined) { name = "collectionSchemaView-searchContainer"; } + if (!this.props.active()) setTimeout(() => this.closeHeader(), 0); TraceMobx(); const menuContent = this.renderMenuContent; const menu =
doc) { onPointerDown={e => this.onHeaderClick(e)} style={{ position: "fixed", background: "white", border: "black 1px solid", - transform: `translate(${(this.menuCoordinates[0] / this.scale)}px, ${(this.menuCoordinates[1] / this.scale)}px)` + transform: `translate(${(this.menuCoordinates[0])}px, ${(this.menuCoordinates[1])}px)` }}> { const dim = this.props.ScreenToLocalTransform().inverse().transformDirection(r.offset.width, r.offset.height); @@ -614,7 +614,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
{this.dividerDragger} {!this.previewWidth() ? (null) : this.previewPanel} - {this._headerOpen ? menu : null} + {this._headerOpen && this.props.active() ? menu : null}
; } } \ No newline at end of file diff --git a/src/client/views/collections/SchemaTable.tsx b/src/client/views/collections/SchemaTable.tsx index 7324dd6df..763e5a410 100644 --- a/src/client/views/collections/SchemaTable.tsx +++ b/src/client/views/collections/SchemaTable.tsx @@ -75,6 +75,7 @@ export interface SchemaTableProps { documentKeys: any[]; headerIsEditing: boolean; openHeader: (column: any, screenx: number, screeny: number) => void; + onClick: (e: React.MouseEvent) => void; onPointerDown: (e: React.PointerEvent) => void; onResizedChange: (newResized: Resize[], event: any) => void; setColumns: (columns: SchemaHeaderField[]) => void; @@ -230,7 +231,7 @@ export class SchemaTable extends React.Component { return { Header: , - accessor: (doc: Doc) => doc ? doc[col.heading] : 0, + accessor: (doc: Doc) => doc ? Field.toString(doc[col.heading] as Field) : 0, id: col.heading, Cell: (rowProps: CellInfo) => { const rowIndex = rowProps.index; @@ -322,7 +323,7 @@ export class SchemaTable extends React.Component { this.props.Document._schemaHeaders = new List(newSchemaHeaders); } else if (this.props.Document._schemaHeaders === undefined) { this.props.Document._schemaHeaders = new List([new SchemaHeaderField("title", "#f1efeb"), new SchemaHeaderField("author", "#f1efeb"), new SchemaHeaderField("*lastModified", "#f1efeb"), - new SchemaHeaderField("text", "#f1efeb"), new SchemaHeaderField("type", "#f1efeb"), new SchemaHeaderField("context", "#f1efeb")]); + new SchemaHeaderField("text", "#f1efeb"), new SchemaHeaderField("type", "#f1efeb"), new SchemaHeaderField("context", "#f1efeb", ColumnType.Doc)]); } } @@ -598,7 +599,7 @@ export class SchemaTable extends React.Component { render() { const preview = ""; return
this.props.active(true) && e.stopPropagation()} + onPointerDown={this.props.onPointerDown} onClick={this.props.onClick} onWheel={e => this.props.active(true) && e.stopPropagation()} onDrop={e => this.props.onDrop(e, {})} onContextMenu={this.onContextMenu} > {this.reactTable} {StrCast(this.props.Document.type) !== "search" ?
this.createRow()}>+ new
diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 99db78778..07f1485c3 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -239,6 +239,7 @@ export class SearchBox extends ViewBoxBaseComponent `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; + const typeExpr = this._onlyAliases ? "NOT {!join from=id to=proto_i}type_t:*" : `(type_t:* OR {!join from=id to=proto_i}type_t:*) ${types.map(type => `NOT ({!join from=id to=proto_i}type_t:${type}) AND NOT type_t:${type}`).join(" AND ")}`; // fq: type_t:collection OR {!join from=id to=proto_i}type_t:collection q:text_t:hello const query = [baseExpr, includeDeleted, typeExpr].join(" AND ").replace(/AND $/, ""); return query; @@ -623,7 +624,7 @@ export class SearchBox extends ViewBoxBaseComponent { while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - this._curRequest = SearchUtil.Search(query, true, { fq: this.filterQuery, start: this._maxSearchIndex, rows: this.NumResults, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, fq: this.filterQuery, start: this._maxSearchIndex, rows: this.NumResults, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { // happens at the beginning this.realTotalResults = res.numFound <= 0 ? 0 : res.numFound; if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { @@ -633,7 +634,7 @@ export class SearchBox extends ViewBoxBaseComponent highlighting[doc[Id]]); const lines = new Map(); res.docs.map((doc, i) => lines.set(doc[Id], res.lines[i])); - const docs = await Promise.all(res.docs.map(async doc => (await Cast(doc.extendsDoc, Doc)) || doc)); + const docs = res.docs; const highlights: typeof res.highlighting = {}; docs.forEach((doc, index) => highlights[doc[Id]] = highlightList[index]); const filteredDocs = this.filterDocsByType(docs); @@ -877,7 +878,7 @@ export class SearchBox extends ViewBoxBaseComponent + style={{ padding: 1, paddingLeft: 20, paddingRight: 60, color: "black", height: 20, width: 250 }} />
drag search results as collection
}> -- cgit v1.2.3-70-g09d2 From ab89ef62d3f11c11f3f6e7162ca0e112bac1517e Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 17 Aug 2020 15:55:17 -0400 Subject: added sort to solr search options. removed delete field assignment when removing Documents. Allowed ToScriptScript and ToString to go through regardless of ACLs --- solr-8.3.1/server/solr/dash/conf/schema.xml | 2 +- src/client/util/SearchUtil.ts | 3 ++- src/client/views/DocComponent.tsx | 1 - src/client/views/collections/CollectionSchemaCells.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 1 - src/client/views/search/SearchBox.tsx | 17 +++++++++++++++-- src/fields/Doc.ts | 16 +++++----------- src/fields/util.ts | 4 ++-- 8 files changed, 26 insertions(+), 20 deletions(-) (limited to 'src/client/util') diff --git a/solr-8.3.1/server/solr/dash/conf/schema.xml b/solr-8.3.1/server/solr/dash/conf/schema.xml index 4f6ae57b2..74c4b494c 100644 --- a/solr-8.3.1/server/solr/dash/conf/schema.xml +++ b/solr-8.3.1/server/solr/dash/conf/schema.xml @@ -51,7 +51,7 @@ - + diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 6dafbd58e..ce96ab67b 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -28,6 +28,7 @@ export namespace SearchUtil { start?: number; rows?: number; fq?: string; + sort?: string; allowAliases?: boolean; onlyAliases?: boolean; "facet"?: string; @@ -42,7 +43,7 @@ export namespace SearchUtil { if (options.onlyAliases) { replacedQuery = `{!join from=id to=proto_i}DEFAULT:${replacedQuery}`; } - const gotten = await rp.get(rpquery, { qs: { ...options, sort: "lastModified_d desc", q: replacedQuery } }); + const gotten = await rp.get(rpquery, { qs: { ...options, q: replacedQuery } }); const result: IdSearchResult = gotten.startsWith("<") ? { ids: [], docs: [], numFound: 0, lines: [] } : JSON.parse(gotten); if (!returnDocs) { return result; diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 8c8bb6fde..23ce71c4f 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -135,7 +135,6 @@ export function ViewBoxAnnotatableComponent

{ Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey + "-annotations", doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - doc.deleted = true; }); return true; } diff --git a/src/client/views/collections/CollectionSchemaCells.tsx b/src/client/views/collections/CollectionSchemaCells.tsx index d46aa3574..fa4d8c51b 100644 --- a/src/client/views/collections/CollectionSchemaCells.tsx +++ b/src/client/views/collections/CollectionSchemaCells.tsx @@ -297,7 +297,7 @@ export class CollectionSchemaCell extends React.Component { let cfield = props.Document[props.fieldKey]; this.type = props.fieldKey; if (StrCast(this.props.Document._searchString).toLowerCase() !== "") { - let term = Field.toString(cfield as Field); + let term = (cfield instanceof Promise) ? "...promise pending..." : Field.toString(cfield as Field); term = term.toLowerCase(); const search = StrCast(this.props.Document._searchString).toLowerCase(); let start = term.indexOf(search); diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 9d305145e..2064b0be4 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -208,7 +208,6 @@ export class CollectionView extends Touchable { Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc); recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - doc.deleted = true; }); return true; } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 07f1485c3..847bda137 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -4,7 +4,7 @@ import { action, computed, observable, runInAction, reaction, IReactionDisposer import { observer } from 'mobx-react'; import * as React from 'react'; import * as rp from 'request-promise'; -import { Doc, DocListCast } from '../../../fields/Doc'; +import { Doc, DocListCast, Opt } from '../../../fields/Doc'; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from '../../../fields/FieldSymbols'; import { List } from '../../../fields/List'; @@ -24,6 +24,7 @@ import { ViewBoxBaseComponent } from "../DocComponent"; import { DocumentView } from '../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; +import { ColumnType } from "../collections/CollectionSchemaView"; export const searchSchema = createSchema({ id: "string", @@ -616,6 +617,18 @@ export class SearchBox extends ViewBoxBaseComponent { + switch (type) { + case ColumnType.Date: return "_d"; + case ColumnType.String: return "_t"; + case ColumnType.Boolean: return "_b"; + case ColumnType.Number: return "_n"; + } + } + const headers = Cast(this.props.Document._schemaHeaders, listSpec(SchemaHeaderField), []); + return headers.reduce((p: Opt, header: SchemaHeaderField) => p || (header.desc !== undefined && suffixMap(header.type) ? (header.heading + suffixMap(header.type) + (header.desc ? " desc" : " asc")) : undefined), undefined); + } private NumResults = 50; private lockPromise?: Promise; getResults = async (query: string) => { @@ -624,7 +637,7 @@ export class SearchBox extends ViewBoxBaseComponent { while (this._results.length <= this._endIndex && (this._numTotalResults === -1 || this._maxSearchIndex < this._numTotalResults)) { - this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, fq: this.filterQuery, start: this._maxSearchIndex, rows: this.NumResults, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { + this._curRequest = SearchUtil.Search(query, true, { onlyAliases: true, allowAliases: true, sort: this.primarySort, fq: this.filterQuery, start: 0, rows: this.NumResults, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { // happens at the beginning this.realTotalResults = res.numFound <= 0 ? 0 : res.numFound; if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5f5fe98bc..0dcb8ab42 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -195,6 +195,8 @@ export class Doc extends RefField { @observable private ___fieldKeys: any = {}; + @observable + public [AclSym]: { [key: string]: symbol }; private [UpdatingFromServer]: boolean = false; @@ -204,17 +206,9 @@ export class Doc extends RefField { private [Self] = this; private [SelfProxy]: any; - public [FieldsSym] = (clear?: boolean) => { - if (clear) { - this.___fields = {}; - this.___fieldKeys = {}; - } - return this.___fields; - } - @observable - public [AclSym]: { [key: string]: symbol }; - public [WidthSym] = () => NumCast(this[SelfProxy]._width); - public [HeightSym] = () => NumCast(this[SelfProxy]._height); + public [FieldsSym](clear?: boolean) { return clear ? this.___fields = this.___fieldKeys = {} : this.___fields; } + public [WidthSym]() { return NumCast(this[SelfProxy]._width); } + public [HeightSym]() { return NumCast(this[SelfProxy]._height); } public [ToScriptString]() { return `DOC-"${this[Self][Id]}"-`; } public [ToString]() { return `Doc(${GetEffectiveAcl(this) === AclPrivate ? "-inaccessible-" : this.title})`; } public get [LayoutSym]() { return this[SelfProxy].__LAYOUT__; } diff --git a/src/fields/util.ts b/src/fields/util.ts index 3d832636f..e3d9ed2ef 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -5,7 +5,7 @@ import { ProxyField, PrefetchProxy } from "./Proxy"; import { RefField } from "./RefField"; import { ObjectField } from "./ObjectField"; import { action, trace } from "mobx"; -import { Parent, OnUpdate, Update, Id, SelfProxy, Self, HandleUpdate } from "./FieldSymbols"; +import { Parent, OnUpdate, Update, Id, SelfProxy, Self, HandleUpdate, ToString, ToScriptString } from "./FieldSymbols"; import { DocServer } from "../client/DocServer"; import { ComputedField } from "./ScriptField"; import { ScriptCast, StrCast } from "./Types"; @@ -286,7 +286,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an export function getter(target: any, in_prop: string | symbol | number, receiver: any): any { let prop = in_prop; - if (in_prop === FieldsSym || in_prop === Id || in_prop === HandleUpdate || in_prop === CachedUpdates) return target.__fields[prop] || target[prop]; + if (in_prop === ToString || in_prop === ToScriptString || in_prop === FieldsSym || in_prop === Id || in_prop === HandleUpdate || in_prop === CachedUpdates) return target.__fields[prop] || target[prop]; if (in_prop === AclSym) return _overrideAcl ? undefined : target[AclSym]; if (GetEffectiveAcl(target) === AclPrivate && !_overrideAcl) return prop === HeightSym || prop === WidthSym ? returnZero : undefined; if (prop === LayoutSym) { -- cgit v1.2.3-70-g09d2