From 2fb042f575626cc6f938eec57c8e71e45ff6b1d5 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 29 Jul 2020 23:30:20 +0530 Subject: anyone can share without setting acls + fixed some inheriting stuff + deleting stuff + some cleanup --- src/client/views/DocComponent.tsx | 18 ++--- src/client/views/DocumentDecorations.tsx | 27 ++++--- src/client/views/collections/CollectionView.tsx | 34 ++++---- src/client/views/nodes/DocumentView.tsx | 100 ------------------------ src/client/views/nodes/TaskCompletedBox.tsx | 2 - 5 files changed, 44 insertions(+), 137 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 9fd406407..ae180a78b 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -154,15 +154,15 @@ export function ViewBoxAnnotatableComponent

{ - const dataDoc = d[DataSym]; - dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; - for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - dataDoc[key] = d[key] = this.AclMap.get(value); - } - }); - } + // if (this.props.Document[AclSym]) { + // added.forEach(d => { + // const dataDoc = d[DataSym]; + // dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; + // for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + // dataDoc[key] = d[key] = this.AclMap.get(value); + // } + // }); + // } if (effectiveAcl === AclAddonly) { added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 8d63537e7..655f330e3 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -1,9 +1,9 @@ import { IconProp, library } from '@fortawesome/fontawesome-svg-core'; import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote, faTextHeight, faArrowAltCircleDown, faArrowAltCircleUp, faCheckCircle, faCloudUploadAlt, faLink, faShare, faStopCircle, faSyncAlt, faTag, faTimes, faAngleLeft, faAngleRight, faAngleDoubleLeft, faAngleDoubleRight, faPause } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable, reaction, runInAction } from "mobx"; +import { action, computed, observable, reaction, runInAction, get } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DataSym, Field, WidthSym, HeightSym } from "../../fields/Doc"; +import { Doc, DataSym, Field, WidthSym, HeightSym, AclEdit, AclAdmin } from "../../fields/Doc"; import { Document } from '../../fields/documentSchemas'; import { ScriptField } from '../../fields/ScriptField'; import { Cast, StrCast, NumCast } from "../../fields/Types"; @@ -23,6 +23,9 @@ import { SnappingManager } from '../util/SnappingManager'; import { HtmlField } from '../../fields/HtmlField'; import { InkData, InkField, InkTool } from "../../fields/InkField"; import { Tooltip } from '@material-ui/core'; +import { GetEffectiveAcl } from '../../fields/util'; +import { DocumentIcon } from './nodes/DocumentIcon'; +import { render } from 'react-dom'; library.add(faCaretUp); library.add(faObjectGroup); @@ -193,8 +196,11 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> SelectionManager.DeselectAll(); selected.map(dv => { - recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true); - dv.props.removeDocument?.(dv.props.Document); + const effectiveAcl = GetEffectiveAcl(dv.props.Document); + if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { // deletes whatever you have the right to delete + recent && Doc.AddDocToList(recent, "data", dv.props.Document, undefined, true, true); + dv.props.removeDocument?.(dv.props.Document); + } }); } } @@ -545,17 +551,18 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 2 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } + const canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.Document)).some(permission => permission === AclAdmin || permission === AclEdit); const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? (

Show context menu
} placement="top">
-
) : ( -
Delete
} placement="top"> -
- {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} - -
); + ) : canDelete ? ( +
Delete
} placement="top"> +
+ {/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} + +
) : null; const titleArea = this._edtingTitle ? <> diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a82c91383..3bb1022e0 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,7 +17,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, distributeAcls, SharingPermissions } from '../../../fields/util'; +import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../../fields/util'; import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -149,16 +149,16 @@ export class CollectionView extends Touchable { - // const dataDoc = d[DataSym]; - for (const [key, value] of Object.entries(this.props.Document[AclSym])) { - distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); - } - // dataDoc[AclSym] = d[AclSym] = this.props.Document[AclSym]; - }); - } + // if (this.props.Document[AclSym]) { + // // change so it only adds if more restrictive + // added.forEach(d => { + // // const dataDoc = d[DataSym]; + // for (const [key, value] of Object.entries(this.props.Document[AclSym])) { + // // key.substring(4).replace("_", ".") !== Doc.CurrentUserEmail && distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); + // distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); + // } + // }); + // } if (effectiveAcl === AclAddonly) { added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); @@ -192,14 +192,16 @@ export class CollectionView extends Touchable { - const effectiveAcl = GetEffectiveAcl(this.props.Document); - if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin || getPlaygroundMode()) { + const collectionEffectiveAcl = GetEffectiveAcl(this.props.Document); + const docEffectiveAcl = GetEffectiveAcl(doc); + // you can remove the document if you either have Admin/Edit access to the collection or to the specific document + if (collectionEffectiveAcl === AclEdit || collectionEffectiveAcl === AclAdmin || docEffectiveAcl === AclAdmin || docEffectiveAcl === AclEdit || getPlaygroundMode()) { const docs = doc instanceof Doc ? [doc] : doc as Doc[]; const targetDataDoc = this.props.Document[DataSym]; const value = DocListCast(targetDataDoc[this.props.fieldKey]); - const result = value.filter(v => !docs.includes(v)); - if (result.length !== value.length) { - targetDataDoc[this.props.fieldKey] = new List(result); + const toRemove = value.filter(v => docs.includes(v)); + if (toRemove.length !== 0) { + toRemove.forEach(doc => Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc)); return true; } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b59875a7e..1d89f3d24 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -697,35 +697,6 @@ export class DocumentView extends DocComponent(Docu this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true; } - @undoBatch - @action - setAcl = (acl: SharingPermissions) => { - this.dataDoc.ACL = this.props.Document.ACL = acl; - DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail) d.ACL = acl; - const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail) data.ACL = acl; - }); - } - - @undoBatch - @action - testAcl = (acl: SharingPermissions) => { - this.dataDoc.author = this.props.Document.author = "ADMIN"; - this.dataDoc.ACL = this.props.Document.ACL = acl; - DocListCast(this.dataDoc[Doc.LayoutFieldKey(this.dataDoc)]).map(d => { - if (d.author === Doc.CurrentUserEmail) { - d.author = "ADMIN"; - d.ACL = acl; - } - const data = d[DataSym]; - if (data && data.author === Doc.CurrentUserEmail) { - data.author = "ADMIN"; - data.ACL = acl; - } - }); - } - @action onContextMenu = async (e: React.MouseEvent | Touch): Promise => { // the touch onContextMenu is button 0, the pointer onContextMenu is button 2 @@ -791,11 +762,6 @@ export class DocumentView extends DocComponent(Docu moreItems.push({ description: "Download document", icon: "download", event: async () => { Doc.Zip(this.props.Document); - // const a = document.createElement("a"); - // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`); - // a.href = url; - // a.download = `DocExport-${this.props.Document[Id]}.zip`; - // a.click(); } }); if (!Doc.UserDoc().noviceMode) { @@ -822,72 +788,6 @@ export class DocumentView extends DocComponent(Docu helpItems.push({ description: "Print Document in Console", event: () => console.log(this.props.Document), icon: "hand-point-right" }); cm.addItem({ description: "Help...", noexpand: true, subitems: helpItems, icon: "question" }); - // const existingAcls = cm.findByDescription("Privacy..."); - // const aclItems: ContextMenuProps[] = existingAcls && "subitems" in existingAcls ? existingAcls.subitems : []; - // aclItems.push({ description: "Make Add Only", event: () => this.setAcl(SharingPermissions.Add), icon: "concierge-bell" }); - // aclItems.push({ description: "Make Read Only", event: () => this.setAcl(SharingPermissions.View), icon: "concierge-bell" }); - // aclItems.push({ description: "Make Private", event: () => this.setAcl(SharingPermissions.None), icon: "concierge-bell" }); - // aclItems.push({ description: "Make Editable", event: () => this.setAcl(SharingPermissions.Edit), icon: "concierge-bell" }); - // aclItems.push({ description: "Test Private", event: () => this.testAcl(SharingPermissions.None), icon: "concierge-bell" }); - // aclItems.push({ description: "Test Readonly", event: () => this.testAcl(SharingPermissions.View), icon: "concierge-bell" }); - // !existingAcls && cm.addItem({ description: "Privacy...", subitems: aclItems, icon: "question" }); - - // cm.addItem({ description: `${getPlaygroundMode() ? "Disable" : "Enable"} playground mode`, event: togglePlaygroundMode, icon: "concierge-bell" }); - - // const recommender_subitems: ContextMenuProps[] = []; - - // recommender_subitems.push({ - // description: "Internal recommendations", - // event: () => this.recommender(), - // icon: "brain" - // }); - - // const ext_recommender_subitems: ContextMenuProps[] = []; - - // ext_recommender_subitems.push({ - // description: "arXiv", - // event: () => this.externalRecommendation("arxiv"), - // icon: "brain" - // }); - // ext_recommender_subitems.push({ - // description: "Bing", - // event: () => this.externalRecommendation("bing"), - // icon: "brain" - // }); - - // recommender_subitems.push({ - // description: "External recommendations", - // subitems: ext_recommender_subitems, - // icon: "brain" - // }); - - - //moreItems.push({ description: "Recommender System", subitems: recommender_subitems, icon: "brain" }); - //moreItems.push({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" }); - //moreItems.push({ description: "Undo Debug Test", event: () => UndoManager.TraceOpenBatches(), icon: "exclamation" }); - - // runInAction(() => { - // const setWriteMode = (mode: DocServer.WriteMode) => { - // DocServer.AclsMode = mode; - // const mode1 = mode; - // const mode2 = mode === DocServer.WriteMode.Default ? mode : DocServer.WriteMode.Playground; - // DocServer.setFieldWriteMode("x", mode1); - // DocServer.setFieldWriteMode("y", mode1); - // DocServer.setFieldWriteMode("_width", mode1); - // DocServer.setFieldWriteMode("_height", mode1); - - // DocServer.setFieldWriteMode("_panX", mode2); - // DocServer.setFieldWriteMode("_panY", mode2); - // DocServer.setFieldWriteMode("scale", mode2); - // DocServer.setFieldWriteMode("_viewType", mode2); - // }; - // const aclsMenu: ContextMenuProps[] = []; - // aclsMenu.push({ description: "Default (write/read all)", event: () => setWriteMode(DocServer.WriteMode.Default), icon: DocServer.AclsMode === DocServer.WriteMode.Default ? "check" : "exclamation" }); - // aclsMenu.push({ description: "Playground (write own/no read)", event: () => setWriteMode(DocServer.WriteMode.Playground), icon: DocServer.AclsMode === DocServer.WriteMode.Playground ? "check" : "exclamation" }); - // aclsMenu.push({ description: "Live Playground (write own/read others)", event: () => setWriteMode(DocServer.WriteMode.LivePlayground), icon: DocServer.AclsMode === DocServer.WriteMode.LivePlayground ? "check" : "exclamation" }); - // aclsMenu.push({ description: "Live Readonly (no write/read others)", event: () => setWriteMode(DocServer.WriteMode.LiveReadonly), icon: DocServer.AclsMode === DocServer.WriteMode.LiveReadonly ? "check" : "exclamation" }); - // cm.addItem({ description: "Collaboration ...", subitems: aclsMenu, icon: "share" }); - // }); runInAction(() => { if (!this.topMost && !(e instanceof Touch)) { // DocumentViews should stop propagation of this event diff --git a/src/client/views/nodes/TaskCompletedBox.tsx b/src/client/views/nodes/TaskCompletedBox.tsx index 89602f219..2a3dd8d2d 100644 --- a/src/client/views/nodes/TaskCompletedBox.tsx +++ b/src/client/views/nodes/TaskCompletedBox.tsx @@ -1,7 +1,5 @@ import React = require("react"); import { observer } from "mobx-react"; -import { documentSchema } from "../../../fields/documentSchemas"; -import { makeInterface } from "../../../fields/Schema"; import "./TaskCompletedBox.scss"; import { observable, action } from "mobx"; import { Fade } from "@material-ui/core"; -- cgit v1.2.3-70-g09d2 From f3f51bb4933cada9ae83594912db10d88082be24 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 30 Jul 2020 10:53:21 -0400 Subject: made 'floatin' document API cleaner. fixed interactions with draggin blue dots off and link lines to link documents. removed Recommndations UI stuff. changed treeView to avoid "No, no, no" error warnin when tryin to render promises --- src/client/documents/DocumentTypes.ts | 1 - src/client/documents/Documents.ts | 9 - src/client/views/DocumentDecorations.tsx | 2 +- src/client/views/GlobalKeyHandler.ts | 1 - src/client/views/RecommendationsBox.scss | 69 ------- src/client/views/RecommendationsBox.tsx | 201 --------------------- src/client/views/TemplateMenu.tsx | 6 +- src/client/views/collections/CollectionMenu.tsx | 2 +- src/client/views/collections/CollectionSubView.tsx | 2 +- .../views/collections/CollectionTreeView.tsx | 4 +- src/client/views/nodes/DocumentContentsView.tsx | 3 +- src/client/views/nodes/DocumentView.tsx | 33 ++-- src/client/views/nodes/LinkAnchorBox.tsx | 4 +- 13 files changed, 30 insertions(+), 307 deletions(-) delete mode 100644 src/client/views/RecommendationsBox.scss delete mode 100644 src/client/views/RecommendationsBox.tsx (limited to 'src/client/views') diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 7578b7df0..985fcce11 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -36,6 +36,5 @@ export enum DocumentType { LINKDB = "linkdb", // database of links ??? why do we have this SCRIPTDB = "scriptdb", // database of scripts - RECOMMENDATION = "recommendation", // view of a recommendation GROUPDB = "groupdb" // database of groups } \ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7e094089f..984d43e32 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -45,7 +45,6 @@ import { SliderBox } from "../views/nodes/SliderBox"; import { VideoBox } from "../views/nodes/VideoBox"; import { WebBox } from "../views/nodes/WebBox"; import { PresElementBox } from "../views/presentationview/PresElementBox"; -import { RecommendationsBox } from "../views/RecommendationsBox"; import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; import { Networking } from "../Network"; @@ -301,10 +300,6 @@ export namespace Docs { layout: { view: FontIconBox, dataField: defaultDataKey }, options: { _width: 40, _height: 40, borderRounding: "100%" }, }], - [DocumentType.RECOMMENDATION, { - layout: { view: RecommendationsBox, dataField: defaultDataKey }, - options: { _width: 200, _height: 200 }, - }], [DocumentType.WEBCAM, { layout: { view: DashWebRTCVideo, dataField: defaultDataKey } }], @@ -805,10 +800,6 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List(), options); } - export function RecommendationsDocument(data: Doc[], options: DocumentOptions = {}) { - return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List(data), options); - } - export type DocConfig = { doc: Doc, initialWidth?: number, diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 190dbc8c3..51325ae1b 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -89,7 +89,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> const transform = (documentView.props.ScreenToLocalTransform().scale(documentView.props.ContentScaling())).inverse(); var [sptX, sptY] = transform.transformPoint(0, 0); let [bptX, bptY] = transform.transformPoint(documentView.props.PanelWidth(), documentView.props.PanelHeight()); - if (StrCast(Doc.Layout(documentView.props.Document).layout).includes("LinkAnchorBox")) { + if (documentView.props.LayoutTemplateString?.includes("LinkAnchorBox")) { const docuBox = documentView.ContentDiv.getElementsByClassName("linkAnchorBox-cont"); if (docuBox.length) { const rect = docuBox[0].getBoundingClientRect(); diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 086085db5..c9f95a538 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -105,7 +105,6 @@ export default class KeyManager { } doDeselect && SelectionManager.DeselectAll(); DictationManager.Controls.stop(); - // RecommendationsBox.Instance.closeMenu(); GoogleAuthenticationManager.Instance.cancel(); HypothesisAuthenticationManager.Instance.cancel(); SharingManager.Instance.close(); diff --git a/src/client/views/RecommendationsBox.scss b/src/client/views/RecommendationsBox.scss deleted file mode 100644 index 7d89042a4..000000000 --- a/src/client/views/RecommendationsBox.scss +++ /dev/null @@ -1,69 +0,0 @@ -@import "globalCssVariables"; - -.rec-content *{ - display: inline-block; - margin: auto; - width: 50; - height: 150px; - border: 1px dashed grey; - padding: 10px 10px; -} - -.rec-content { - float: left; - width: inherit; - align-content: center; -} - -.rec-scroll { - overflow-y: scroll; - overflow-x: hidden; - position: absolute; - pointer-events: all; - // display: flex; - z-index: 10000; - box-shadow: gray 0.2vw 0.2vw 0.4vw; - // flex-direction: column; - background: whitesmoke; - padding-bottom: 10px; - padding-top: 20px; - // border-radius: 15px; - border: solid #BBBBBBBB 1px; - width: 100%; - text-align: center; - // max-height: 250px; - height: 100%; - text-transform: uppercase; - color: grey; - letter-spacing: 2px; -} - -.content { - padding: 10px; - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} - -.image-background { - pointer-events: none; - background-color: transparent; - width: 50%; - text-align: center; - margin-left: 5px; -} - -// bcz: UGH!! Can't have global settings like this!!! -// img{ -// width: 100%; -// height: 100%; -// } - -.score { - // margin-left: 15px; - width: 50%; - height: 100%; - text-align: center; - margin-left: 10px; -} diff --git a/src/client/views/RecommendationsBox.tsx b/src/client/views/RecommendationsBox.tsx deleted file mode 100644 index 196151e32..000000000 --- a/src/client/views/RecommendationsBox.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, computed, runInAction } from "mobx"; -import Measure from "react-measure"; -import "./RecommendationsBox.scss"; -import { Doc, DocListCast, WidthSym, HeightSym } from "../../fields/Doc"; -import { DocumentIcon } from "./nodes/DocumentIcon"; -import { StrCast, NumCast } from "../../fields/Types"; -import { returnFalse, emptyFunction, returnEmptyString, returnOne, emptyPath, returnZero, returnEmptyFilter } from "../../Utils"; -import { Transform } from "../util/Transform"; -import { ObjectField } from "../../fields/ObjectField"; -import { DocumentView } from "./nodes/DocumentView"; -import { DocumentType } from '../documents/DocumentTypes'; -import { ClientRecommender } from "../ClientRecommender"; -import { DocServer } from "../DocServer"; -import { Id } from "../../fields/FieldSymbols"; -import { FieldView, FieldViewProps } from "./nodes/FieldView"; -import { DocumentManager } from "../util/DocumentManager"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { library } from "@fortawesome/fontawesome-svg-core"; -import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; -import { DocUtils } from "../documents/Documents"; - -export interface RecProps { - documents: { preview: Doc, similarity: number }[]; - node: Doc; -} - -library.add(faBullseye, faLink); - -@observer -export class RecommendationsBox extends React.Component { - - public static LayoutString(fieldKey: string) { return FieldView.LayoutString(RecommendationsBox, fieldKey); } - - // @observable private _display: boolean = false; - @observable private _pageX: number = 0; - @observable private _pageY: number = 0; - @observable private _width: number = 0; - @observable private _height: number = 0; - @observable.shallow private _docViews: JSX.Element[] = []; - // @observable private _documents: { preview: Doc, score: number }[] = []; - private previewDocs: Doc[] = []; - - constructor(props: FieldViewProps) { - super(props); - } - - @action - private DocumentIcon(doc: Doc) { - const layoutresult = StrCast(doc.type); - let renderDoc = doc; - //let box: number[] = []; - if (layoutresult.indexOf(DocumentType.COL) !== -1) { - renderDoc = Doc.MakeDelegate(renderDoc); - } - const returnXDimension = () => 150; - const returnYDimension = () => 150; - const scale = () => returnXDimension() / NumCast(renderDoc._nativeWidth, returnXDimension()); - //let scale = () => 1; - const newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt - newRenderDoc.height = NumCast(this.props.Document.documentIconHeight); - newRenderDoc.autoHeight = false; - const docview =
- -
; - return docview; - - } - - // @action - // closeMenu = () => { - // this._display = false; - // this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id])); - // this.previewDocs = []; - // } - - // @action - // resetDocuments = () => { - // this._documents = []; - // } - - // @action - // displayRecommendations(x: number, y: number) { - // this._pageX = x; - // this._pageY = y; - // this._display = true; - // } - - static readonly buffer = 20; - - // get pageX() { - // const x = this._pageX; - // if (x < 0) { - // return 0; - // } - // const width = this._width; - // if (x + width > window.innerWidth - RecommendationsBox.buffer) { - // return window.innerWidth - RecommendationsBox.buffer - width; - // } - // return x; - // } - - // get pageY() { - // const y = this._pageY; - // if (y < 0) { - // return 0; - // } - // const height = this._height; - // if (y + height > window.innerHeight - RecommendationsBox.buffer) { - // return window.innerHeight - RecommendationsBox.buffer - height; - // } - // return y; - // } - - // get createDocViews() { - // return DocListCast(this.props.Document.data).map(doc => { - // return ( - //
- // - // {this.DocumentIcon(doc)} - // - // {NumCast(doc.score).toFixed(4)} - //
DocumentManager.Instance.jumpToDocument(doc, false)}> - // - //
- //
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}> - // - //
- //
- // ); - // }); - // } - - componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set - runInAction(() => { - if (this._docViews.length === 0) { - this._docViews = DocListCast(this.props.Document.data).map(doc => { - return ( -
- - {this.DocumentIcon(doc)} - - {NumCast(doc.score).toFixed(4)} -
DocumentManager.Instance.jumpToDocument(doc, false)}> - -
-
DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "Recommender", "", undefined)}> - -
-
- ); - }); - } - }); - } - - render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered. - // if (!this._display) { - // return null; - // } - // let style = { left: this.pageX, top: this.pageY }; - //const transform = "translate(" + (NumCast(this.props.node.x) + 350) + "px, " + NumCast(this.props.node.y) + "px" - let title = StrCast((this.props.Document.sourceDoc as Doc).title); - if (title.length > 15) { - title = title.substring(0, 15) + "..."; - } - return ( -
-

Recommendations for "{title}"

- {this._docViews} -
- ); - } - // - // -} \ No newline at end of file diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 9fb8a227e..ebaf2cfcb 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -64,11 +64,7 @@ export class TemplateMenu extends React.Component { } toggleFloat = (e: React.ChangeEvent): void => { - SelectionManager.DeselectAll(); - const topDocView = this.props.docViews[0]; - const ex = e.target.getBoundingClientRect().left; - const ey = e.target.getBoundingClientRect().top; - DocumentView.FloatDoc(topDocView, ex, ey); + DocumentView.FloatDoc(this.props.docViews[0]); } toggleAudio = (e: React.ChangeEvent): void => { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index d6cb79e9c..8813861d2 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -313,7 +313,7 @@ export class CollectionViewBaseChrome extends React.Component
{this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.viewModes} - {this.props.type === CollectionViewType.Invalid || this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome} + {this.props.type === CollectionViewType.Docking ? (null) : this.templateChrome}
- {!this.props.isOverlay ? (null) : + {} + + {!this.props.isOverlay || this.document.type !== DocumentType.WEB ? (null) :
+ + {this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? (null) : } {this.subChrome} @@ -541,13 +548,6 @@ export class CollectionFreeFormViewChrome extends React.Component - {} - {!this.props.isOverlay || this.document.type !== DocumentType.WEB ? (null) : ; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index c792df882..954b62332 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -4,7 +4,7 @@ const pdfjs = require('pdfjs-dist/es5/build/pdf.js'); import * as Pdfjs from "pdfjs-dist"; import "pdfjs-dist/web/pdf_viewer.css"; import { Dictionary } from "typescript-collections"; -import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym } from "../../../fields/Doc"; +import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; @@ -13,7 +13,7 @@ import { createSchema, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; -import { TraceMobx } from "../../../fields/util"; +import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; @@ -565,9 +565,13 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && this.props.addDocument?.(annotationDoc); - return annotationDoc; + const effectiveAcl = GetEffectiveAcl(this.props.Document); + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + const annotationDoc = this.makeAnnotationDocument(color); + annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); + return annotationDoc; + } + return undefined; } /** -- cgit v1.2.3-70-g09d2 From 19c0ca86ed6ff8d8644125fa119270fc79e0afc9 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 13:59:04 +0530 Subject: integrated playgroundmode into geteffectiveacl, still some issues with deleting docs --- src/client/views/DocComponent.tsx | 8 ++++---- src/client/views/collections/CollectionView.tsx | 10 +++++----- .../views/collections/collectionFreeForm/MarqueeView.tsx | 4 ++-- src/client/views/nodes/WebBox.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 4 ++-- src/fields/util.ts | 6 +----- 6 files changed, 16 insertions(+), 20 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 3bcf4b922..804c7a8d4 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -7,7 +7,7 @@ import { InteractionUtils } from '../util/InteractionUtils'; import { List } from '../../fields/List'; import { DateField } from '../../fields/DateField'; import { ScriptField } from '../../fields/ScriptField'; -import { GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../fields/util'; +import { GetEffectiveAcl, SharingPermissions } from '../../fields/util'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -150,7 +150,7 @@ export function ViewBoxAnnotatableComponent

Doc.AddDocToList(targetDataDoc, this.annotationKey, doc)); } else { added.map(doc => doc.context = this.props.Document); (targetDataDoc[this.annotationKey] as List).push(...added); - if (!getPlaygroundMode()) targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.annotationKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 5262c8b46..7e7ea6786 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -17,7 +17,7 @@ import { listSpec } from '../../../fields/Schema'; import { ComputedField, ScriptField } from '../../../fields/ScriptField'; import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../fields/Types'; import { ImageField } from '../../../fields/URLField'; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode, SharingPermissions } from '../../../fields/util'; +import { TraceMobx, GetEffectiveAcl, SharingPermissions } from '../../../fields/util'; import { emptyFunction, emptyPath, returnEmptyFilter, returnFalse, returnOne, returnZero, setupMoveUpEvents, Utils } from '../../../Utils'; import { Docs, DocUtils } from '../../documents/Documents'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -142,7 +142,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc)); } else { @@ -181,7 +181,7 @@ export class CollectionView extends Touchable Doc.AddDocToList(Cast(Doc.UserDoc().myCatalog, Doc, null), "data", add)); // targetDataDoc[this.props.fieldKey] = new List([...docList, ...added]); (targetDataDoc[this.props.fieldKey] as List).push(...added); - if (!getPlaygroundMode()) targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); + targetDataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())); } } } @@ -193,7 +193,7 @@ export class CollectionView extends Touchable { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); return annotationDoc; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 954b62332..59fa6b08c 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -13,7 +13,7 @@ import { createSchema, makeInterface } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { Cast, NumCast } from "../../../fields/Types"; import { PdfField } from "../../../fields/URLField"; -import { TraceMobx, GetEffectiveAcl, getPlaygroundMode } from "../../../fields/util"; +import { TraceMobx, GetEffectiveAcl } from "../../../fields/util"; import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, emptyPath, intersectRect, returnZero, smoothScroll, Utils } from "../../../Utils"; import { Docs, DocUtils } from "../../documents/Documents"; import { DocumentType } from "../../documents/DocumentTypes"; @@ -566,7 +566,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) || getPlaygroundMode()) { + if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { const annotationDoc = this.makeAnnotationDocument(color); annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); return annotationDoc; diff --git a/src/fields/util.ts b/src/fields/util.ts index 048b66b53..500daf0c7 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -122,10 +122,6 @@ export function togglePlaygroundMode() { playgroundMode = !playgroundMode; } -export function getPlaygroundMode() { - return playgroundMode; -} - // the list of groups that the current user is a member of let currentUserGroups: string[] = []; @@ -188,7 +184,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } } - return effectiveAcl; + return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; } -- cgit v1.2.3-70-g09d2 From 5d50404b127560d525cab4645fcd3b07367ef5a2 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 31 Jul 2020 16:19:46 +0530 Subject: comments --- src/client/util/GroupManager.tsx | 37 +++++++++++++------------------------ src/client/util/SharingManager.tsx | 8 ++++++-- src/client/views/MainViewModal.tsx | 2 +- src/fields/util.ts | 7 +++++-- 4 files changed, 25 insertions(+), 29 deletions(-) (limited to 'src/client/views') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index a0db9a421..5215ea35f 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -38,8 +38,8 @@ export default class GroupManager extends React.Component<{}> { @observable currentGroup: Opt; // the currently selected group. @observable private createGroupModalOpen: boolean = false; private inputRef: React.RefObject = React.createRef(); // the ref for the input box. - private createGroupButtonRef: React.RefObject = React.createRef(); - private currentUserGroups: string[] = []; + private createGroupButtonRef: React.RefObject = React.createRef(); // the ref for the group creation button + private currentUserGroups: string[] = []; // the list of groups the current user is a member of @observable private buttonColour: "#979797" | "black" = "#979797"; @observable private groupSort: "ascending" | "descending" | "none" = "none"; @@ -50,6 +50,9 @@ export default class GroupManager extends React.Component<{}> { GroupManager.Instance = this; } + /** + * Populates the list of users and groups. + */ componentDidMount() { this.populateUsers(); this.populateGroups(); @@ -63,8 +66,6 @@ export default class GroupManager extends React.Component<{}> { const userList = await RequestPromise.get(Utils.prepend("/getUsers")); const raw = JSON.parse(userList) as User[]; const evaluating = raw.map(async user => { - // const isCandidate = user.email !== Doc.CurrentUserEmail; - // if (isCandidate) { const userDocument = await DocServer.GetRefField(user.userDocumentId); if (userDocument instanceof Doc) { const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc); @@ -74,11 +75,13 @@ export default class GroupManager extends React.Component<{}> { } }); } - // } }); return Promise.all(evaluating); } + /** + * Populates the list of groups the current user is a member of and sets this list to be used in the GetEffectiveAcl in util.ts + */ populateGroups = () => { DocListCastAsync(this.GroupManagerDoc?.data).then(groups => { groups?.forEach(group => { @@ -146,25 +149,8 @@ export default class GroupManager extends React.Component<{}> { } /** - * @returns a readonly copy of a single group document + * Returns an array of the list of members of a given group. */ - getGroupCopy(groupName: string): Doc | undefined { - const groupDoc = this.getGroup(groupName); - if (groupDoc) { - const { members, owners } = groupDoc; - return Doc.assign(new Doc, { groupName, members: StrCast(members), owners: StrCast(owners) }); - } - return undefined; - } - /** - * @returns a readonly copy of the list of group documents - */ - getAllGroupsCopy(): Doc[] { - return this.getAllGroups().map(({ groupName, owners, members }) => - Doc.assign(new Doc, { groupName: (StrCast(groupName)), owners: (StrCast(owners)), members: (StrCast(members)) }) - ); - } - getGroupMembers(group: string | Doc): string[] { if (group instanceof Doc) return JSON.parse(StrCast(group.members)) as string[]; else return JSON.parse(StrCast(this.getGroup(group)!.members)) as string[]; @@ -317,6 +303,9 @@ export default class GroupManager extends React.Component<{}> { } + /** + * @returns the MainViewModal which allows the user to create groups. + */ private get groupCreationModal() { const contents = (

@@ -416,7 +405,7 @@ export default class GroupManager extends React.Component<{}> {
this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}> - Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""} {/* → */} + Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""}
{groups.map(group => diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 4ab4a3c42..64dc491ed 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -81,13 +81,14 @@ export default class SharingManager extends React.Component<{}> { public open = (target: DocumentView) => { runInAction(() => this.users = []); // SelectionManager.DeselectAll(); - this.populateUsers().then(action(() => { + this.populateUsers(); + runInAction(() => { this.targetDocView = target; this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; this.permissions = SharingPermissions.Edit; - })); + }); } @@ -108,6 +109,9 @@ export default class SharingManager extends React.Component<{}> { SharingManager.Instance = this; } + /** + * Populates the list of users. + */ componentDidMount() { this.populateUsers(); } diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx index 249715511..66ea2dbf8 100644 --- a/src/client/views/MainViewModal.tsx +++ b/src/client/views/MainViewModal.tsx @@ -10,7 +10,7 @@ export interface MainViewOverlayProps { overlayStyle?: React.CSSProperties; dialogueBoxDisplayedOpacity?: number; overlayDisplayedOpacity?: number; - closeOnExternalClick?: () => void; + closeOnExternalClick?: () => void; // the close method of a MainViewModal, triggered if there is a click on the overlay (closing the modal) } @observer diff --git a/src/fields/util.ts b/src/fields/util.ts index 500daf0c7..16517f25f 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -184,6 +184,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) } } } + // if we're in playground mode, return AclEdit (or AclAdmin if that's the user's effectiveAcl) return playgroundMode && HierarchyMapping.get(effectiveAcl)! < 3 ? AclEdit : effectiveAcl; } return AclAdmin; @@ -194,6 +195,7 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) * @param acl the access right being stored (e.g. "Can Edit") * @param target the document on which this access right is being set * @param inheritingFromCollection whether the target is being assigned rights after being dragged into a collection (and so is inheriting the ACLs from the collection) + * inheritingFromCollection is not currently being used but could be used if ACL assignment defaults change */ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc, inheritingFromCollection?: boolean) { @@ -205,7 +207,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc ["Admin", 4] ]); - let changed = false; + let changed = false; // determines whether fetchProto should be called or not (i.e. is there a change that should be reflected in target[AclSym]) 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 @@ -241,7 +243,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc }); } - changed && fetchProto(target); // updates aclsym when changes to acls have been made + changed && fetchProto(target); // updates target[AclSym] when changes to acls have been made } const layoutProps = ["panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "fitWidth", "fitToBox", @@ -251,6 +253,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an const effectiveAcl = GetEffectiveAcl(target, in_prop); if (effectiveAcl !== AclEdit && effectiveAcl !== AclAdmin) return true; + // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === "string" && prop.startsWith("ACL") && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value))) return true; // if (typeof prop === "string" && prop.startsWith("ACL") && !["Can Edit", "Can Add", "Can View", "Not Shared", undefined].includes(value)) return true; -- cgit v1.2.3-70-g09d2 From 7512ed96b9ed7a02332d55749889061191d82b55 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 31 Jul 2020 11:14:20 -0400 Subject: chaned implementation of playroundMode --- src/client/DocServer.ts | 31 +++++++++++----------- src/client/util/SettingsManager.tsx | 10 +++++-- .../views/collections/CollectionDockingView.tsx | 1 - 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'src/client/views') diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index dec8724c6..f5ee6da3c 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -9,6 +9,7 @@ import GestureOverlay from './views/GestureOverlay'; import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { runInAction } from 'mobx'; import { ObjectField } from '../fields/ObjectField'; +import { getPlaygroundMode } from '../fields/util'; /** * This class encapsulates the transfer and cross-client synchronization of @@ -156,23 +157,23 @@ export namespace DocServer { let _isReadOnly = false; export function makeReadOnly() { - if (_isReadOnly) return; - _isReadOnly = true; - _CreateField = field => { - _cache[field[Id]] = field; - }; - _UpdateField = emptyFunction; - _RespondToUpdate = emptyFunction; + if (!_isReadOnly) { + _isReadOnly = true; + _CreateField = field => _cache[field[Id]] = field; + _UpdateField = emptyFunction; + _RespondToUpdate = emptyFunction; + } } export function makeEditable() { - if (!_isReadOnly) return; - location.reload(); - // _isReadOnly = false; - // _CreateField = _CreateFieldImpl; - // _UpdateField = _UpdateFieldImpl; - // _respondToUpdate = _respondToUpdateImpl; - // _cache = {}; + if (_isReadOnly) { + location.reload(); + // _isReadOnly = false; + // _CreateField = _CreateFieldImpl; + // _UpdateField = _UpdateFieldImpl; + // _respondToUpdate = _respondToUpdateImpl; + // _cache = {}; + } } export function isReadOnly() { return _isReadOnly; } @@ -451,7 +452,7 @@ export namespace DocServer { } function _UpdateFieldImpl(id: string, diff: any) { - Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); + (!getPlaygroundMode()) && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); } let _UpdateField: (id: string, diff: any) => void = errorFunc; diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx index 90d59aa51..fbdceb43e 100644 --- a/src/client/util/SettingsManager.tsx +++ b/src/client/util/SettingsManager.tsx @@ -9,18 +9,20 @@ import "./SettingsManager.scss"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Networking } from "../Network"; import { CurrentUserUtils } from "./CurrentUserUtils"; -import { Utils } from "../../Utils"; +import { Utils, addStyleSheet, addStyleSheetRule, removeStyleSheetRule } from "../../Utils"; import { Doc } from "../../fields/Doc"; import GroupManager from "./GroupManager"; import HypothesisAuthenticationManager from "../apis/HypothesisAuthenticationManager"; import GoogleAuthenticationManager from "../apis/GoogleAuthenticationManager"; import { togglePlaygroundMode } from "../../fields/util"; +import { DocServer } from "../DocServer"; library.add(fa.faTimes); @observer export default class SettingsManager extends React.Component<{}> { public static Instance: SettingsManager; + static _settingsStyle = addStyleSheet(); @observable private isOpen = false; @observable private dialogueBoxOpacity = 1; @observable private overlayOpacity = 0.4; @@ -99,8 +101,12 @@ export default class SettingsManager extends React.Component<{}> { @action togglePlaygroundMode = () => { - togglePlaygroundMode(); + //togglePlaygroundMode(); this.playgroundMode = !this.playgroundMode; + if (this.playgroundMode) DocServer.Control.makeReadOnly(); + else DocServer.Control.makeEditable(); + + addStyleSheetRule(SettingsManager._settingsStyle, "lm_header", { background: "pink !important" }); } private get settingsInterface() { diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 53b2d5254..4952dedc9 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -595,7 +595,6 @@ export class CollectionDockingView extends React.Component { //stack.header.controlsContainer.find('.lm_popout').hide(); - stack.header.element[0].style.backgroundColor = DocServer.Control.isReadOnly() ? "#228540" : undefined; stack.header.element.on('mousedown', (e: any) => { if (e.target === stack.header.element[0] && e.button === 1) { this.AddTab(stack, Docs.Create.FreeformDocument([], { _width: this.props.PanelWidth(), _height: this.props.PanelHeight(), title: "Untitled Collection" })); -- cgit v1.2.3-70-g09d2 From c71d7fa4f84149bcb62246d50e06bfd1481365bc Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 31 Jul 2020 13:49:30 -0400 Subject: fixed undoin makin hyperlinks from richtextmenu. fixed indentin/etc pasted text --- .../views/nodes/formattedText/RichTextMenu.tsx | 16 +++++++++------- src/client/views/nodes/formattedText/nodes_rts.ts | 21 +++++++++++++++++---- 2 files changed, 26 insertions(+), 11 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 47a4911b8..7ccbfa051 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -223,7 +223,7 @@ export default class RichTextMenu extends AntimodeMenu { if (this.view && this.TextView.props.isSelected(true)) { const path = (this.view.state.selection.$from as any).path; for (let i = path.length - 3; i < path.length && i >= 0; i -= 3) { - if (path[i]?.type === this.view.state.schema.nodes.paragraph) { + if (path[i]?.type === this.view.state.schema.nodes.paragraph || path[i]?.type === this.view.state.schema.nodes.heading) { return path[i].attrs.align || "left"; } } @@ -490,7 +490,7 @@ export default class RichTextMenu extends AntimodeMenu { alignParagraphs(state: EditorState, align: "left" | "right" | "center", dispatch: any) { var tr = state.tr; state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => { - if (node.type === schema.nodes.paragraph) { + if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) { tr = tr.setNodeMarkup(pos, node.type, { ...node.attrs, align }, node.marks); return false; } @@ -503,7 +503,7 @@ export default class RichTextMenu extends AntimodeMenu { insetParagraph(state: EditorState, dispatch: any) { var tr = state.tr; state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => { - if (node.type === schema.nodes.paragraph) { + if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) { const inset = (node.attrs.inset ? Number(node.attrs.inset) : 0) + 10; tr = tr.setNodeMarkup(pos, node.type, { ...node.attrs, inset }, node.marks); return false; @@ -516,7 +516,7 @@ export default class RichTextMenu extends AntimodeMenu { outsetParagraph(state: EditorState, dispatch: any) { var tr = state.tr; state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => { - if (node.type === schema.nodes.paragraph) { + if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) { const inset = Math.max(0, (node.attrs.inset ? Number(node.attrs.inset) : 0) - 10); tr = tr.setNodeMarkup(pos, node.type, { ...node.attrs, inset }, node.marks); return false; @@ -529,8 +529,9 @@ export default class RichTextMenu extends AntimodeMenu { indentParagraph(state: EditorState, dispatch: any) { var tr = state.tr; + let headin = false; state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => { - if (node.type === schema.nodes.paragraph) { + if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) { const nodeval = node.attrs.indent ? Number(node.attrs.indent) : undefined; const indent = !nodeval ? 25 : nodeval < 0 ? 0 : nodeval + 25; tr = tr.setNodeMarkup(pos, node.type, { ...node.attrs, indent }, node.marks); @@ -538,14 +539,14 @@ export default class RichTextMenu extends AntimodeMenu { } return true; }); - dispatch?.(tr); + !headin && dispatch?.(tr); return true; } hangingIndentParagraph(state: EditorState, dispatch: any) { var tr = state.tr; state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos, parent, index) => { - if (node.type === schema.nodes.paragraph) { + if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) { const nodeval = node.attrs.indent ? Number(node.attrs.indent) : undefined; const indent = !nodeval ? -25 : nodeval > 0 ? 0 : nodeval - 10; tr = tr.setNodeMarkup(pos, node.type, { ...node.attrs, indent }, node.marks); @@ -827,6 +828,7 @@ export default class RichTextMenu extends AntimodeMenu { } // TODO: should check for valid URL + @undoBatch makeLinkToURL = (target: string, lcoation: string) => { ((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRight", "", target); } diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts index 1af821738..0eca6d753 100644 --- a/src/client/views/nodes/formattedText/nodes_rts.ts +++ b/src/client/views/nodes/formattedText/nodes_rts.ts @@ -66,9 +66,11 @@ export const nodes: { [index: string]: NodeSpec } = { // should hold the number 1 to 6. Parsed and serialized as `

` to // `

` elements. heading: { - attrs: { level: { default: 1 } }, - content: "inline*", - group: "block", + ...ParagraphNodeSpec, + attrs: { + ...ParagraphNodeSpec.attrs, + level: { default: 1 }, + }, defining: true, parseDOM: [{ tag: "h1", attrs: { level: 1 } }, { tag: "h2", attrs: { level: 2 } }, @@ -76,7 +78,18 @@ export const nodes: { [index: string]: NodeSpec } = { { tag: "h4", attrs: { level: 4 } }, { tag: "h5", attrs: { level: 5 } }, { tag: "h6", attrs: { level: 6 } }], - toDOM(node: any) { return ["h" + node.attrs.level, 0]; } + toDOM(node) { + var dom = toParagraphDOM(node) as any; + var level = node.attrs.level || 1; + dom[0] = 'h' + level; + return dom; + }, + getAttrs(dom: any) { + var attrs = getParagraphNodeAttrs(dom) as any; + var level = Number(dom.nodeName.substring(1)) || 1; + attrs.level = level; + return attrs; + } }, // :: NodeSpec A code listing. Disallows marks or non-text inline -- cgit v1.2.3-70-g09d2 From 982e2d8ebf4a3aed32443c8d23bb5a8ed01b0e5e Mon Sep 17 00:00:00 2001 From: bobzel Date: Fri, 31 Jul 2020 18:37:17 -0400 Subject: fixed color picker --- .../collections/collectionFreeForm/FormatShapePane.scss | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss index 010beb836..d49ab27fb 100644 --- a/src/client/views/collections/collectionFreeForm/FormatShapePane.scss +++ b/src/client/views/collections/collectionFreeForm/FormatShapePane.scss @@ -27,13 +27,15 @@ position: absolute; } -.sketch-picker { - background: #323232; - width: 160px !important; - height: 80% !important; - - .flexbox-fit { +.btn-group-palette { + .sketch-picker { background: #323232; + width: 160px !important; + height: 80% !important; + + .flexbox-fit { + background: #323232; + } } } -- cgit v1.2.3-70-g09d2 From 4792b8875f27770882943c8dc0ef021d22a37c06 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 2 Aug 2020 08:57:35 -0400 Subject: changed highlight() calls in PdfViewer and WebBox --- src/client/views/nodes/WebBox.tsx | 9 +++------ src/client/views/pdf/PDFViewer.tsx | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 3fbebe3e6..646a94aa7 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -536,12 +536,9 @@ export class WebBox extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); - return annotationDoc; - } - return undefined; + const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color); + annotationDoc && this.addDocument?.(annotationDoc); + return annotationDoc ?? undefined; } /** * This is temporary for creating annotations from highlights. It will diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 59fa6b08c..b81baf417 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -566,12 +566,9 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.Document); - if ([AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl)) { - const annotationDoc = this.makeAnnotationDocument(color); - annotationDoc && Doc.AddDocToList(this.props.Document, this.annotationKey, annotationDoc); - return annotationDoc; - } - return undefined; + const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color); + annotationDoc && this.addDocument?.(annotationDoc); + return annotationDoc ?? undefined; } /** -- cgit v1.2.3-70-g09d2 From 63fd10d0940331d68a9ce58b4b77734b11e393f5 Mon Sep 17 00:00:00 2001 From: bobzel Date: Sun, 2 Aug 2020 09:22:38 -0400 Subject: fixed hiding of close button based on permsisions. --- src/client/views/DocumentDecorations.tsx | 4 ++-- src/client/views/pdf/PDFViewer.tsx | 2 +- src/fields/util.ts | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 6e6ffc893..7fc4a5c99 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -586,7 +586,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (SnappingManager.GetIsDragging() || bounds.r - bounds.x < 2 || bounds.x === Number.MAX_VALUE || !seldoc || this._hidden || isNaN(bounds.r) || isNaN(bounds.b) || isNaN(bounds.x) || isNaN(bounds.y)) { return (null); } - const canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.Document)).some(permission => permission === AclAdmin || permission === AclEdit); + const canDelete = SelectionManager.SelectedDocuments().map(docView => GetEffectiveAcl(docView.props.ContainingCollectionDoc)).some(permission => permission === AclAdmin || permission === AclEdit); const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? (
Show context menu
} placement="top"> @@ -597,7 +597,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
{/* Currently, this is set to be enabled if there is no ink selected. It might be interesting to think about minimizing ink if it's useful? -syip2*/} -
) : null; +
) : (null); const titleArea = this._edtingTitle ? <> diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index b81baf417..5a43a076b 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -568,7 +568,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent