From 9d9ca5adaa19ff80e6e7f4aab1adccf659c80f47 Mon Sep 17 00:00:00 2001 From: usodhi <61431818+usodhi@users.noreply.github.com> Date: Fri, 26 Jun 2020 16:29:52 +0530 Subject: added GroupManager privacy + setting up group sharing + permissions + group sharing ui --- src/client/util/GroupManager.tsx | 27 ++++++-- src/client/util/SharingManager.scss | 62 +++++++++++------- src/client/util/SharingManager.tsx | 121 +++++++++++++++++++++++++++--------- 3 files changed, 156 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 7f48ca014..fa8da86c1 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -88,7 +88,7 @@ export default class GroupManager extends React.Component<{}> { /** * @returns a list of all group documents. */ - getAllGroups(): Doc[] { + private getAllGroups(): Doc[] { const groupDoc = this.GroupManagerDoc; return groupDoc ? DocListCast(groupDoc.data) : []; } @@ -97,11 +97,31 @@ export default class GroupManager extends React.Component<{}> { * @returns a group document based on the group name. * @param groupName */ - getGroup(groupName: string): Doc | undefined { + private getGroup(groupName: string): Doc | undefined { const groupDoc = this.getAllGroups().find(group => group.groupName === groupName); return groupDoc; } + /** + * @returns a readonly copy of a single group document + */ + 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: (groupName as string), owners: (owners as string), members: (members as string) }) + ); + } + /** * @returns the members of the admin group. */ @@ -194,7 +214,6 @@ export default class GroupManager extends React.Component<{}> { */ @action handleChange = (selectedOptions: any) => { - console.log(selectedOptions); this.selectedUsers = selectedOptions as UserOptions[]; } @@ -312,7 +331,7 @@ export default class GroupManager extends React.Component<{}> {
{group.groupName}
)} diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index dec9f751a..1aff345a0 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -1,13 +1,52 @@ .sharing-interface { display: flex; flex-direction: column; + width: 730px; + + .sharing-contents { + display: flex; + + .individual-container, + .group-container { + width: 50%; + + .share-groups, + .share-individual { + margin-top: 20px; + margin-bottom: 20px; + } + + .groups-list, + .users-list { + font-style: italic; + background: white; + border: 1px solid black; + padding-left: 10px; + padding-right: 10px; + // max-height: 200px; + overflow: scroll; + height: -webkit-fill-available; + text-align: left; + display: flex; + align-content: center; + align-items: center; + text-align: center; + justify-content: center; + color: red; + + // width: 50%; + max-height: 150px; + } + } + } .focus-span { text-decoration: underline; } p { - font-size: 20px; + // font-size: 20px; + font-size: 15px; text-align: left; font-style: italic; padding: 0; @@ -36,28 +75,7 @@ } } - .share-individual { - margin-top: 20px; - margin-bottom: 20px; - } - .users-list { - font-style: italic; - background: white; - border: 1px solid black; - padding-left: 10px; - padding-right: 10px; - max-height: 200px; - overflow: scroll; - height: -webkit-fill-available; - text-align: left; - display: flex; - align-content: center; - align-items: center; - text-align: center; - justify-content: center; - color: red; - } .container { display: block; diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 2e660e819..3d796539c 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -17,6 +17,7 @@ import { SelectionManager } from "./SelectionManager"; import { DocumentManager } from "./DocumentManager"; import { CollectionView } from "../views/collections/CollectionView"; import { DictationOverlay } from "../views/DictationOverlay"; +import GroupManager from "./GroupManager"; library.add(fa.faCopy); @@ -28,7 +29,7 @@ export interface User { export enum SharingPermissions { None = "Not Shared", View = "Can View", - Add = "Can Add and Comment", + Add = "Can Add", Edit = "Can Edit" } @@ -39,6 +40,13 @@ const ColorMapping = new Map([ [SharingPermissions.Edit, "green"] ]); +const HierarchyMapping = new Map([ + [SharingPermissions.None, 0], + [SharingPermissions.View, 1], + [SharingPermissions.Add, 2], + [SharingPermissions.Edit, 3] +]); + const SharingKey = "sharingPermissions"; const PublicKey = "publicLinkPermissions"; const DefaultColor = "black"; @@ -55,6 +63,7 @@ export default class SharingManager extends React.Component<{}> { public static Instance: SharingManager; @observable private isOpen = false; @observable private users: ValidatedUser[] = []; + @observable private groups: Doc[] = []; @observable private targetDoc: Doc | undefined; @observable private targetDocView: DocumentView | undefined; @observable private copied = false; @@ -76,6 +85,8 @@ export default class SharingManager extends React.Component<{}> { this.sharingDoc = new Doc; } })); + + runInAction(() => this.groups = GroupManager.Instance.getAllGroupsCopy()); } public close = action(() => { @@ -121,11 +132,30 @@ export default class SharingManager extends React.Component<{}> { return Promise.all(evaluating); } + setInternalGroupSharing = (group: Doc, permission: string) => { + const members: string[] = JSON.parse(StrCast(group.members)); + const users: ValidatedUser[] = this.users.filter(user => members.includes(user.user.email)); + + const sharingDoc = this.sharingDoc!; + if (permission === SharingPermissions.None) { + const metadata = sharingDoc[group[Id]]; + if (metadata) sharingDoc[group[Id]] = undefined; + } + else { + sharingDoc[group[Id]] = permission; + } + + users.forEach(user => { + this.setInternalSharing(user, permission); + }); + } + setInternalSharing = async (recipient: ValidatedUser, state: string) => { const { user, notificationDoc } = recipient; const target = this.targetDoc!; const manager = this.sharingDoc!; const key = user.userDocumentId; + if (state === SharingPermissions.None) { const metadata = (await DocCastAsync(manager[key])); if (metadata) { @@ -211,15 +241,17 @@ export default class SharingManager extends React.Component<{}> { if (!sharingDoc) { return SharingPermissions.None; } - const metadata = sharingDoc[userKey] as Doc; + const metadata = sharingDoc[userKey] as Doc | string; if (!metadata) { return SharingPermissions.None; } - return StrCast(metadata.permissions, SharingPermissions.None); + return StrCast(metadata instanceof Doc ? metadata.permissions : metadata, SharingPermissions.None); } + private get sharingInterface() { const existOtherUsers = this.users.length > 0; + const existGroups = this.groups.length > 0; return (

Manage the public link to {this.focusOn("this document...")}

@@ -252,31 +284,64 @@ export default class SharingManager extends React.Component<{}> {
-

Privately share {this.focusOn("this document")} with an individual...

-
- {!existOtherUsers ? "There are no other users in your database." : - this.users.map(({ user, notificationDoc }) => { - const userKey = user.userDocumentId; - const permissions = this.computePermissions(userKey); - const color = ColorMapping.get(permissions); - return ( -
- - {user.email} -
- ); - }) - } +
+
+

Privately share {this.focusOn("this document")} with an individual...

+
{/*200*/} + {!existOtherUsers ? "There are no other users in your database." : + this.users.map(({ user, notificationDoc }) => { + const userKey = user.userDocumentId; + const permissions = this.computePermissions(userKey); + const color = ColorMapping.get(permissions); + return ( +
+ + {user.email} +
+ ); + }) + } +
+
+
+

Privately share {this.focusOn("this document")} with a group...

+
{/*200*/} + {!existGroups ? "There are no groups in your database." : + this.groups.map(group => { + const permissions = this.computePermissions(group[Id]); + const color = ColorMapping.get(permissions); + return ( +
+ + {group.groupName} +
+ ); + }) + + } + +
+
Done
-- cgit v1.2.3-70-g09d2