From b3991f16b8e91bc19b5df5430efe3a71b9ad2ac7 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 3 Aug 2020 10:19:25 +0530 Subject: prevented repopulating users while populating users --- src/client/util/SharingManager.tsx | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'src/client/util/SharingManager.tsx') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 892fb6d6d..6393170fa 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -71,8 +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; @@ -119,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); + } } /** -- cgit v1.2.3-70-g09d2 From d83959572d55510755f9d6b9e0b456b4b1ad5148 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 3 Aug 2020 11:33:49 +0530 Subject: popup fades on close --- src/client/util/GroupManager.tsx | 11 +++++------ src/client/util/SharingManager.tsx | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src/client/util/SharingManager.tsx') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 448e5dc54..b13d8cf5f 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -124,6 +124,7 @@ export default class GroupManager extends React.Component<{}> { this.currentGroup = undefined; // this.users = []; this.createGroupModalOpen = false; + TaskCompletionBox.taskCompleted = false; } /** @@ -136,7 +137,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) : []; @@ -146,7 +146,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; @@ -213,8 +212,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)); @@ -315,7 +312,9 @@ export default class GroupManager extends React.Component<{}> {

New Group

-
this.createGroupModalOpen = false)}> +
{ + this.createGroupModalOpen = false; TaskCompletionBox.taskCompleted = false; + })}>
@@ -367,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 a3c0a88fa..d2891a772 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -94,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; -- cgit v1.2.3-70-g09d2 From 2331b3a271cc53390d281fa16a553467a3d7a7de Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Mon, 3 Aug 2020 19:21:40 +0530 Subject: minor changes --- src/client/util/GroupManager.tsx | 2 +- src/client/util/SharingManager.tsx | 47 ++++++++++++-------------------------- 2 files changed, 16 insertions(+), 33 deletions(-) (limited to 'src/client/util/SharingManager.tsx') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index b13d8cf5f..c750be1c8 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -92,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); }); } @@ -322,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")} /> diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index d2891a772..30bed9cb9 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"; @@ -156,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).push(target)) : group.docsShared = new List([target]); + group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List).push(target) : group.docsShared = new List([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 }); } @@ -174,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)); } /** @@ -192,10 +184,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 }); } } @@ -206,18 +196,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)}`; - - distributeAcls(ACL, SharingPermissions.None, doc); + DocListCast(group.docsShared).forEach(doc => { + const ACL = `ACL-${StrCast(group.groupName)}`; - const members: string[] = JSON.parse(StrCast(group.members)); - const users: ValidatedUser[] = this.users.filter(({ user: { email } }) => members.includes(email)); + distributeAcls(ACL, SharingPermissions.None, doc); - 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)); }); } } @@ -231,14 +218,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); } } -- cgit v1.2.3-70-g09d2 From 13c85ceb6637e5dbecbc1a9be3dd5915b3e4b95d Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Tue, 4 Aug 2020 17:32:13 +0530 Subject: owner's acl set when sharing menu opened --- src/client/util/SharingManager.tsx | 7 +++++-- src/client/views/DocComponent.tsx | 11 +++++------ 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/client/util/SharingManager.tsx') diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index adfc8c2bf..97f94692d 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -88,7 +88,7 @@ export default class SharingManager extends React.Component<{}> { this.isOpen = true; this.permissions = SharingPermissions.Edit; }); - + this.targetDoc!.author === Doc.CurrentUserEmail && !this.targetDoc![`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`] && distributeAcls(`ACL-${Doc.CurrentUserEmail.replace(".", "_")}`, SharingPermissions.Admin, this.targetDoc!); } public close = action(() => { @@ -221,7 +221,10 @@ export default class SharingManager extends React.Component<{}> { const key = user.email.replace('.', '_'); const ACL = `ACL-${key}`; - target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); + + if (target.author === Doc.CurrentUserEmail) { + distributeAcls(ACL, permission as SharingPermissions, target); + } if (permission !== SharingPermissions.None) { Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 34144d3eb..831c246d1 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -1,4 +1,4 @@ -import { Doc, Opt, DataSym, AclReadonly, AclAddonly, AclPrivate, AclEdit, AclSym, DocListCastAsync, DocListCast } from '../../fields/Doc'; +import { Doc, Opt, DataSym, AclReadonly, AclAddonly, AclPrivate, AclEdit, AclSym, DocListCastAsync, DocListCast, AclAdmin } from '../../fields/Doc'; import { Touchable } from './Touchable'; import { computed, action, observable } from 'mobx'; import { Cast, BoolCast, ScriptCast } from '../../fields/Types'; @@ -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, SharingPermissions } from '../../fields/util'; +import { GetEffectiveAcl, SharingPermissions, distributeAcls } from '../../fields/util'; /// DocComponent returns a generic React base class used by views that don't have 'fieldKey' props (e.g.,CollectionFreeFormDocumentView, DocumentView) @@ -96,7 +96,8 @@ export function ViewBoxAnnotatableComponent

ScriptCast((this.layoutDoc as any).lookupField)?.script.run({ self: this.layoutDoc, data: this.rootDoc, field: field }).result; @@ -156,10 +157,8 @@ 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); + distributeAcls(key, this.AclMap.get(value) as SharingPermissions, d, true); } }); } -- cgit v1.2.3-70-g09d2 From 0566852022c17a12d521ebf1f280f748fe34c602 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Wed, 5 Aug 2020 10:00:57 +0530 Subject: comments + carets --- src/client/util/GroupManager.scss | 1 + src/client/util/GroupManager.tsx | 7 +++-- src/client/util/SharingManager.scss | 1 + src/client/util/SharingManager.tsx | 58 +++++++++++++++++++++++++++++-------- 4 files changed, 53 insertions(+), 14 deletions(-) (limited to 'src/client/util/SharingManager.tsx') diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss index 51e4fa9e2..9438bdd72 100644 --- a/src/client/util/GroupManager.scss +++ b/src/client/util/GroupManager.scss @@ -92,6 +92,7 @@ .sort-groups { text-align: left; margin-left: 5; + width: 50px; cursor: pointer; } diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 45c26d87a..277e96a89 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -18,7 +18,7 @@ import { setGroups } from "../../fields/util"; import { DocServer } from "../DocServer"; import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox"; -library.add(fa.faPlus, fa.faTimes, fa.faInfoCircle); +library.add(fa.faPlus, fa.faTimes, fa.faInfoCircle, fa.faCaretUp, fa.faCaretRight, fa.faCaretDown); /** * Interface for options for the react-select component @@ -408,7 +408,10 @@ 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.scss b/src/client/util/SharingManager.scss index 8da80ef52..7912db74d 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -84,6 +84,7 @@ .user-sort { text-align: left; margin-left: 10; + width: 100px; cursor: pointer; } diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 97f94692d..d50a132f8 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -21,6 +21,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { List } from "../../fields/List"; import { distributeAcls, SharingPermissions, GetEffectiveAcl } from "../../fields/util"; import { TaskCompletionBox } from "../views/nodes/TaskCompletedBox"; +import { library } from "@fortawesome/fontawesome-svg-core"; + +library.add(fa.faInfoCircle, fa.faCaretUp, fa.faCaretRight, fa.faCaretDown); + export interface User { email: string; @@ -215,6 +219,9 @@ export default class SharingManager extends React.Component<{}> { } } + /** + * Shares the document with a user. + */ setInternalSharing = (recipient: ValidatedUser, permission: string, targetDoc?: Doc) => { const { user, notificationDoc } = recipient; const target = targetDoc || this.targetDoc!; @@ -222,9 +229,7 @@ export default class SharingManager extends React.Component<{}> { const ACL = `ACL-${key}`; - if (target.author === Doc.CurrentUserEmail) { - distributeAcls(ACL, permission as SharingPermissions, target); - } + target.author === Doc.CurrentUserEmail && distributeAcls(ACL, permission as SharingPermissions, target); if (permission !== SharingPermissions.None) { Doc.IndexOf(target, DocListCast(notificationDoc[storage])) === -1 && Doc.AddDocToList(notificationDoc, storage, target); @@ -258,14 +263,17 @@ export default class SharingManager extends React.Component<{}> { // } // }); + /** + * Returns the SharingPermissions (Admin, Can Edit etc) access that's used to share + */ private get sharingOptions() { - return Object.values(SharingPermissions).map(permission => { - return ( - - ); - }); + ) + ); } private focusOn = (contents: string) => { @@ -298,16 +306,25 @@ export default class SharingManager extends React.Component<{}> { ); } + /** + * Handles changes in the users selected in react-select + */ @action handleUsersChange = (selectedOptions: any) => { this.selectedUsers = selectedOptions as UserOptions[]; } + /** + * Handles changes in the permission chosen to share with someone with + */ @action handlePermissionsChange = (event: React.ChangeEvent) => { this.permissions = event.currentTarget.value as SharingPermissions; } + /** + * Calls the relevant method for sharing, displays the popup, and resets the relevant variables. + */ @action share = () => { if (this.selectedUsers) { @@ -331,18 +348,27 @@ export default class SharingManager extends React.Component<{}> { } } + /** + * Sorting algorithm to sort users. + */ sortUsers = (u1: ValidatedUser, u2: ValidatedUser) => { const { email: e1 } = u1.user; const { email: e2 } = u2.user; return e1 < e2 ? -1 : e1 === e2 ? 0 : 1; } + /** + * Sorting algorithm to sort groups. + */ sortGroups = (group1: Doc, group2: Doc) => { const g1 = StrCast(group1.groupName); const g2 = StrCast(group2.groupName); return g1 < g2 ? -1 : g1 === g2 ? 0 : 1; } + /** + * @returns the main interface of the SharingManager. + */ private get sharingInterface() { const groupList = GroupManager.Instance?.getAllGroups() || []; @@ -351,8 +377,8 @@ export default class SharingManager extends React.Component<{}> { const sortedGroups = groupList.slice().sort(this.sortGroups) .map(({ groupName }) => ({ label: StrCast(groupName), value: groupType + StrCast(groupName) })); + // the next block handles the users shown (individuals/groups/both) const options: GroupedOptions[] = []; - if (GroupManager.Instance) { if ((this.showUserOptions && this.showGroupOptions) || (!this.showUserOptions && !this.showGroupOptions)) { options.push({ @@ -383,6 +409,7 @@ export default class SharingManager extends React.Component<{}> { const effectiveAcl = this.targetDoc ? GetEffectiveAcl(this.targetDoc) : AclPrivate; + // the list of users shared with const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { const userKey = user.email.replace('.', '_'); const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`]); @@ -412,6 +439,7 @@ export default class SharingManager extends React.Component<{}> { ); }); + // the owner of the doc and the current user are placed at the top of the user list. userListContents.unshift( (
{ ) : null ); + // the list of groups shared with const groupListContents = groups.map(group => { const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`]); @@ -467,6 +496,7 @@ export default class SharingManager extends React.Component<{}> { ); }); + // don't display the group list if all groups are null const displayGroupList = !groupListContents?.every(group => group === null); return ( @@ -528,7 +558,7 @@ export default class SharingManager extends React.Component<{}> { }) }} /> - {this.sharingOptions}