diff options
author | Tyler Schicke <tyler_schicke@brown.edu> | 2019-06-17 23:04:07 -0400 |
---|---|---|
committer | Tyler Schicke <tyler_schicke@brown.edu> | 2019-06-17 23:04:07 -0400 |
commit | 8c64ffd92e382050bc8727981cf9fb830e4f02a7 (patch) | |
tree | ddee69fbea574065241deb0e72f194ac64930526 /src | |
parent | df05220570628c0f6f1f97329cd3719bb232ecd2 (diff) |
Added share with user functionality
Diffstat (limited to 'src')
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 48 | ||||
-rw-r--r-- | src/client/views/nodes/FieldView.tsx | 2 | ||||
-rw-r--r-- | src/server/RouteStore.ts | 1 | ||||
-rw-r--r-- | src/server/database.ts | 4 | ||||
-rw-r--r-- | src/server/index.ts | 11 |
5 files changed, 52 insertions, 14 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9d0206e48..942228e71 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,11 +1,11 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons'; -import { action, computed, IReactionDisposer, reaction, trace, observable } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; -import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, Utils } from "../../../Utils"; @@ -26,10 +26,12 @@ import { DocComponent } from "../DocComponent"; import { PresentationView } from "../PresentationView"; import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; +import * as rp from "request-promise"; import "./DocumentView.scss"; import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { ContextMenuProps } from '../ContextMenuItem'; +import { RouteStore } from '../../../server/RouteStore'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); @@ -452,7 +454,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } @action - onContextMenu = (e: React.MouseEvent): void => { + onContextMenu = async (e: React.MouseEvent): Promise<void> => { + e.persist(); e.stopPropagation(); if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 || e.isDefaultPrevented()) { @@ -483,14 +486,37 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); - if (!this.topMost) { - // DocumentViews should stop propagation of this event - e.stopPropagation(); - } - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!SelectionManager.IsSelected(this)) { - SelectionManager.SelectDoc(this, false); - } + type User = { email: string, userDocumentId: string }; + const users: User[] = JSON.parse(await rp.get(DocServer.prepend(RouteStore.getUsers))); + let usersMenu: ContextMenuProps[] = users.filter(({ email }) => email !== CurrentUserUtils.email).map(({ email, userDocumentId }) => ({ + description: email, event: async () => { + const userDocument = await Cast(DocServer.GetRefField(userDocumentId), Doc); + if (!userDocument) { + throw new Error(`Couldn't get user document of user ${email}`); + } + const notifDoc = await Cast(userDocument.optionalRightCollection, Doc); + if (notifDoc instanceof Doc) { + const data = await Cast(notifDoc.data, listSpec(Doc)); + const sharedDoc = Doc.MakeAlias(this.props.Document); + if (data) { + data.push(sharedDoc); + } else { + notifDoc.data = new List([sharedDoc]); + } + } + } + })); + runInAction(() => { + cm.addItem({ description: "Share...", subitems: usersMenu }); + if (!this.topMost) { + // DocumentViews should stop propagation of this event + e.stopPropagation(); + } + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + if (!SelectionManager.IsSelected(this)) { + SelectionManager.SelectDoc(this, false); + } + }); } onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index cf6d2012f..4738e90d7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -109,7 +109,7 @@ export class FieldView extends React.Component<FieldViewProps> { } else if (field instanceof List) { return (<div> - {field.map(f => f instanceof Doc ? f.title : f.toString()).join(", ")} + {field.map(f => f instanceof Doc ? f.title : (f && f.toString && f.toString())).join(", ")} </div>); } // bcz: this belongs here, but it doesn't render well so taking it out for now diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts index c4af5cdaa..5c13495ff 100644 --- a/src/server/RouteStore.ts +++ b/src/server/RouteStore.ts @@ -16,6 +16,7 @@ export enum RouteStore { // USER AND WORKSPACES getCurrUser = "/getCurrentUser", + getUsers = "/getUsers", getUserDocumentId = "/getUserDocumentId", updateCursor = "/updateCursor", diff --git a/src/server/database.ts b/src/server/database.ts index 70b3efced..d240bd909 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -120,9 +120,9 @@ export class Database { } } - public query(query: any): Promise<mongodb.Cursor> { + public query(query: any, collectionName = "newDocuments"): Promise<mongodb.Cursor> { if (this.db) { - return Promise.resolve<mongodb.Cursor>(this.db.collection('newDocuments').find(query)); + return Promise.resolve<mongodb.Cursor>(this.db.collection(collectionName).find(query)); } else { return new Promise<mongodb.Cursor>(res => { this.onConnect.push(() => res(this.query(query))); diff --git a/src/server/index.ts b/src/server/index.ts index b91c91282..7ef542b01 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -205,6 +205,17 @@ addSecureRoute( addSecureRoute( Method.GET, + async (_, res) => { + const cursor = await Database.Instance.query({}, "users"); + const results = await cursor.toArray(); + res.send(results.map(user => ({ email: user.email, userDocumentId: user.userDocumentId }))); + }, + undefined, + RouteStore.getUsers +); + +addSecureRoute( + Method.GET, (user, res, req) => { let detector = new mobileDetect(req.headers['user-agent'] || ""); let filename = detector.mobile() !== null ? 'mobile/image.html' : 'index.html'; |