import { observable, runInAction, action } from "mobx"; import * as React from "react"; import MainViewModal from "../views/MainViewModal"; import { Doc, Opt, DocCastAsync } from "../../new_fields/Doc"; import { DocServer } from "../DocServer"; import { Cast, StrCast } from "../../new_fields/Types"; import * as RequestPromise from "request-promise"; import { Utils } from "../../Utils"; import "./SharingManager.scss"; import { Id } from "../../new_fields/FieldSymbols"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { library } from '@fortawesome/fontawesome-svg-core'; import * as fa from '@fortawesome/free-solid-svg-icons'; import { DocumentView } from "../views/nodes/DocumentView"; import { SelectionManager } from "./SelectionManager"; import { DocumentManager } from "./DocumentManager"; import { CollectionView } from "../views/collections/CollectionView"; import { DictationOverlay } from "../views/DictationOverlay"; library.add(fa.faCopy); export interface User { email: string; userDocumentId: string; } export enum SharingPermissions { None = "Not Shared", View = "Can View", Comment = "Can Comment", Edit = "Can Edit" } const ColorMapping = new Map([ [SharingPermissions.None, "red"], [SharingPermissions.View, "maroon"], [SharingPermissions.Comment, "blue"], [SharingPermissions.Edit, "green"] ]); const SharingKey = "sharingPermissions"; const PublicKey = "publicLinkPermissions"; const DefaultColor = "black"; interface ValidatedUser { user: User; notificationDoc: Doc; } const storage = "data"; @observer export default class SharingManager extends React.Component<{}> { public static Instance: SharingManager; @observable private isOpen = false; @observable private users: ValidatedUser[] = []; @observable private targetDoc: Doc | undefined; @observable private targetDocView: DocumentView | undefined; @observable private copied = false; @observable private dialogueBoxOpacity = 1; @observable private overlayOpacity = 0.4; private get linkVisible() { return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false; } public open = (target: DocumentView) => { SelectionManager.DeselectAll(); this.populateUsers().then(action(() => { this.targetDocView = target; this.targetDoc = target.props.Document; DictationOverlay.Instance.hasActiveModal = true; this.isOpen = true; if (!this.sharingDoc) { this.sharingDoc = new Doc; } })); } public close = action(() => { this.isOpen = false; this.users = []; setTimeout(action(() => { this.copied = false; DictationOverlay.Instance.hasActiveModal = false; this.targetDoc = undefined; }), 500); }); private get sharingDoc() { return this.targetDoc ? Cast(this.targetDoc[SharingKey], Doc) as Doc : undefined; } private set sharingDoc(value: Doc | undefined) { this.targetDoc && (this.targetDoc[SharingKey] = value); } constructor(props: {}) { super(props); SharingManager.Instance = this; } populateUsers = async () => { 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.optionalRightCollection, Doc); runInAction(() => { if (notificationDoc instanceof Doc) { this.users.push({ user, notificationDoc }); } }); } } }); return Promise.all(evaluating); } 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) { const sharedAlias = (await DocCastAsync(metadata.sharedAlias))!; Doc.RemoveDocFromList(notificationDoc, storage, sharedAlias); manager[key] = undefined; } } else { const sharedAlias = Doc.MakeAlias(target); Doc.AddDocToList(notificationDoc, storage, sharedAlias); const metadata = new Doc; metadata.permissions = state; metadata.sharedAlias = sharedAlias; manager[key] = metadata; } } private setExternalSharing = (state: string) => { const sharingDoc = this.sharingDoc; if (!sharingDoc) { return; } sharingDoc[PublicKey] = state; } private get sharingUrl() { if (!this.targetDoc) { return undefined; } const baseUrl = Utils.prepend("/doc/" + this.targetDoc[Id]); return `${baseUrl}?sharing=true`; } copy = action(() => { if (this.sharingUrl) { Utils.CopyText(this.sharingUrl); this.copied = true; } }); private get sharingOptions() { return Object.values(SharingPermissions).map(permission => { return ( ); }); } private focusOn = (contents: string) => { const title = this.targetDoc ? StrCast(this.targetDoc.title) : ""; return ( { let context: Opt; if (this.targetDoc && this.targetDocView && (context = this.targetDocView.props.ContainingCollectionView)) { DocumentManager.Instance.jumpToDocument(this.targetDoc, true, undefined, context.props.Document); } }} onPointerEnter={action(() => { if (this.targetDoc) { Doc.BrushDoc(this.targetDoc); this.dialogueBoxOpacity = 0.1; this.overlayOpacity = 0.1; } })} onPointerLeave={action(() => { this.targetDoc && Doc.UnBrushDoc(this.targetDoc); this.dialogueBoxOpacity = 1; this.overlayOpacity = 0.4; })} > {contents} ); } private computePermissions = (userKey: string) => { const sharingDoc = this.sharingDoc; if (!sharingDoc) { return SharingPermissions.None; } const metadata = sharingDoc[userKey] as Doc; if (!metadata) { return SharingPermissions.None; } return StrCast(metadata.permissions, SharingPermissions.None); } private get sharingInterface() { const existOtherUsers = this.users.length > 0; return (

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

{!this.linkVisible ? (null) :
{this.sharingUrl}
}
{!this.linkVisible ? (null) :

People with this link

}

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}
); }) }
Done
); } render() { return ( ); } }