aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/DocServer.ts7
-rw-r--r--src/client/util/GroupManager.tsx60
-rw-r--r--src/client/util/SharingManager.tsx42
-rw-r--r--src/client/views/DocComponent.tsx7
-rw-r--r--src/client/views/collections/CollectionView.tsx8
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx6
-rw-r--r--src/client/views/nodes/DocumentView.tsx5
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx8
8 files changed, 53 insertions, 90 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts
index eac53bb02..860a8fd92 100644
--- a/src/client/DocServer.ts
+++ b/src/client/DocServer.ts
@@ -39,9 +39,10 @@ export namespace DocServer {
const docsWithUpdates: { [field: string]: Set<Doc> } = {};
export var PlaygroundFields: string[];
- export function setPlaygroundFields(livePlayougroundFields: string[]) {
- DocServer.PlaygroundFields = livePlayougroundFields;
- livePlayougroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground));
+ export function setPlaygroundFields(livePlaygroundFields: string[]) {
+ console.log("here");
+ DocServer.PlaygroundFields = livePlaygroundFields;
+ livePlaygroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground));
}
export function setFieldWriteMode(field: string, writeMode: WriteMode) {
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index b14dcf55b..83b206f94 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -33,7 +33,7 @@ export default class GroupManager extends React.Component<{}> {
@observable private selectedUsers: UserOptions[] | null = null; // list of users selected in the "Select users" dropdown.
@observable currentGroup: Opt<Doc>; // the currently selected group.
private inputRef: React.RefObject<HTMLInputElement> = React.createRef(); // the ref for the input box.
- private currentUserGroups: Doc[] = [];
+ currentUserGroups: string[] = [];
constructor(props: Readonly<{}>) {
super(props);
@@ -51,7 +51,7 @@ export default class GroupManager extends React.Component<{}> {
DocListCastAsync(this.GroupManagerDoc?.data).then(groups => {
groups?.forEach(group => {
const members: string[] = JSON.parse(StrCast(group.members));
- if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(group);
+ if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(StrCast(group.groupName));
});
})
.finally(() => console.log(this.currentUserGroups));
@@ -82,11 +82,6 @@ export default class GroupManager extends React.Component<{}> {
return this.users.map(user => ({ label: user, value: user }));
}
-
- get groupMemberships() {
- return this.currentUserGroups;
- }
-
/**
* Makes the GroupManager visible.
*/
@@ -151,6 +146,11 @@ export default class GroupManager extends React.Component<{}> {
);
}
+ getGroupMembers(group: string | Doc): string[] {
+ if (group instanceof Doc) return JSON.parse(StrCast(group.members)) as string[];
+ else return JSON.parse(StrCast(this.getGroup(group)!.members)) as string[];
+ }
+
/**
* @returns the members of the admin group.
*/
@@ -280,52 +280,6 @@ export default class GroupManager extends React.Component<{}> {
}
/**
- * A getter that @returns the interface rendered to view an individual group.
- */
- // private get editingInterface() {
- // const members: string[] = this.currentGroup ? JSON.parse(StrCast(this.currentGroup.members)) : [];
- // const options: UserOptions[] = this.currentGroup ? this.options.filter(option => !(JSON.parse(StrCast(this.currentGroup!.members)) as string[]).includes(option.value)) : [];
- // return (!this.currentGroup ? null :
- // <div className="editing-interface">
- // <div className="editing-header">
- // <b>{this.currentGroup.groupName}</b>
- // <div className={"close-button"} onClick={action(() => this.currentGroup = undefined)}>
- // <FontAwesomeIcon icon={fa.faWindowClose} size={"lg"} />
- // </div>
-
- // {this.hasEditAccess(this.currentGroup) ?
- // <div className="group-buttons">
- // <div className="add-member-dropdown">
- // <Select
- // // isMulti={true}
- // isSearchable={true}
- // options={options}
- // onChange={selectedOption => this.addMemberToGroup(this.currentGroup!, (selectedOption as UserOptions).value)}
- // placeholder={"Add members"}
- // value={null}
- // closeMenuOnSelect={true}
- // />
- // </div>
- // <button onClick={() => this.deleteGroup(this.currentGroup!)}>Delete group</button>
- // </div> :
- // null}
- // </div>
- // <div className="editing-contents">
- // {members.map(member => (
- // <div className="editing-row">
- // <div className="user-email">
- // {member}
- // </div>
- // {this.hasEditAccess(this.currentGroup!) ? <button onClick={() => this.removeMemberFromGroup(this.currentGroup!, member)}> Remove </button> : null}
- // </div>
- // ))}
- // </div>
- // </div>
- // );
-
- // }
-
- /**
* A getter that @returns the main interface for the GroupManager.
*/
private get groupInterface() {
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index e74824581..bec6b973b 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -43,18 +43,18 @@ export enum SharingPermissions {
// [SharingPermissions.Edit, "green"]
// ]);
-const HierarchyMapping = new Map<string, string>([
- [SharingPermissions.None, "0"],
- [SharingPermissions.View, "1"],
- [SharingPermissions.Add, "2"],
- [SharingPermissions.Edit, "3"],
+// export const HierarchyMapping = new Map<string, number>([
+// [SharingPermissions.None, 0],
+// [SharingPermissions.View, 1],
+// [SharingPermissions.Add, 2],
+// [SharingPermissions.Edit, 3]
- ["0", SharingPermissions.None],
- ["1", SharingPermissions.View],
- ["2", SharingPermissions.Add],
- ["3", SharingPermissions.Edit]
+// // ["0", SharingPermissions.None],
+// // ["1", SharingPermissions.View],
+// // ["2", SharingPermissions.Add],
+// // ["3", SharingPermissions.Edit]
-]);
+// ]);
interface GroupOptions {
label: string;
@@ -161,14 +161,6 @@ export default class SharingManager extends React.Component<{}> {
const ACL = `ACL-${StrCast(group.groupName)}`;
target[ACL] = permission;
- // const sharingDoc = this.sharingDoc!;
- // if (permission === SharingPermissions.None) {
- // const metadata = sharingDoc[StrCast(group.groupName)];
- // if (metadata) sharingDoc[StrCast(group.groupName)] = undefined;
- // }
- // else {
- // sharingDoc[StrCast(group.groupName)] = permission;
- // }
group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List<Doc>).push(target) : group.docsShared = new List<Doc>([target]);
@@ -206,7 +198,7 @@ export default class SharingManager extends React.Component<{}> {
const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email));
users.forEach(user => Doc.RemoveDocFromList(user.notificationDoc, storage, doc));
- })
+ });
}
}
@@ -224,8 +216,16 @@ export default class SharingManager extends React.Component<{}> {
target[ACL] = permission;
- 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);
+ if (permission !== SharingPermissions.None) {
+ !this.sharedUsers.includes(recipient) && this.sharedUsers.push(recipient);
+
+ Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
+ }
+ else {
+ const index = this.sharedUsers.findIndex(user => user === recipient);
+ index !== -1 && this.sharedUsers.splice(index, 1);
+ Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
+ }
}
diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx
index 9b9a28f0f..e8c34d931 100644
--- a/src/client/views/DocComponent.tsx
+++ b/src/client/views/DocComponent.tsx
@@ -7,6 +7,7 @@ import { InteractionUtils } from '../util/InteractionUtils';
import { List } from '../../fields/List';
import { DateField } from '../../fields/DateField';
import { ScriptField } from '../../fields/ScriptField';
+import { getEffectiveAcl } from '../../fields/util';
/// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView)
@@ -137,10 +138,12 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T
const targetDataDoc = this.props.Document[DataSym];
const docList = DocListCast(targetDataDoc[this.annotationKey]);
const added = docs.filter(d => !docList.includes(d));
+ console.log("here");
+ const effectiveAcl = getEffectiveAcl(this.dataDoc);
if (added.length) {
- if (this.dataDoc[AclSym] === AclReadonly) {
+ if (effectiveAcl === AclReadonly) {
return false;
- } else if (this.dataDoc[AclSym] === AclAddonly) {
+ } else if (effectiveAcl === AclAddonly) {
added.map(doc => Doc.AddDocToList(targetDataDoc, this.annotationKey, doc));
} else {
added.map(doc => doc.context = this.props.Document);
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 26abd2529..0dfe9c52a 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 } from '../../../fields/util';
+import { TraceMobx, getEffectiveAcl } 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';
@@ -132,10 +132,12 @@ export class CollectionView extends Touchable<FieldViewProps & CollectionViewCus
const targetDataDoc = this.props.Document[DataSym];
const docList = DocListCast(targetDataDoc[this.props.fieldKey]);
const added = docs.filter(d => !docList.includes(d));
+ console.log("here");
+ const effectiveAcl = getEffectiveAcl(this.dataDoc);
if (added.length) {
- if (this.dataDoc[AclSym] === AclReadonly) {
+ if (effectiveAcl === AclReadonly) {
return false;
- } else if (this.dataDoc[AclSym] === AclAddonly) {
+ } else if (effectiveAcl === AclAddonly) {
added.map(doc => Doc.AddDocToList(targetDataDoc, this.props.fieldKey, doc));
} else {
added.map(doc => {
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index f1438fd54..d480c76d0 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -36,7 +36,7 @@ import { WebBox } from "./WebBox";
import { InkingStroke } from "../InkingStroke";
import React = require("react");
import { RecommendationsBox } from "../RecommendationsBox";
-import { TraceMobx } from "../../../fields/util";
+import { TraceMobx, getEffectiveAcl } from "../../../fields/util";
import { ScriptField } from "../../../fields/ScriptField";
import XRegExp = require("xregexp");
@@ -184,8 +184,8 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
const bindings = this.CreateBindings(onClick, onInput);
// layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns
-
- return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || this.layoutDoc[AclSym] === AclPrivate) ? (null) :
+ console.log("here");
+ return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || getEffectiveAcl(this.layoutDoc) === AclPrivate) ? (null) :
<ObserverJsxParser
key={42}
blacklistedAttrs={[]}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 297a9f2a5..e277ddc36 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -12,7 +12,7 @@ import { listSpec } from "../../../fields/Schema";
import { SchemaHeaderField } from '../../../fields/SchemaHeaderField';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types";
-import { TraceMobx } from '../../../fields/util';
+import { TraceMobx, getEffectiveAcl } from '../../../fields/util';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
import { emptyFunction, OmitKeys, returnOne, returnTransparent, Utils, emptyPath } from "../../../Utils";
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
@@ -1188,7 +1188,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
render() {
- if (this.props.Document[AclSym] && this.props.Document[AclSym] === AclPrivate) return (null);
+ console.log("here");
+ if (getEffectiveAcl(this.props.Document) === AclPrivate) return (null);
if (!(this.props.Document instanceof Doc)) 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);
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/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index fc63dfbf5..a0dbcd980 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -13,7 +13,7 @@ import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from "
import { ReplaceStep } from 'prosemirror-transform';
import { EditorView } from "prosemirror-view";
import { DateField } from '../../../../fields/DateField';
-import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclSym } from "../../../../fields/Doc";
+import { DataSym, Doc, DocListCast, DocListCastAsync, Field, HeightSym, Opt, WidthSym, AclSym, AclEdit } from "../../../../fields/Doc";
import { documentSchema } from '../../../../fields/documentSchemas';
import applyDevTools = require("prosemirror-dev-tools");
import { removeMarkWithAttrs } from "./prosemirrorPatches";
@@ -24,7 +24,7 @@ import { RichTextField } from "../../../../fields/RichTextField";
import { RichTextUtils } from '../../../../fields/RichTextUtils';
import { createSchema, makeInterface } from "../../../../fields/Schema";
import { Cast, DateCast, NumCast, StrCast, ScriptCast } from "../../../../fields/Types";
-import { TraceMobx, OVERRIDE_ACL } from '../../../../fields/util';
+import { TraceMobx, OVERRIDE_ACL, getEffectiveAcl } from '../../../../fields/util';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnOne, returnZero, Utils, setupMoveUpEvents } from '../../../../Utils';
import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
import { DocServer } from "../../../DocServer";
@@ -226,7 +226,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const curProto = Cast(Cast(this.dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype
const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template
const json = JSON.stringify(state.toJSON());
- if (!this.dataDoc[AclSym]) {
+ // if (!this.dataDoc[AclSym]) { // what?
+ console.log("here");
+ if (getEffectiveAcl(this.dataDoc) === AclEdit) {
if (!this._applyingChange && json.replace(/"selection":.*/, "") !== curProto?.Data.replace(/"selection":.*/, "")) {
this._applyingChange = true;
(curText !== Cast(this.dataDoc[this.fieldKey], RichTextField)?.Text) && (this.dataDoc[this.props.fieldKey + "-lastModified"] = new DateField(new Date(Date.now())));