From f557c78db9a77812ab398aaff08d9511c1c65fc9 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 10 Aug 2020 18:07:51 +0530 Subject: prevented infinite loop in distributeAcls + allowed change of alias x, y, width, height in owned collection + changes to removeDocument calls in many places + comments etc --- src/fields/util.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/fields') diff --git a/src/fields/util.ts b/src/fields/util.ts index 4c71572db..7d3268b80 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -167,6 +167,9 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) // 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; + // if it's your alias then you can manipulate the x, y, width, height + if ((target.aliasOf || target.__fields?.aliasOf) && Doc.CurrentUserEmail === (target.__fields?.author || target.author) && (in_prop && ["_width", "_height", "x", "y"].includes(in_prop.toString()))) return AclEdit; + let effectiveAcl = AclPrivate; const HierarchyMapping = new Map([ [AclPrivate, 0], @@ -218,9 +221,10 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc changed = true; // maps over the aliases of the document - if (target.aliases) { - DocListCast(target.aliases).map(alias => { - distributeAcls(key, acl, alias, inheritingFromCollection); + const aliases = DocListCast(target.aliases); + if (aliases.length) { + aliases.map(alias => { + alias !== target && distributeAcls(key, acl, alias, inheritingFromCollection); }); } -- cgit v1.2.3-70-g09d2 From 4d6da44b4eb484d79fc263e5d36c02ea50265767 Mon Sep 17 00:00:00 2001 From: Andy Rickert Date: Wed, 12 Aug 2020 03:55:26 -0400 Subject: filtering in solr and pagination --- .../views/collections/CollectionSchemaHeaders.tsx | 13 +- src/client/views/collections/CollectionSubView.tsx | 2 - src/client/views/search/SearchBox.tsx | 269 +++++++++++++-------- src/fields/Doc.ts | 1 + 4 files changed, 177 insertions(+), 108 deletions(-) (limited to 'src/fields') diff --git a/src/client/views/collections/CollectionSchemaHeaders.tsx b/src/client/views/collections/CollectionSchemaHeaders.tsx index c1c4eb628..fc2463c97 100644 --- a/src/client/views/collections/CollectionSchemaHeaders.tsx +++ b/src/client/views/collections/CollectionSchemaHeaders.tsx @@ -387,8 +387,7 @@ export class KeysDropdown extends React.Component { }); // if search term does not already exist as a group type, give option to create new group type - console.log("Start here"); - console.log(this._key, this._searchTerm.slice(0, this._key.length)); + if (this._key !== this._searchTerm.slice(0, this._key.length)) { console.log("little further"); if (!exactFound && this._searchTerm !== "" && this.props.canAddNew) { @@ -414,16 +413,20 @@ export class KeysDropdown extends React.Component { } return options; } + + docSafe: Doc[] = [] + @action renderFilterOptions = (): JSX.Element[] | JSX.Element => { - console.log("we here"); if (!this._isOpen) { this.defaultMenuHeight = 0; return <>; } let keyOptions: string[] = []; - let docs = DocListCast(this.props.dataDoc![this.props.fieldKey!]); - + if (this.docSafe.length === 0) { + this.docSafe = DocListCast(this.props.dataDoc![this.props.fieldKey!]); + } + let docs = this.docSafe; docs.forEach((doc) => { const key = StrCast(doc[this._key]); if (keyOptions.includes(key) === false) { diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 806ae8ffa..a4493897c 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -172,8 +172,6 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T, moreProps?: }); return docsforFilter; } - console.log("you fool"); - console.log(childDocs); const docRangeFilters = this.props.ignoreFields?.includes("_docRangeFilters") ? [] : Cast(this.props.Document._docRangeFilters, listSpec("string"), []); return this.props.Document.dontRegisterView ? childDocs : DocUtils.FilterDocs(childDocs, this.docFilters(), docRangeFilters, viewSpecScript); } diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index da298e54c..39dd8d4bf 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -1,6 +1,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; -import { action, computed, observable, runInAction } from 'mobx'; +import { action, computed, observable, runInAction, reaction, IReactionDisposer } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import * as rp from 'request-promise'; @@ -24,6 +24,8 @@ import { ViewBoxBaseComponent } from "../DocComponent"; import { DocumentView } from '../nodes/DocumentView'; import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./SearchBox.scss"; +import { stringifyUrl } from "query-string"; +import { filterSeries } from "async"; export const searchSchema = createSchema({ id: "string", @@ -86,7 +88,19 @@ export class SearchBox extends ViewBoxBaseComponent { + this._disposers.filters = reaction(() => Cast(this.props.Document._docFilters, listSpec("string")), // if a link is deleted, then remove all hyperlinks that reference it from the text's marks + newFilters => { + if (this.searchFullDB) { + runInAction(() => this._pageStart = 0); + this.submitSearch(); + // newFilters?.forEach(f => { + // console.log(f); + // }) + } + }); if (this.setupButtons === false) { runInAction(() => this.setupButtons = true); @@ -113,6 +127,10 @@ export class SearchBox extends ViewBoxBaseComponent disposer?.()); + } + @action getViews = (doc: Doc) => SearchUtil.GetViewsOfDocument(doc) @@ -123,8 +141,6 @@ export class SearchBox extends ViewBoxBaseComponent) { this.layoutDoc._searchString = e.target.value; this.newsearchstring = e.target.value; - - if (e.target.value === "") { if (this.currentSelectedCollection !== undefined) { let newarray: Doc[] = []; @@ -176,6 +192,7 @@ export class SearchBox extends ViewBoxBaseComponent { if (e.key === "Enter") { this.layoutDoc._searchString = this.newsearchstring; + runInAction(() => this._pageStart = 0); if (StrCast(this.layoutDoc._searchString) !== "" || !this.searchFullDB) { runInAction(() => this.open = true); @@ -228,26 +245,102 @@ export class SearchBox extends ViewBoxBaseComponent { + i === 0 ? newWords.push(key + mod + word) : newWords.push("&& " + key + mod + word) + }); + let v = "(" + newWords.join(" ") + ")"; + query = query + " && " + v; + } + else { + for (let i = 0; i < values.length; i++) { + let mod = "_t:" + const newWords: string[] = []; + const oldWords = values[i].split(" "); + oldWords.forEach((word, i) => { + i === 0 ? newWords.push(key + mod + word) : newWords.push("&& " + key + mod + word) + }); + let v = "(" + newWords.join(" ") + ")"; + if (i === 0) { + query = query + " && (" + v; + if (values.length === 1) { + query = query + ")"; + } + } + else if (i === values.length - 1) { + query = query + " " + v + ")"; + } + else { + query = query + " " + v; + } + } + } } + + + // let limit = typepos.length + // typepos.forEach(i => { + // if (i === 0) { + // if (i + 1 === limit) { + // query = query + " && " + filters[i] + "_t:" + filters; + // } + // else if (filters[i] === filters[i + 3]) { + // query = query + " && (" + filters[i] + "_t:" + filters; + // } + // else { + // query = query + " && " + filters[i] + "_t:" + filters; + // } + + // } + // else if (i + 3 > filters.length) { + + // } + // else { + + // } + + // }); + + // query = this.applyBasicFieldFilters(query); + + + + query = query.replace(/-\s+/g, ''); + query = query.replace(/-/g, ""); + console.log(query); return query; } @@ -400,15 +493,9 @@ export class SearchBox extends ViewBoxBaseComponent { if (d.data !== undefined) { d._searchDocs = new List(); - d._docFilters = new List(); + //d._docFilters = new List(); const newdocs = DocListCast(d.data); newdocs.forEach((newdoc) => { newarray.push(newdoc); @@ -463,7 +549,7 @@ export class SearchBox extends ViewBoxBaseComponent([]); @@ -471,9 +557,9 @@ export class SearchBox extends ViewBoxBaseComponent { Doc.UnBrushDoc(result[0]); result[0].searchMatch = undefined; @@ -542,11 +628,12 @@ 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, { fq: this.filterQuery, start: this._maxSearchIndex, rows: 10000000, hl: true, "hl.fl": "*", }).then(action(async (res: SearchUtil.DocSearchResult) => { // happens at the beginning if (res.numFound !== this._numTotalResults && this._numTotalResults === -1) { this._numTotalResults = res.numFound; } + console.log(res.numFound); const highlighting = res.highlighting || {}; const highlightList = res.docs.map(doc => highlighting[doc[Id]]); const lines = new Map(); @@ -558,31 +645,23 @@ export class SearchBox extends ViewBoxBaseComponent { filteredDocs.forEach((doc, i) => { + console.log(i); const index = this._resultsSet.get(doc); const highlight = highlights[doc[Id]]; const line = lines.get(doc[Id]) || []; const hlights = highlight ? Object.keys(highlight).map(key => key.substring(0, key.length - 2)).filter(k => k) : []; doc ? console.log(Cast(doc.context, Doc)) : null; - if (this.findCommonElements(hlights)) { - } - else { - const layoutresult = Cast(doc.type, "string"); - if (layoutresult) { - if (this.new_buckets[layoutresult] === undefined) { - this.new_buckets[layoutresult] = 1; - } - else { - this.new_buckets[layoutresult] = this.new_buckets[layoutresult] + 1; - } - } - if (index === undefined) { - this._resultsSet.set(doc, this._results.length); - this._results.push([doc, hlights, line]); - } else { - this._results[index][1].push(...hlights); - this._results[index][2].push(...line); - } + // if (this.findCommonElements(hlights)) { + // } + if (index === undefined) { + this._resultsSet.set(doc, this._results.length); + this._results.push([doc, hlights, line]); + console.log(i); + } else { + this._results[index][1].push(...hlights); + this._results[index][2].push(...line); } + }); }); @@ -663,15 +742,16 @@ export class SearchBox extends ViewBoxBaseComponent) => { if (!this._resultsRef.current) return; - this.props.Document._schemaHeaders = new List([]); const scrollY = e ? e.currentTarget.scrollTop : this._resultsRef.current ? this._resultsRef.current.scrollTop : 0; const itemHght = 53; - const startIndex = Math.floor(Math.max(0, scrollY / itemHght)); //const endIndex = Math.ceil(Math.min(this._numTotalResults - 1, startIndex + (this._resultsRef.current.getBoundingClientRect().height / itemHght))); const endIndex = 30; //this._endIndex = endIndex === -1 ? 12 : endIndex; @@ -699,62 +779,42 @@ export class SearchBox extends ViewBoxBaseComponent(this._numTotalResults === -1 ? 0 : this._numTotalResults); } - for (let i = 0; i < this._numTotalResults; i++) { + let max = this._pageStart + this._pageCount; + max > this._results.length ? max = this._results.length : console.log(""); + for (let i = this._pageStart; i < max; i++) { //if the index is out of the window then put a placeholder in //should ones that have already been found get set to placeholders? - if (i < startIndex || i > endIndex) { - if (this._isSearch[i] !== "placeholder") { - this._isSearch[i] = "placeholder"; - this._isSorted[i] = "placeholder"; - this._visibleElements[i] =
Loading...
; - } - } - else { - if (this._isSearch[i] !== "search") { - let result: [Doc, string[], string[]] | undefined = undefined; - if (i >= this._results.length) { - this.getResults(StrCast(this.layoutDoc._searchString)); - if (i < this._results.length) result = this._results[i]; - if (result) { - const highlights = Array.from([...Array.from(new Set(result[1]).values())]); - const lines = new List(result[2]); - result[0].lines = lines; - result[0].highlighting = highlights.join(", "); - highlights.forEach((item) => headers.add(item)); - this._visibleDocuments[i] = result[0]; - this._isSearch[i] = "search"; - Doc.BrushDoc(result[0]); - result[0].searchMatch = true; - Doc.AddDocToList(this.dataDoc, this.props.fieldKey, result[0]); - this.children++; - } - } - else { - result = this._results[i]; - if (result) { - const highlights = Array.from([...Array.from(new Set(result[1]).values())]); - const lines = new List(result[2]); - highlights.forEach((item) => headers.add(item)); - result[0].lines = lines; - result[0].highlighting = highlights.join(", "); - result[0].searchMatch = true; - if (i < this._visibleDocuments.length) { - this._visibleDocuments[i] = result[0]; - this._isSearch[i] = "search"; - Doc.BrushDoc(result[0]); - Doc.AddDocToList(this.dataDoc, this.props.fieldKey, result[0]); - this.children++; - } - } + + if (this._isSearch[i] !== "search") { + let result: [Doc, string[], string[]] | undefined = undefined; + + result = this._results[i]; + if (result) { + const highlights = Array.from([...Array.from(new Set(result[1]).values())]); + const lines = new List(result[2]); + highlights.forEach((item) => headers.add(item)); + result[0].lines = lines; + result[0].highlighting = highlights.join(", "); + result[0].searchMatch = true; + if (i < this._visibleDocuments.length) { + this._visibleDocuments[i] = result[0]; + this._isSearch[i] = "search"; + Doc.BrushDoc(result[0]); + Doc.AddDocToList(this.dataDoc, this.props.fieldKey, result[0]); + this.children++; } + } + } } const schemaheaders: SchemaHeaderField[] = []; this.headerscale = headers.size; headers.forEach((item) => schemaheaders.push(new SchemaHeaderField(item, "#f1efeb"))); this.headercount = schemaheaders.length; - this.props.Document._schemaHeaders = new List(schemaheaders); + if (Cast(this.props.Document._docFilters, listSpec("string"), []).length === 0) { + this.props.Document._schemaHeaders = new List(schemaheaders); + } if (this._maxSearchIndex >= this._numTotalResults) { this._visibleElements.length = this._results.length; this._visibleDocuments.length = this._results.length; @@ -799,6 +859,11 @@ export class SearchBox extends ViewBoxBaseComponent([]); + this.resultsScrolled(); + } render() { this.props.Document._chromeStatus === "disabled"; this.props.Document._searchDoc = true; @@ -807,14 +872,16 @@ export class SearchBox extends ViewBoxBaseComponent 5 ? length = 1076 : length = cols * 205 + 51; let height = 0; const rows = this.children; - rows > 6 ? height = 31 + 31 * 6 : height = 31 * rows + 31; + height = 31 + 31 * 6; return (
{Doc.CurrentUserEmail}
drag search results as collection
} >
- StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg" + {/* StrCast(this.layoutDoc._searchString) ? this.startDragCollection() : undefined)} icon={"search"} size="lg" + style={{ cursor: "hand", color: "black", padding: 1, left: 35, position: "relative" }} /> */} + { this.newpage(); }} icon={"search"} size="lg" style={{ cursor: "hand", color: "black", padding: 1, left: 35, position: "relative" }} />
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index b535fea5a..927ff4422 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -1044,6 +1044,7 @@ export namespace Doc { if (docFilters[i] === key && (docFilters[i + 1] === value || modifiers === "match")) { if (docFilters[i + 2] === modifiers && modifiers && docFilters[i + 1] === value) return; docFilters.splice(i, 3); + container._docFilters = new List(docFilters); break; } } -- cgit v1.2.3-70-g09d2 From 4927e0d6318afc63f3476839999761decc5842ac Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 12 Aug 2020 08:04:56 -0400 Subject: switching syntax from && to AND for solr filters and added quotes around solr term values --- src/client/views/search/SearchBox.tsx | 8 ++++---- src/fields/SchemaHeaderField.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/fields') diff --git a/src/client/views/search/SearchBox.tsx b/src/client/views/search/SearchBox.tsx index 39dd8d4bf..36b490839 100644 --- a/src/client/views/search/SearchBox.tsx +++ b/src/client/views/search/SearchBox.tsx @@ -279,10 +279,10 @@ export class SearchBox extends ViewBoxBaseComponent { - i === 0 ? newWords.push(key + mod + word) : newWords.push("&& " + key + mod + word) + i === 0 ? newWords.push(key + mod + "\"" + word + "\"") : newWords.push("AND " + key + mod + "\"" + word + "\"") }); let v = "(" + newWords.join(" ") + ")"; - query = query + " && " + v; + query = query + " AND " + v; } else { for (let i = 0; i < values.length; i++) { @@ -290,11 +290,11 @@ export class SearchBox extends ViewBoxBaseComponent { - i === 0 ? newWords.push(key + mod + word) : newWords.push("&& " + key + mod + word) + i === 0 ? newWords.push(key + mod + "\"" + word + "\"") : newWords.push("AND " + key + mod + "\"" + word + "\"") }); let v = "(" + newWords.join(" ") + ")"; if (i === 0) { - query = query + " && (" + v; + query = query + " AND (" + v; if (values.length === 1) { query = query + ")"; } diff --git a/src/fields/SchemaHeaderField.ts b/src/fields/SchemaHeaderField.ts index 07c90f5a2..22ae454f8 100644 --- a/src/fields/SchemaHeaderField.ts +++ b/src/fields/SchemaHeaderField.ts @@ -114,7 +114,7 @@ export class SchemaHeaderField extends ObjectField { } [ToScriptString]() { - return `invalid`; + return `header(${this.heading},${this.type}})`; } [ToString]() { return `SchemaHeaderField`; -- cgit v1.2.3-70-g09d2 From c01cb1dcda454a80555d2ae041800ef3bd261d81 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 12 Aug 2020 21:47:39 +0530 Subject: used datadoc for acl calculations in many places + some other changes --- src/client/views/DocComponent.tsx | 31 ++++++++++++---------- src/client/views/DocumentDecorations.tsx | 5 ++-- src/client/views/GlobalKeyHandler.ts | 3 +-- src/client/views/PropertiesButtons.tsx | 3 +-- src/client/views/collections/CollectionView.tsx | 8 +++--- .../collections/collectionFreeForm/MarqueeView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 6 ++--- src/client/views/nodes/WebBox.tsx | 4 +-- src/client/views/pdf/PDFViewer.tsx | 4 +-- src/fields/util.ts | 6 +---- 10 files changed, 33 insertions(+), 39 deletions(-) (limited to 'src/fields') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 4a92ed262..8c8bb6fde 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -122,20 +122,23 @@ export function ViewBoxAnnotatableComponent

doc.isPushpin = doc.annotationOn = undefined); - const targetDataDoc = this.dataDoc; - const value = DocListCast(targetDataDoc[this.annotationKey]); - const toRemove = value.filter(v => docs.includes(v)); - - if (toRemove.length !== 0) { - const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc; - toRemove.forEach(doc => { - Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey, doc); - recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); - doc.deleted = true; - }); - return true; + const effectiveAcl = GetEffectiveAcl(this.dataDoc); + if (effectiveAcl === AclAdmin || effectiveAcl === AclEdit) { + const docs = doc instanceof Doc ? [doc] : doc; + docs.map(doc => doc.isPushpin = doc.annotationOn = undefined); + const targetDataDoc = this.dataDoc; + const value = DocListCast(targetDataDoc[this.annotationKey]); + const toRemove = value.filter(v => docs.includes(v)); + + if (toRemove.length !== 0) { + const recent = Cast(Doc.UserDoc().myRecentlyClosed, Doc) as Doc; + toRemove.forEach(doc => { + Doc.RemoveDocFromList(targetDataDoc, this.props.fieldKey + "-annotations", doc); + recent && Doc.AddDocToList(recent, "data", doc, undefined, true, true); + doc.deleted = true; + }); + return true; + } } return false; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index cfe76f361..596c5931b 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -607,9 +607,8 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> return (null); } const canDelete = SelectionManager.SelectedDocuments().some(docView => { - const docAcl = GetEffectiveAcl(docView.props.Document); - const collectionAcl = GetEffectiveAcl(docView.props.ContainingCollectionDoc); - return [docAcl, collectionAcl].some(acl => [AclAdmin, AclEdit].includes(acl)); + const collectionAcl = GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]); + return collectionAcl === AclAdmin || collectionAcl === AclEdit; }); const minimal = bounds.r - bounds.x < 100 ? true : false; const maximizeIcon = minimal ? ( diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index 1fc0ed034..be6aa6be2 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -1,6 +1,6 @@ import { action } from "mobx"; import { DateField } from "../../fields/DateField"; -import { Doc, DocListCast, AclEdit, AclAdmin } from "../../fields/Doc"; +import { Doc, DocListCast } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; import { InkTool } from "../../fields/InkField"; import { List } from "../../fields/List"; @@ -23,7 +23,6 @@ import PDFMenu from "./pdf/PDFMenu"; import { ContextMenu } from "./ContextMenu"; import GroupManager from "../util/GroupManager"; import { CollectionFreeFormViewChrome } from "./collections/CollectionMenu"; -import { GetEffectiveAcl } from "../../fields/util"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise; diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx index 0ca28df9c..1ddae97ce 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, DocListCast, AclEdit, AclAdmin } from "../../fields/Doc"; +import { Doc } from "../../fields/Doc"; import { RichTextField } from '../../fields/RichTextField'; import { Cast, NumCast, BoolCast } from "../../fields/Types"; import { emptyFunction, setupMoveUpEvents, Utils } from "../../Utils"; @@ -30,7 +30,6 @@ 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; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index a048d4ebd..7562d7e9c 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -142,7 +142,7 @@ export class CollectionView extends Touchable !docList.includes(d)); - const effectiveAcl = GetEffectiveAcl(this.props.Document); + const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]); if (added.length) { if (effectiveAcl === AclPrivate || effectiveAcl === AclReadonly) { @@ -193,10 +193,8 @@ export class CollectionView extends Touchable { - 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) { + const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]); + if (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) { const docs = doc instanceof Doc ? [doc] : doc as Doc[]; const targetDataDoc = this.props.Document[DataSym]; const value = DocListCast(targetDataDoc[this.props.fieldKey]); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index a396dc6c8..54b09ab72 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -278,7 +278,7 @@ export class MarqueeView extends React.Component(Docu RadialMenu.Instance.openMenu(pt.pageX - 15, pt.pageY - 15); // RadialMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), "onRight"), icon: "map-pin", selected: -1 }); - const effectiveAcl = GetEffectiveAcl(this.props.Document); + const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]); (effectiveAcl === AclEdit || effectiveAcl === AclAdmin) && RadialMenu.Instance.addItem({ description: "Delete", event: () => { this.props.ContainingCollectionView?.removeDocument(this.props.Document), RadialMenu.Instance.closeMenu(); }, icon: "external-link-square-alt", selected: -1 }); // RadialMenu.Instance.addItem({ description: "Open in a new tab", event: () => this.props.addDocTab(this.props.Document, "onRight"), icon: "trash", selected: -1 }); RadialMenu.Instance.addItem({ description: "Pin", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin", selected: -1 }); @@ -992,7 +992,7 @@ export class DocumentView extends DocComponent(Docu render() { if (!(this.props.Document instanceof Doc)) return (null); - if (GetEffectiveAcl(this.props.Document) === AclPrivate) return (null); + if (GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate) return (null); if (this.props.Document.hidden) return (null); const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth); const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null))); diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 3283f568a..f37909e6e 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -4,7 +4,7 @@ import { action, computed, IReactionDisposer, observable, reaction, runInAction import { observer } from "mobx-react"; import { Dictionary } from "typescript-collections"; import * as WebRequest from 'web-request'; -import { Doc, DocListCast, Opt, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc"; +import { Doc, DocListCast, Opt, AclAddonly, AclEdit, AclAdmin, DataSym } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { HtmlField } from "../../../fields/HtmlField"; @@ -535,7 +535,7 @@ export class WebBox extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights - const effectiveAcl = GetEffectiveAcl(this.props.Document); + const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]); const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) ? this.makeAnnotationDocument(color) : undefined; annotationDoc && this.addDocument?.(annotationDoc); return annotationDoc ?? undefined; diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 7c1b2f621..cca86adb5 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, AclAddonly, AclEdit, AclAdmin } from "../../../fields/Doc"; +import { Doc, DocListCast, FieldResult, HeightSym, Opt, WidthSym, AclAddonly, AclEdit, AclAdmin, DataSym } from "../../../fields/Doc"; import { documentSchema } from "../../../fields/documentSchemas"; import { Id } from "../../../fields/FieldSymbols"; import { InkTool } from "../../../fields/InkField"; @@ -573,7 +573,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent { // creates annotation documents for current highlights - const effectiveAcl = GetEffectiveAcl(this.props.Document); + const effectiveAcl = GetEffectiveAcl(this.props.Document[DataSym]); const annotationDoc = [AclAddonly, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color); annotationDoc && this.addDocument?.(annotationDoc); return annotationDoc as Doc ?? undefined; diff --git a/src/fields/util.ts b/src/fields/util.ts index 7d3268b80..3d832636f 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -161,15 +161,11 @@ export function GetEffectiveAcl(target: any, in_prop?: string | symbol | number) if (target[AclSym] && Object.keys(target[AclSym]).length) { // if the current user is the author of the document / the current user is a member of the admin group - // but not if the doc in question is an alias - the current user will be the author of their alias rather than the original author - if ((Doc.CurrentUserEmail === (target.__fields?.author || target.author) && !(target.aliasOf || target.__fields?.aliasOf)) || currentUserGroups.includes("admin")) return AclAdmin; + if (Doc.CurrentUserEmail === (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; - // if it's your alias then you can manipulate the x, y, width, height - if ((target.aliasOf || target.__fields?.aliasOf) && Doc.CurrentUserEmail === (target.__fields?.author || target.author) && (in_prop && ["_width", "_height", "x", "y"].includes(in_prop.toString()))) return AclEdit; - let effectiveAcl = AclPrivate; const HierarchyMapping = new Map([ [AclPrivate, 0], -- cgit v1.2.3-70-g09d2