aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/GroupManager.tsx47
-rw-r--r--src/client/util/SharingManager.tsx87
-rw-r--r--src/client/views/DocumentDecorations.tsx6
-rw-r--r--src/client/views/MainViewNotifs.tsx2
4 files changed, 68 insertions, 74 deletions
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 5215ea35f..c750be1c8 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -42,6 +42,7 @@ export default class GroupManager extends React.Component<{}> {
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";
+ private populating: boolean = false;
@@ -62,21 +63,24 @@ export default class GroupManager extends React.Component<{}> {
* Fetches the list of users stored on the database.
*/
populateUsers = async () => {
- runInAction(() => this.users = []);
- const userList = await RequestPromise.get(Utils.prepend("/getUsers"));
- const raw = JSON.parse(userList) as User[];
- const evaluating = raw.map(async user => {
- const userDocument = await DocServer.GetRefField(user.userDocumentId);
- if (userDocument instanceof Doc) {
- const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
- runInAction(() => {
- if (notificationDoc instanceof Doc) {
- this.users.push(user.email);
- }
- });
- }
- });
- return Promise.all(evaluating);
+ if (!this.populating) {
+ this.populating = true;
+ runInAction(() => this.users = []);
+ const userList = await RequestPromise.get(Utils.prepend("/getUsers"));
+ const raw = JSON.parse(userList) as User[];
+ const evaluating = raw.map(async user => {
+ const userDocument = await DocServer.GetRefField(user.userDocumentId);
+ if (userDocument instanceof Doc) {
+ const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
+ runInAction(() => {
+ if (notificationDoc instanceof Doc) {
+ this.users.push(user.email);
+ }
+ });
+ }
+ });
+ return Promise.all(evaluating).then(() => this.populating = false);
+ }
}
/**
@@ -88,7 +92,6 @@ export default class GroupManager extends React.Component<{}> {
const members: string[] = JSON.parse(StrCast(group.members));
if (members.includes(Doc.CurrentUserEmail)) this.currentUserGroups.push(StrCast(group.groupName));
});
-
setGroups(this.currentUserGroups);
});
}
@@ -120,6 +123,7 @@ export default class GroupManager extends React.Component<{}> {
this.currentGroup = undefined;
// this.users = [];
this.createGroupModalOpen = false;
+ TaskCompletionBox.taskCompleted = false;
}
/**
@@ -132,7 +136,6 @@ export default class GroupManager extends React.Component<{}> {
/**
* @returns a list of all group documents.
*/
- // private ?
getAllGroups(): Doc[] {
const groupDoc = this.GroupManagerDoc;
return groupDoc ? DocListCast(groupDoc.data) : [];
@@ -142,7 +145,6 @@ export default class GroupManager extends React.Component<{}> {
* @returns a group document based on the group name.
* @param groupName
*/
- // private?
getGroup(groupName: string): Doc | undefined {
const groupDoc = this.getAllGroups().find(group => group.groupName === groupName);
return groupDoc;
@@ -209,8 +211,6 @@ export default class GroupManager extends React.Component<{}> {
deleteGroup(group: Doc): boolean {
if (group) {
if (this.GroupManagerDoc && this.hasEditAccess(group)) {
- // TODO look at this later
- // SharingManager.Instance.setInternalGroupSharing(group, "Not Shared");
Doc.RemoveDocFromList(this.GroupManagerDoc, "data", group);
SharingManager.Instance.removeGroup(group);
const members: string[] = JSON.parse(StrCast(group.members));
@@ -311,7 +311,9 @@ export default class GroupManager extends React.Component<{}> {
<div className="group-create">
<div className="group-heading" style={{ marginBottom: 0 }}>
<p><b>New Group</b></p>
- <div className={"close-button"} onClick={action(() => this.createGroupModalOpen = false)}>
+ <div className={"close-button"} onClick={action(() => {
+ this.createGroupModalOpen = false; TaskCompletionBox.taskCompleted = false;
+ })}>
<FontAwesomeIcon icon={fa.faTimes} color={"black"} size={"lg"} />
</div>
</div>
@@ -319,6 +321,7 @@ export default class GroupManager extends React.Component<{}> {
className="group-input"
ref={this.inputRef}
onKeyDown={this.handleKeyDown}
+ autoFocus
type="text"
placeholder="Group name"
onChange={action(() => this.buttonColour = this.inputRef.current?.value ? "black" : "#979797")} />
@@ -363,7 +366,7 @@ export default class GroupManager extends React.Component<{}> {
interactive={true}
contents={contents}
dialogueBoxStyle={{ width: "90%", height: "70%" }}
- closeOnExternalClick={action(() => this.createGroupModalOpen = false)}
+ closeOnExternalClick={action(() => { this.createGroupModalOpen = false; TaskCompletionBox.taskCompleted = false; })}
/>
);
}
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 7a0fe4140..a233b08e7 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,7 +1,7 @@
import { observable, runInAction, action } from "mobx";
import * as React from "react";
import MainViewModal from "../views/MainViewModal";
-import { Doc, Opt, DocListCastAsync, AclAdmin, DataSym, AclPrivate } from "../../fields/Doc";
+import { Doc, Opt, AclAdmin, AclPrivate, DocListCast } from "../../fields/Doc";
import { DocServer } from "../DocServer";
import { Cast, StrCast } from "../../fields/Types";
import * as RequestPromise from "request-promise";
@@ -71,6 +71,7 @@ export default class SharingManager extends React.Component<{}> {
// if both showUserOptions and showGroupOptions are false then both are displayed
@observable private showUserOptions: boolean = false; // whether to show individuals as options when sharing (in the react-select component)
@observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component)
+ private populating: boolean = false;
// private get linkVisible() {
// return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
@@ -93,7 +94,7 @@ export default class SharingManager extends React.Component<{}> {
public close = action(() => {
this.isOpen = false;
this.selectedUsers = null; // resets the list of users and seleected users (in the react-select component)
-
+ TaskCompletionBox.taskCompleted = false;
setTimeout(action(() => {
// this.copied = false;
DictationOverlay.Instance.hasActiveModal = false;
@@ -117,24 +118,27 @@ export default class SharingManager extends React.Component<{}> {
* Populates the list of validated users (this.users) by adding registered users which have a rightSidebarCollection.
*/
populateUsers = async () => {
- runInAction(() => this.users = []);
- const userList = await RequestPromise.get(Utils.prepend("/getUsers"));
- const raw = JSON.parse(userList) as User[];
- const evaluating = raw.map(async user => {
- const isCandidate = user.email !== Doc.CurrentUserEmail;
- if (isCandidate) {
- const userDocument = await DocServer.GetRefField(user.userDocumentId);
- if (userDocument instanceof Doc) {
- const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
- runInAction(() => {
- if (notificationDoc instanceof Doc) {
- this.users.push({ user, notificationDoc });
- }
- });
+ if (!this.populating) {
+ this.populating = true;
+ runInAction(() => this.users = []);
+ const userList = await RequestPromise.get(Utils.prepend("/getUsers"));
+ const raw = JSON.parse(userList) as User[];
+ const evaluating = raw.map(async user => {
+ const isCandidate = user.email !== Doc.CurrentUserEmail;
+ if (isCandidate) {
+ const userDocument = await DocServer.GetRefField(user.userDocumentId);
+ if (userDocument instanceof Doc) {
+ const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
+ runInAction(() => {
+ if (notificationDoc instanceof Doc) {
+ this.users.push({ user, notificationDoc });
+ }
+ });
+ }
}
- }
- });
- return Promise.all(evaluating);
+ });
+ return Promise.all(evaluating).then(() => this.populating = false);
+ }
}
/**
@@ -152,13 +156,11 @@ export default class SharingManager extends React.Component<{}> {
target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target);
// if documents have been shared, add the target to that list if it doesn't already exist, otherwise create a new list with the target
- group.docsShared ? DocListCastAsync(group.docsShared).then(resolved => Doc.IndexOf(target, resolved!) === -1 && (group.docsShared as List<Doc>).push(target)) : group.docsShared = new List<Doc>([target]);
+ group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List<Doc>).push(target) : group.docsShared = new List<Doc>([target]);
users.forEach(({ notificationDoc }) => {
- DocListCastAsync(notificationDoc[storage]).then(resolved => {
- if (permission !== SharingPermissions.None) Doc.IndexOf(target, resolved!) === -1 && Doc.AddDocToList(notificationDoc, storage, target); // add the target to the notificationDoc if it hasn't already been added
- else Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists
- });
+ if (permission !== SharingPermissions.None) Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); // add the target to the notificationDoc if it hasn't already been added
+ else Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target); // remove the target from the list if it already exists
});
}
@@ -170,13 +172,7 @@ export default class SharingManager extends React.Component<{}> {
shareWithAddedMember = (group: Doc, emailId: string) => {
const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!;
- if (group.docsShared) {
- DocListCastAsync(group.docsShared).then(docsShared => {
- docsShared?.forEach(doc => {
- DocListCastAsync(user.notificationDoc[storage]).then(resolved => Doc.IndexOf(doc, resolved!) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc)); // add the doc if it isn't already in the list
- });
- });
- }
+ if (group.docsShared) DocListCast(group.docsShared).forEach(doc => Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) === -1 && Doc.AddDocToList(user.notificationDoc, storage, doc));
}
shareFromPropertiesSidebar = (shareWith: string, permission: SharingPermissions, target: Doc) => {
@@ -194,10 +190,8 @@ export default class SharingManager extends React.Component<{}> {
const user: ValidatedUser = this.users.find(({ user: { email } }) => email === emailId)!;
if (group.docsShared) {
- DocListCastAsync(group.docsShared).then(docsShared => {
- docsShared?.forEach(doc => {
- DocListCastAsync(user.notificationDoc[storage]).then(resolved => Doc.IndexOf(doc, resolved!) !== -1 && Doc.RemoveDocFromList(user.notificationDoc, storage, doc)); // remove the doc only if it is in the list
- });
+ DocListCast(group.docsShared).forEach(doc => {
+ Doc.IndexOf(doc, DocListCast(user.notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(user.notificationDoc, storage, doc); // remove the doc only if it is in the list
});
}
}
@@ -208,18 +202,15 @@ export default class SharingManager extends React.Component<{}> {
*/
removeGroup = (group: Doc) => {
if (group.docsShared) {
- DocListCastAsync(group.docsShared).then(resolved => {
- resolved?.forEach(doc => {
- const ACL = `ACL-${StrCast(group.groupName)}`;
+ DocListCast(group.docsShared).forEach(doc => {
+ const ACL = `ACL-${StrCast(group.groupName)}`;
- distributeAcls(ACL, SharingPermissions.None, doc);
+ distributeAcls(ACL, SharingPermissions.None, doc);
- const members: string[] = JSON.parse(StrCast(group.members));
- const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
-
- users.forEach(({ notificationDoc }) => Doc.RemoveDocFromList(notificationDoc, storage, doc));
- });
+ const members: string[] = JSON.parse(StrCast(group.members));
+ const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email));
+ users.forEach(({ notificationDoc }) => Doc.RemoveDocFromList(notificationDoc, storage, doc));
});
}
}
@@ -233,14 +224,10 @@ export default class SharingManager extends React.Component<{}> {
target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target);
if (permission !== SharingPermissions.None) {
- DocListCastAsync(notificationDoc[storage]).then(resolved => {
- Doc.IndexOf(target, resolved!) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
- });
+ Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
}
else {
- DocListCastAsync(notificationDoc[storage]).then(resolved => {
- Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
- });
+ Doc.IndexOf(target, DocListCast(notificationDoc[storage])) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
}
}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index f16cb273b..8dcba27e4 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -588,7 +588,11 @@ 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.ContainingCollectionDoc)).some(permission => permission === AclAdmin || permission === AclEdit);
+ 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 minimal = bounds.r - bounds.x < 100 ? true : false;
const maximizeIcon = minimal ? (
<Tooltip title={<><div className="dash-tooltip">Show context menu</div></>} placement="top">
diff --git a/src/client/views/MainViewNotifs.tsx b/src/client/views/MainViewNotifs.tsx
index 05f890485..041d7301f 100644
--- a/src/client/views/MainViewNotifs.tsx
+++ b/src/client/views/MainViewNotifs.tsx
@@ -23,7 +23,7 @@ export class MainViewNotifs extends React.Component {
const notifsRef = React.createRef<HTMLDivElement>();
const dragNotifs = action(() => MainViewNotifs.NotifsCol!);
return <div className="mainNotifs-container" ref={notifsRef}>
- <button className="mainNotifs-badge" style={length > 0 ? { "display": "initial" } : { "display": "none" }}
+ <button className="mainNotifs-badge" style={{ display: length > 0 ? "initial" : "none" }}
onClick={this.openNotifsCol} onPointerDown={MainViewNotifs.NotifsCol ? SetupDrag(notifsRef, dragNotifs) : emptyFunction}>
{length}
</button>