diff options
Diffstat (limited to 'src/client/util/SharingManager.tsx')
-rw-r--r-- | src/client/util/SharingManager.tsx | 97 |
1 files changed, 36 insertions, 61 deletions
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 895bd3374..3c05af4bb 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -5,9 +5,10 @@ import { observer } from 'mobx-react'; import * as React from 'react'; import Select from 'react-select'; import * as RequestPromise from 'request-promise'; -import { AclAugment, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, AclUnset, DataSym, Doc, DocListCast, DocListCastAsync, Opt, AclSelfEdit } from '../../fields/Doc'; +import { AclAdmin, AclPrivate, AclSym, AclUnset, DataSym, Doc, DocListCast, DocListCastAsync, HierarchyMapping, Opt } from '../../fields/Doc'; +import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; -import { Cast, NumCast, StrCast } from '../../fields/Types'; +import { Cast, NumCast, PromiseValue, StrCast } from '../../fields/Types'; import { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from '../../fields/util'; import { Utils } from '../../Utils'; import { DocServer } from '../DocServer'; @@ -20,10 +21,9 @@ import { SearchBox } from '../views/search/SearchBox'; import { DocumentManager } from './DocumentManager'; import { GroupManager, UserOptions } from './GroupManager'; import { GroupMemberView } from './GroupMemberView'; +import { LinkManager } from './LinkManager'; import { SelectionManager } from './SelectionManager'; import './SharingManager.scss'; -import { LinkManager } from './LinkManager'; -import { Id } from '../../fields/FieldSymbols'; export interface User { email: string; @@ -82,16 +82,6 @@ export class SharingManager extends React.Component<{}> { @observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used @observable private myDocAcls: boolean = false; // whether the My Docs checkbox is selected or not - // maps acl symbols to SharingPermissions - private AclMap = new Map<symbol, string>([ - [AclPrivate, SharingPermissions.None], - [AclReadonly, SharingPermissions.View], - [AclAugment, SharingPermissions.Augment], - [AclSelfEdit, SharingPermissions.SelfEdit], - [AclEdit, SharingPermissions.Edit], - [AclAdmin, SharingPermissions.Admin], - ]); - // private get linkVisible() { // return this.targetDoc ? this.targetDoc["acl-" + PublicKey] !== SharingPermissions.None : false; // } @@ -140,35 +130,21 @@ export class SharingManager extends React.Component<{}> { if (!this.populating && Doc.UserDoc()[Id] !== '__guest__') { this.populating = true; const userList = await RequestPromise.get(Utils.prepend('/getUsers')); - const raw = JSON.parse(userList) as User[]; - const sharingDocs: ValidatedUser[] = []; - const evaluating = raw.map(async user => { - const isCandidate = user.email !== Doc.CurrentUserEmail; - if (isCandidate) { - const sharingDoc = await DocServer.GetRefField(user.sharingDocumentId); - const linkDatabase = await DocServer.GetRefField(user.linkDatabaseId); + const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== Doc.CurrentUserEmail); + const docs = await DocServer.GetRefFields(raw.reduce((list, user) => [...list, user.sharingDocumentId, user.linkDatabaseId], [] as string[])); + raw.map( + action((newUser: User) => { + const sharingDoc = docs[newUser.sharingDocumentId]; + const linkDatabase = docs[newUser.linkDatabaseId]; if (sharingDoc instanceof Doc && linkDatabase instanceof Doc) { - await DocListCastAsync(linkDatabase.data); - (await DocListCastAsync(Cast(linkDatabase, Doc, null).data))?.forEach(async link => { - // makes sure link anchors are loaded to avoid incremental updates to computedFns in LinkManager - const a1 = await Cast(link?.anchor1, Doc, null); - const a2 = await Cast(link?.anchor2, Doc, null); - }); - sharingDocs.push({ user, sharingDoc, linkDatabase, userColor: StrCast(sharingDoc.userColor) }); - } - } - }); - return Promise.all(evaluating).then(() => { - runInAction(async () => { - for (const sharer of sharingDocs) { - if (!this.users.find(user => user.user.email === sharer.user.email)) { - this.users.push(sharer); - LinkManager.addLinkDB(sharer.linkDatabase); + if (!this.users.find(user => user.user.email === newUser.email)) { + this.users.push({ user: newUser, sharingDoc, linkDatabase, userColor: StrCast(sharingDoc.userColor) }); + // LinkManager.addLinkDB(sharer.linkDatabase); } } - }); - this.populating = false; - }); + }) + ); + this.populating = false; } }; @@ -184,6 +160,7 @@ export class SharingManager extends React.Component<{}> { const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); return !docs + .map(doc => (this.layoutDocAcls ? doc : doc[DataSym])) .map(doc => { doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc, undefined, undefined, isDashboard); @@ -217,6 +194,7 @@ export class SharingManager extends React.Component<{}> { // ! ensures it returns true if document has been shared successfully, false otherwise return !docs + .map(doc => (this.layoutDocAcls ? doc : doc[DataSym])) .map(doc => { doc.author === Doc.CurrentUserEmail && !doc[`acl-${Doc.CurrentUserEmailNormalized}`] && distributeAcls(`acl-${Doc.CurrentUserEmailNormalized}`, SharingPermissions.Admin, doc, undefined, undefined, isDashboard); @@ -283,6 +261,7 @@ export class SharingManager extends React.Component<{}> { docs.forEach(doc => { const isDashboard = dashboards.indexOf(doc) !== -1; if (GetEffectiveAcl(doc) === AclAdmin) distributeAcls(`acl-${shareWith}`, permission, doc, undefined, undefined, isDashboard); + this.setDashboardBackground(doc, permission as SharingPermissions); }); } }; @@ -290,14 +269,18 @@ export class SharingManager extends React.Component<{}> { /** * Sets the background of the Dashboard if it has been shared as a visual indicator */ - setDashboardBackground = async (doc: Doc, permission: SharingPermissions) => { + setDashboardBackground = (doc: Doc, permission: SharingPermissions) => { if (Doc.IndexOf(doc, DocListCast(Doc.MyDashboards.data)) !== -1) { if (permission !== SharingPermissions.None) { doc.isShared = true; doc.backgroundColor = 'green'; } else { const acls = doc[DataSym][AclSym]; - if (Object.keys(acls).every(key => (key === `acl-${Doc.CurrentUserEmailNormalized}` ? true : [AclUnset, AclPrivate].includes(acls[key])))) { + if ( + Object.keys(acls) + .filter(key => key !== `acl-${Doc.CurrentUserEmailNormalized}` && key !== 'acl-Me') + .every(key => [AclUnset, AclPrivate].includes(acls[key])) + ) { doc.isShared = undefined; doc.backgroundColor = undefined; } @@ -372,9 +355,9 @@ export class SharingManager extends React.Component<{}> { private sharingOptions(uniform: boolean, override?: boolean) { const dropdownValues: string[] = Object.values(SharingPermissions); if (!uniform) dropdownValues.unshift('-multiple-'); - if (override) dropdownValues.unshift('None'); + if (!override) dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1); return dropdownValues - .filter(permission => !Doc.noviceMode || ![SharingPermissions.View, SharingPermissions.SelfEdit].includes(permission as any)) + .filter(permission => !Doc.noviceMode || ![SharingPermissions.SelfEdit].includes(permission as any)) .map(permission => ( <option key={permission} value={permission}> {permission} @@ -392,7 +375,7 @@ export class SharingManager extends React.Component<{}> { onClick={() => { let context: Opt<CollectionView>; if (this.targetDoc && this.targetDocView && docs.length === 1 && (context = this.targetDocView.props.ContainingCollectionView)) { - DocumentManager.Instance.jumpToDocument(this.targetDoc, true, undefined, [context.props.Document]); + DocumentManager.Instance.showDocument(this.targetDoc, { willZoomCentered: true }); } }} onPointerEnter={action(() => { @@ -458,17 +441,6 @@ export class SharingManager extends React.Component<{}> { } }; - // distributeOverCollection = (targetDoc?: Doc) => { - // const target = targetDoc || this.targetDoc!; - - // const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); - // docs.forEach(doc => { - // for (const [key, value] of Object.entries(doc[AclSym])) { - // distributeAcls(key, this.AclMap.get(value)! as SharingPermissions, target); - // } - // }); - // } - /** * Sorting algorithm to sort users. */ @@ -491,6 +463,7 @@ export class SharingManager extends React.Component<{}> { * @returns the main interface of the SharingManager. */ @computed get sharingInterface() { + if (!this.targetDoc) return null; TraceMobx(); const groupList = GroupManager.Instance?.allGroups || []; const sortedUsers = this.users @@ -523,21 +496,21 @@ export class SharingManager extends React.Component<{}> { docs = newDocs.filter(doc => GetEffectiveAcl(doc) === AclAdmin); } - const targetDoc = docs[0]; + const targetDoc = this.layoutDocAcls ? docs[0] : docs[0]?.[DataSym]; // tslint:disable-next-line: no-unnecessary-callback-wrapper const effectiveAcls = docs.map(doc => GetEffectiveAcl(doc)); const admin = this.myDocAcls ? Boolean(docs.length) : effectiveAcls.every(acl => acl === AclAdmin); // users in common between all docs - const commonKeys = intersection(...docs.map(doc => (this.layoutDocAcls ? doc?.[AclSym] && Object.keys(doc[AclSym]) : doc?.[DataSym]?.[AclSym] && Object.keys(doc[DataSym][AclSym])))); + const commonKeys = intersection(...docs.map(doc => (this.layoutDocAcls ? doc : doc[DataSym])).map(doc => doc?.[AclSym] && Object.keys(doc[AclSym]))); // the list of users shared with const userListContents: (JSX.Element | null)[] = users .filter(({ user }) => (docs.length > 1 ? commonKeys.includes(`acl-${normalizeEmail(user.email)}`) : docs[0]?.author !== user.email)) .map(({ user, linkDatabase, sharingDoc, userColor }) => { const userKey = `acl-${normalizeEmail(user.email)}`; - const uniform = docs.every(doc => (this.layoutDocAcls ? doc?.[AclSym]?.[userKey] === docs[0]?.[AclSym]?.[userKey] : doc?.[DataSym]?.[AclSym]?.[userKey] === docs[0]?.[DataSym]?.[AclSym]?.[userKey])); + const uniform = docs.map(doc => (this.layoutDocAcls ? doc : doc[DataSym])).every(doc => doc?.[AclSym]?.[userKey] === docs[0]?.[AclSym]?.[userKey]); const permissions = uniform ? StrCast(targetDoc?.[userKey]) : '-multiple-'; return !permissions ? null : ( @@ -573,7 +546,7 @@ export class SharingManager extends React.Component<{}> { <div key={'me'} className={'container'}> <span className={'padding'}>Me</span> <div className="edit-actions"> - <div className={'permissions-dropdown'}>{effectiveAcls.every(acl => acl === effectiveAcls[0]) ? this.AclMap.get(effectiveAcls[0])! : '-multiple-'}</div> + <div className={'permissions-dropdown'}>{effectiveAcls.every(acl => acl === effectiveAcls[0]) ? HierarchyMapping.get(effectiveAcls[0])!.name : '-multiple-'}</div> </div> </div> ) : null @@ -584,7 +557,9 @@ export class SharingManager extends React.Component<{}> { groupListMap.unshift({ title: 'Public' }); //, { title: "ALL" }); const groupListContents = groupListMap.map(group => { const groupKey = `acl-${StrCast(group.title)}`; - const uniform = docs.every(doc => (this.layoutDocAcls ? doc?.[AclSym]?.[groupKey] === docs[0]?.[AclSym]?.[groupKey] : doc?.[DataSym]?.[AclSym]?.[groupKey] === docs[0]?.[DataSym]?.[AclSym]?.[groupKey])); + const uniform = docs + .map(doc => (this.layoutDocAcls ? doc : doc[DataSym])) + .every(doc => (this.layoutDocAcls ? doc?.[AclSym]?.[groupKey] === docs[0]?.[AclSym]?.[groupKey] : doc?.[DataSym]?.[AclSym]?.[groupKey] === docs[0]?.[DataSym]?.[AclSym]?.[groupKey])); const permissions = uniform ? StrCast(targetDoc?.[`acl-${StrCast(group.title)}`]) : '-multiple-'; return !permissions ? null : ( |