diff options
-rw-r--r-- | src/client/documents/Documents.ts | 2 | ||||
-rw-r--r-- | src/client/util/SharingManager.scss | 5 | ||||
-rw-r--r-- | src/client/util/SharingManager.tsx | 120 | ||||
-rw-r--r-- | src/client/views/DocComponent.tsx | 10 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.scss | 3 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 6 | ||||
-rw-r--r-- | src/client/views/Main.tsx | 2 | ||||
-rw-r--r-- | src/client/views/MarqueeAnnotator.tsx | 4 | ||||
-rw-r--r-- | src/client/views/PropertiesView.scss | 4 | ||||
-rw-r--r-- | src/client/views/PropertiesView.tsx | 93 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/FormattedTextBox.tsx | 9 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts | 12 | ||||
-rw-r--r-- | src/fields/Doc.ts | 3 | ||||
-rw-r--r-- | src/fields/util.ts | 6 |
14 files changed, 81 insertions, 198 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index f5510d7e1..9c67f1f37 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -506,7 +506,7 @@ export namespace Docs { description: '', showCaption: 'description', backgroundColor: 'lightblue', // lightblue is default color for linking dot and link documents text comment area - _removeDropProperties: new List(['isLinkButton']), + // _removeDropsties: new List(['isLinkButton']), }, }, ], diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss index f47c48805..3cab77816 100644 --- a/src/client/util/SharingManager.scss +++ b/src/client/util/SharingManager.scss @@ -23,6 +23,11 @@ z-index: 999; } + .share-title { + display: inline-flex; + gap: 5px; + } + .share-container { .share-setup { display: flex; diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 5e61f6d3c..40a282db0 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -25,6 +25,7 @@ import { GroupMemberView } from './GroupMemberView'; import { LinkManager } from './LinkManager'; import { SelectionManager } from './SelectionManager'; import './SharingManager.scss'; +import { IconButton, Size } from 'browndash-components'; export interface User { email: string; @@ -159,27 +160,14 @@ export class SharingManager extends React.Component<{}> { const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`; const isDashboard = DocListCast(Doc.MyDashboards.data).indexOf(target) !== -1; - // var docs: Doc[] = []; - // const dashboardList = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); - // const dashboard = dashboardList[0] - // docs.push(dashboard!) - // const tabs = DocListCast(dashboard?.data) - // tabs.forEach(tab => { - // docs.push(tab) - // var newDocs = DocListCast(tab.data) - // newDocs.forEach(newDoc => - // docs.push(newDoc)) - // }) - - // if (!docs){ - // return null; - // } + // setting the same acl for a docs within the doc being shared + var childDocs = DocListCast(target.data) + childDocs.map(doc => { + this.setInternalSharing(recipient, permission, doc) + }) const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); - //var docs: Doc[] = []; - docs.push(targetDoc!) - // ! ensures it returns true if document has been shared successfully, false otherwise return !docs .map(doc => (this.layoutDocAcls ? doc : doc[DataSym])) @@ -191,7 +179,6 @@ export class SharingManager extends React.Component<{}> { } else { if (!doc[acl] || doc[acl] === SharingPermissions.None) doc.numUsersShared = NumCast(doc.numUsersShared, 0) + 1; } - doc = targetDoc distributeAcls(acl, permission as SharingPermissions, doc, undefined, undefined, isDashboard); this.setDashboardBackground(doc, permission as SharingPermissions); @@ -211,19 +198,15 @@ export class SharingManager extends React.Component<{}> { const key = normalizeEmail(StrCast(group.title)); const acl = `acl-${key}`; const isDashboard = DocListCast(Doc.MyDashboards.data).indexOf(target) !== -1; - - var docs: Doc[] = []; - const dashboardList = SelectionManager.Views().length < 2 ? [this.targetDoc] : SelectionManager.Views().map(docView => docView.props.Document); - const dashboard = dashboardList[0] - const tabs = DocListCast(dashboard?.data) - tabs.forEach(tab => { - var newDocs = DocListCast(tab.data) - newDocs.forEach(newDoc => docs.push(newDoc)) - }) - if (!docs){ - return null; - } + // setting the same acl for a docs within the doc being shared + var childDocs = DocListCast(target.data) + childDocs.map(doc => { + this.setInternalGroupSharing(group, permission, doc) + }) + + const docs = SelectionManager.Views().length < 2 ? [target] : SelectionManager.Views().map(docView => docView.props.Document); + // ! ensures it returns true if document has been shared successfully, false otherwise return !docs .map(doc => (this.layoutDocAcls ? doc : doc[DataSym])) @@ -292,6 +275,7 @@ export class SharingManager extends React.Component<{}> { const dashboards = DocListCast(Doc.MyDashboards.data); docs.forEach(doc => { const isDashboard = dashboards.indexOf(doc) !== -1; + this.shareFromPropertiesSidebar(shareWith, permission, DocListCast(doc.data)) if (GetEffectiveAcl(doc) === AclAdmin) distributeAcls(`acl-${shareWith}`, permission, doc, undefined, undefined, isDashboard); this.setDashboardBackground(doc, permission as SharingPermissions); }); @@ -364,30 +348,15 @@ export class SharingManager extends React.Component<{}> { // return; // } // targetDoc["acl-" + PublicKey] = permission; - // } - - private get sharingUrl() { - if (!this.targetDoc) { - return undefined; - } - const baseUrl = Utils.prepend("/doc/" + this.targetDoc[Id]); - return `${baseUrl}?sharing=true`; - } + // }s /** * Copies the Public sharing url to the user's clipboard. */ private copyURL = (e: any) => { - Utils.CopyText(this.sharingUrl!) + Utils.CopyText(Utils.shareUrl(this.targetDoc![Id])) } - // copy = action(() => { - // if (this.sharingUrl) { - // Utils.CopyText(this.sharingUrl); - // this.copied = true; - // } - // }); - /** * Returns the SharingPermissions (Admin, Can Edit etc) access that's used to share */ @@ -396,7 +365,6 @@ export class SharingManager extends React.Component<{}> { if (!uniform) dropdownValues.unshift('-multiple-'); if (!override) dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1); return dropdownValues - .filter(permission => permission != SharingPermissions.SelfEdit && (!Doc.noviceMode || ![SharingPermissions.SelfEdit].includes(permission as any))) .map(permission => ( <option key={permission} value={permission}> {permission} @@ -546,19 +514,6 @@ export class SharingManager extends React.Component<{}> { // users in common between all docs const commonKeys = intersection(...docs.map(doc => (this.layoutDocAcls ? doc : doc[DataSym])).map(doc => doc?.[AclSym] && Object.keys(doc[AclSym]))); - // including all users on dashboard - // SharingManager.Instance.users.forEach(eachUser => { - // var userOnDashboard = true; - // if(Doc.ActiveDashboard){ - // if(Doc.ActiveDashboard['acl-'+normalizeEmail(eachUser.user.email)]=='' || Doc.ActiveDashboard['acl-'+normalizeEmail(eachUser.user.email)]==undefined){ - // userOnDashboard = false; - // } - // } - // if (userOnDashboard && !commonKeys.includes(`acl-${normalizeEmail(eachUser.user.email)}`)){ - // users.push(eachUser.user); - // } - // }); - // the list of users shared with const userListContents: (JSX.Element | null)[] = users @@ -570,19 +525,6 @@ export class SharingManager extends React.Component<{}> { const dashboard = Doc.ActiveDashboard var docToUse = dashboard - // const tabs = DocListCast(dashboard?.data) - // tabs.forEach(tab => { - // if (tab.title == targetDoc.title){ - // docToUse = tab - // } - // var newdocsList = DocListCast(tab.data) - // newdocsList.forEach(newDoc => { - // if (newDoc.title == targetDoc.title){ - // docToUse = newDoc - // } - // }) - // }) - docToUse = Doc.GetProto(this.targetDoc!) const userKey = `acl-${normalizeEmail(user.email)}`; @@ -641,22 +583,6 @@ export class SharingManager extends React.Component<{}> { return !permissions ? null : ( <div key={groupKey} className={'container'}> <div className={'padding'} >{StrCast(group.title)}</div> - <div> - {StrCast(group.title)==='Public' ? ( - <div title={"Copy Public URL"} onClick={this.copyURL}> - {/* <IconButton - size={Size.SMALL} - isCircle={true} - hoverStyle="gray" - onClick={() => this.copyURL} - icon={<FontAwesomeIcon icon="copy" />} - /> */} - <FontAwesomeIcon icon={'copy'} size={'sm'} /> - </div> - ) : ( - <div/> - )} - </div> {group instanceof Doc ? ( <div className="group-info" onClick={action(() => (GroupManager.Instance.currentGroup = group))}> <FontAwesomeIcon icon={'info-circle'} color={'#e8e8e8'} size={'sm'} style={{ backgroundColor: '#1e89d7', borderRadius: '100%', border: '1px solid #1e89d7' }} /> @@ -679,19 +605,16 @@ export class SharingManager extends React.Component<{}> { <div className={'sharing-interface'}> {GroupManager.Instance?.currentGroup ? <GroupMemberView group={GroupManager.Instance.currentGroup} onCloseButtonClick={action(() => (GroupManager.Instance.currentGroup = undefined))} /> : null} <div className="sharing-contents"> - <p className={'share-title'}> + <p className="share-title"> <b>Share </b> {this.focusOn(docs.length < 2 ? StrCast(targetDoc?.title, 'this document') : '-multiple-')} + {/* <FontAwesomeIcon title={"Copy Public URL"} icon={'copy'} size={'sm'} onClick={this.copyURL}/> */} + <IconButton size={Size.SMALL} isCircle={true} tooltip='Copy Public URL' hoverStyle="gray" onClick={this.copyURL}icon={<FontAwesomeIcon icon="copy" />}/> </p> <div className={'close-button'} onClick={this.close}> <FontAwesomeIcon icon={'times'} color={'black'} size={'lg'} /> </div> - {/* {this.linkVisible ? - <div> - {this.sharingUrl} - </div> : - (null)} */} - { + { admin ? <div className="share-container"> <div className="share-setup"> <Select @@ -730,6 +653,7 @@ export class SharingManager extends React.Component<{}> { )} </div> </div> + : <br></br> } <div className="main-container"> <div className={'individual-container'}> diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index 0b92fd864..5a1dae8db 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -222,8 +222,12 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() if (effectiveAcl === AclAugment) { added.map(doc => { - if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc)) && Doc.ActiveDashboard) inheritParentAcls(Doc.ActiveDashboard, doc); doc.context = this.props.Document; + const contextDoc = Cast(doc.context, Doc, null) + if ([AclAdmin, AclEdit].includes(GetEffectiveAcl(doc))) { + if (contextDoc) inheritParentAcls(contextDoc, doc); + else if (Doc.ActiveDashboard) inheritParentAcls(Doc.ActiveDashboard, doc); + }; if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document; Doc.AddDocToList(targetDataDoc, annotationKey ?? this.annotationKey, doc); }); @@ -237,7 +241,9 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps>() doc.context = this.props.Document; if (annotationKey ?? this._annotationKeySuffix()) Doc.GetProto(doc).annotationOn = this.props.Document; - Doc.ActiveDashboard && inheritParentAcls(Doc.ActiveDashboard, doc); + const contextDoc = Cast(doc.context, Doc, null) + if (contextDoc) inheritParentAcls(contextDoc, doc); + else if (Doc.ActiveDashboard) inheritParentAcls(Doc.ActiveDashboard, doc); }); const annoDocs = targetDataDoc[annotationKey ?? this.annotationKey] as List<Doc>; if (annoDocs instanceof List) annoDocs.push(...added); diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index ce5378e69..32bcc872a 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -237,8 +237,7 @@ $resizeHandler: 8px; color: rgb(71, 71, 71); border-color: rgb(71, 71, 71); } - .documentDecorations-shareEdit, - .documentDecorations-shareSelf-Edit{ + .documentDecorations-shareEdit{ width: calc(100% + 10px); background: rgb(235, 235, 145); color: rgb(75, 75, 5); diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 3e0a1f7a4..b769056d8 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -32,6 +32,7 @@ import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { ImageBox } from './nodes/ImageBox'; import React = require('react'); import { SharingManager } from '../util/SharingManager'; +import { DocServer } from '../DocServer'; @observer export class DocumentDecorations extends React.Component<{ PanelWidth: number; PanelHeight: number; boundsLeft: number; boundsTop: number }, { value: string }> { @@ -754,9 +755,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P case ("Edit"): shareSymbolIcon = "⬢ "; break; - case ("Self-Edit"): - shareSymbolIcon = "⬢ "; - break; case ("Augment"): shareSymbolIcon = "⬟ "; break; @@ -794,7 +792,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P // const collectionAcl = docView.props.ContainingCollectionView ? GetEffectiveAcl(docView.props.ContainingCollectionDoc?.[DataSym]) : AclEdit; // return docView.rootDoc.stayInCollection || (collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); const effectiveAcl = GetEffectiveAcl(Doc.GetProto(seldocview.rootDoc)) - return docView.rootDoc.stayInCollection || (effectiveAcl !== AclAdmin && effectiveAcl !== AclEdit && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); + return docView.rootDoc.stayInCollection || (effectiveAcl !== AclAdmin && GetEffectiveAcl(docView.rootDoc) !== AclAdmin); }); const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => ( <Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top"> diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 6b18caed0..7da9dc603 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -26,7 +26,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0 }; // bcz: not sure root.render(<FieldLoader />); window.location.search.includes('safe') && CollectionView.SetSafeMode(true); const info = await CurrentUserUtils.loadCurrentUser(); - if (info.email === 'guest') DocServer.Control.makeReadOnly(); + // if (info.email === 'guest') DocServer.Control.makeReadOnly(); await CurrentUserUtils.loadUserDocument(info.id); setTimeout(() => { document.getElementById('root')!.addEventListener( diff --git a/src/client/views/MarqueeAnnotator.tsx b/src/client/views/MarqueeAnnotator.tsx index 30867a774..094c9cc61 100644 --- a/src/client/views/MarqueeAnnotator.tsx +++ b/src/client/views/MarqueeAnnotator.tsx @@ -1,6 +1,6 @@ import { action, observable, ObservableMap, runInAction } from 'mobx'; import { observer } from 'mobx-react'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, DataSym, Doc, Opt } from '../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit, DataSym, Doc, Opt } from '../../fields/Doc'; import { Id } from '../../fields/FieldSymbols'; import { List } from '../../fields/List'; import { NumCast } from '../../fields/Types'; @@ -202,7 +202,7 @@ export class MarqueeAnnotator extends React.Component<MarqueeAnnotatorProps> { highlight = (color: string, isLinkButton: boolean, savedAnnotations?: ObservableMap<number, HTMLDivElement[]>, addAsAnnotation?: boolean) => { // creates annotation documents for current highlights const effectiveAcl = GetEffectiveAcl(this.props.rootDoc[DataSym]); - const annotationDoc = [AclAugment, AclSelfEdit, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color, isLinkButton, savedAnnotations); + const annotationDoc = [AclAugment, AclEdit, AclAdmin].includes(effectiveAcl) && this.makeAnnotationDocument(color, isLinkButton, savedAnnotations); addAsAnnotation && !savedAnnotations && annotationDoc && this.props.addDocument(annotationDoc); return (annotationDoc as Doc) ?? undefined; }; diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss index 50bf6ce74..71107a5f9 100644 --- a/src/client/views/PropertiesView.scss +++ b/src/client/views/PropertiesView.scss @@ -172,8 +172,7 @@ border-radius: 6px; border: 1px solid rgb(71, 71, 71); } - & .propertiesView-shareDropDownEdit, - .propertiesView-shareDropDownSelf-Edit{ + & .propertiesView-shareDropDownEdit{ padding: 5px; background: rgb(235, 235, 145); color: rgb(75, 75, 5); @@ -426,7 +425,6 @@ background: inherit; border: none; background: inherit; - // width: 100%; text-align: justify; // for Edge text-align-last: end; &:hover { diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index a6a5347ad..984c2dc04 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -369,7 +369,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { changePermissions = (e: any, user: string) => { const docs = (SelectionManager.Views().length < 2 ? [this.selectedDoc] : SelectionManager.Views().map(dv => dv.props.Document)).filter(doc => doc).map(doc => (this.layoutDocAcls ? doc : DocCast(doc)[DataSym])); if (user=="Public"){ - docs[0]['acl-' +user] = e.currentTarget.value as SharingPermissions; + // docs[0]['acl-' +user] = e.currentTarget.value as SharingPermissions; + SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs); } else{ @@ -385,12 +386,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { if (permission === '-multiple-') dropdownValues.unshift(permission); if (user !== 'Override') { dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1); - // dropdownValues.splice(dropdownValues.indexOf(SharingPermissions.Unset), 1); } return ( <select className="propertiesView-permissions-select" value={permission} onChange={e => this.changePermissions(e, user)}> {dropdownValues - .filter(permission => permission != SharingPermissions.SelfEdit && (!Doc.noviceMode || ![SharingPermissions.View, SharingPermissions.SelfEdit].includes(permission as any))) + .filter(permission => !Doc.noviceMode || ![SharingPermissions.View].includes(permission as any)) .map(permission => ( <option className="propertiesView-permisssions-select" key={permission} value={permission}> {' '}{permission}{' '} @@ -464,9 +464,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { case ("Edit"): dropDownText = "⬢ "; break; - case ("Self-Edit"): - dropDownText = "⬢ "; - break; case ("Augment"): dropDownText = "⬟ "; break; @@ -494,52 +491,35 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { } /** + * Sorting algorithm to sort users. + */ + sortUsers = (u1: String, u2: String) => { + return u1 > u2 ? -1 : u1 === u2 ? 0 : 1; + }; + + /** * @returns the sharing and permissions panel. */ @computed get sharingTable() { - // const docToUse = this.selectedDocumentView?.rootDoc; - - // const dashboard = Doc.ActiveDashboard - // var docToUse = dashboard - // const tabs = DocListCast(dashboard?.data) - // tabs.forEach(tab => { - // if (tab.title == this.selectedDoc?.title){ - // docToUse = tab - // } - // var newdocsList = DocListCast(tab.data) - // newdocsList.forEach(newDoc => { - // if (newDoc.title == this.selectedDoc?.title){ - // docToUse = newDoc - // } - // }) - // }) const docToUse = this.selectedDoc; - if (!docToUse){ return null; } // all selected docs const docs = SelectionManager.Views().length < 2 ? [this.layoutDocAcls ? docToUse : docToUse?.[DataSym]] : SelectionManager.Views().map(docView => (this.layoutDocAcls ? docView.props.Document : docView.props.Document[DataSym])); - const target = docs[0]; - // tslint:disable-next-line: no-unnecessary-callback-wrapper - // const effectiveAcls = docs.map(doc => GetEffectiveAcl(doc)); - // const effectiveAcls = GetEffectiveAcl(docToUse) const effectiveAcls = GetEffectiveAcl(target) - - // const showAdmin = effectiveAcls.every(acl => acl === AclAdmin); const showAdmin= effectiveAcls==AclAdmin || docToUse!['acl-'+normalizeEmail(Doc.CurrentUserEmail)]=='Owner'; // users in common between all docs - const commonKeys: string[] = intersection(...docs.map(doc => doc?.[AclSym] && Object.keys(doc[AclSym]).filter(key => key !== 'acl-Me'))); + // const commonKeys: string[] = intersection(...docs.map(doc => doc?.[AclSym] && Object.keys(doc[AclSym]).filter(key => key !== 'acl-Me'))); + // const ownerSame = Doc.CurrentUserEmail !== target.author && docs.filter(doc => doc).every(doc => doc.author === docs[0].author); const tableEntries = []; const usersAdded: string[] = []; // all shared users being added - organized by denormalized email - const ownerSame = Doc.CurrentUserEmail !== target.author && docs.filter(doc => doc).every(doc => doc.author === docs[0].author); - usersAdded.push(target.author); SharingManager.Instance.users.forEach(eachUser => { var userOnDashboard = true; var permission = StrCast(target[`acl-${normalizeEmail(eachUser.user.email)}`]) @@ -548,46 +528,33 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { userOnDashboard = false; } } - if (userOnDashboard && !usersAdded.includes(eachUser.user.email) && eachUser.user.email!='Public'){ - tableEntries.unshift(this.sharingItem(eachUser.user.email, showAdmin, permission, false)); // adds each user + if (userOnDashboard && !usersAdded.includes(eachUser.user.email) && eachUser.user.email!='Public' && eachUser.user.email!=target.author){ + // tableEntries.unshift(this.sharingItem(eachUser.user.email, showAdmin, permission, false)); // adds each user usersAdded.push(eachUser.user.email); } }); - - // commonKeys.forEach(user => { - // const userEmail = user.slice(4) - // var userOnDashboard = true; - // if(Doc.ActiveDashboard){ - // if(Doc.ActiveDashboard[user]=='' || Doc.ActiveDashboard[user]==undefined){ - // userOnDashboard = false; - // } - // } - // if (userOnDashboard && !usersAdded.includes(denormalizeEmail(userEmail)) && userEmail!='Public'){ - // tableEntries.unshift(this.sharingItem(denormalizeEmail(userEmail), showAdmin, StrCast(docToUse![`acl-${normalizeEmail((userEmail))}`]), false)); // adds each user - // usersAdded.push(denormalizeEmail(userEmail)); - // } - // }) - - // current user - const userEmail = Doc.CurrentUserEmail - var userOnDashboard = true; - if(Doc.ActiveDashboard){ - if(Doc.ActiveDashboard['acl-'+normalizeEmail(userEmail)]=='' || Doc.ActiveDashboard['acl-'+normalizeEmail(userEmail)]==undefined){ - userOnDashboard = false; - } - } - if (userOnDashboard && !usersAdded.includes(denormalizeEmail(userEmail)) && userEmail!='Public'){ - tableEntries.unshift(this.sharingItem(denormalizeEmail(userEmail), showAdmin, StrCast(target[`acl-${normalizeEmail((userEmail))}`]), false)); // adds each user - usersAdded.push(denormalizeEmail(userEmail)); + + usersAdded.sort(this.sortUsers) + usersAdded.map(userEmail => { + const permission = StrCast(target[`acl-${normalizeEmail(userEmail)}`]) + tableEntries.unshift(this.sharingItem(userEmail, showAdmin, permission, false)); // adds each user + }) + + // add current user + var userEmail = Doc.CurrentUserEmail + if (userEmail == 'guest') userEmail = 'Public'; + if (!usersAdded.includes(userEmail) && userEmail!='Public' && userEmail!=target.author){ + tableEntries.unshift(this.sharingItem(userEmail, showAdmin, StrCast(target[`acl-${normalizeEmail((userEmail))}`]), false)); // adds each user + usersAdded.push(userEmail); } - // if (ownerSame ) tableEntries.unshift(this.sharingItem(StrCast(target.author), showAdmin, 'Owner'), false); // shift owner to top - tableEntries.unshift(this.sharingItem(StrCast(target.author), showAdmin, 'Owner'), false); // shift owner to top + // shift owner to top + tableEntries.unshift(this.sharingItem(StrCast(target.author), showAdmin, 'Owner'), false); return ( <div > Sharing Mode <div>{ - this.publicACLDropDown(true, StrCast(target['acl-Public']), false)} + this.publicACLDropDown(showAdmin, StrCast(target['acl-Public']), false)} </div> <div> <br></br> Who has access to the Dashboard? </div> <div className="propertiesView-sharingTable">{ diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 0e4330fa5..c073c7468 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -11,7 +11,7 @@ import { Fragment, Mark, Node, Slice } from 'prosemirror-model'; import { EditorState, NodeSelection, Plugin, TextSelection, Transaction } from 'prosemirror-state'; import { EditorView } from 'prosemirror-view'; import { DateField } from '../../../../fields/DateField'; -import { AclAdmin, AclAugment, AclEdit, AclSelfEdit, Doc, DocListCast, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit, Doc, DocListCast, Field, ForceServerWrite, HeightSym, Opt, UpdatingFromServer, WidthSym } from '../../../../fields/Doc'; import { Id } from '../../../../fields/FieldSymbols'; import { InkTool } from '../../../../fields/InkField'; import { PrefetchProxy } from '../../../../fields/Proxy'; @@ -295,12 +295,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps const curProto = Cast(Cast(dataDoc.proto, Doc, null)?.[this.fieldKey], RichTextField, null); // the default text inherited from a prototype const curLayout = this.rootDoc !== this.layoutDoc ? Cast(this.layoutDoc[this.fieldKey], RichTextField, null) : undefined; // the default text stored in a layout template const json = JSON.stringify(state.toJSON()); - // const effectiveAcl = GetEffectiveAcl(dataDoc); const effectiveAcl = GetEffectiveAcl(this.rootDoc); const removeSelection = (json: string | undefined) => (json?.indexOf('"storedMarks"') === -1 ? json?.replace(/"selection":.*/, '') : json?.replace(/"selection":"\"storedMarks\""/, '"storedMarks"')); - if ([AclEdit, AclAdmin, AclSelfEdit, AclAugment].includes(effectiveAcl)) { + if ([AclEdit, AclAdmin, AclAugment].includes(effectiveAcl)) { const accumTags = [] as string[]; state.tr.doc.nodesBetween(0, state.doc.content.size, (node: any, pos: number, parent: any) => { if (node.type === schema.nodes.dashField && node.attrs.fieldKey.startsWith('#')) { @@ -1690,7 +1689,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps e.stopPropagation(); for (var i = state.selection.from; i <= state.selection.to; i++) { const node = state.doc.resolve(i); - if (state.doc.content.size - 1 > i && node?.marks?.().some(mark => mark.type === schema.marks.user_mark && mark.attrs.userid !== Doc.CurrentUserEmail) && [AclSelfEdit].includes(GetEffectiveAcl(this.rootDoc))) { + if (state.doc.content.size - 1 > i && node?.marks?.().some(mark => mark.type === schema.marks.user_mark && mark.attrs.userid !== Doc.CurrentUserEmail) ) { e.preventDefault(); } } @@ -1712,7 +1711,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps if (e.code == "Space"){ break; } - [AclEdit, AclAugment, AclSelfEdit, AclAdmin].includes(GetEffectiveAcl(this.rootDoc)) && + [AclEdit, AclAugment, AclAdmin].includes(GetEffectiveAcl(this.rootDoc)) && this._editorView!.dispatch(this._editorView!.state.tr.removeStoredMark(schema.marks.user_mark.create({})).addStoredMark(schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) }))); } this.startUndoTypingBatch(); diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts index 68b0488a2..64cc7addc 100644 --- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts +++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts @@ -4,7 +4,7 @@ import { Schema } from 'prosemirror-model'; import { splitListItem, wrapInList } from 'prosemirror-schema-list'; import { EditorState, NodeSelection, TextSelection, Transaction } from 'prosemirror-state'; import { liftTarget } from 'prosemirror-transform'; -import { AclAugment, AclSelfEdit, Doc } from '../../../../fields/Doc'; +import { AclAdmin, AclAugment, AclEdit} from '../../../../fields/Doc'; import { GetEffectiveAcl } from '../../../../fields/util'; import { Utils } from '../../../../Utils'; import { Docs } from '../../../documents/Documents'; @@ -48,14 +48,6 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey switch (GetEffectiveAcl(props.DataDoc)) { case AclAugment: return false; - case AclSelfEdit: - for (var i = state.selection.from; i < state.selection.to; i++) { - const marks = state.doc.resolve(i)?.marks?.(); - if (marks?.some((mark: any) => mark.type === schema.marks.user_mark && mark.attrs.userid !== Doc.CurrentUserEmail)) { - return false; - } - } - break; } return true; }; @@ -259,7 +251,7 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey //Command to create a blank space bind('Space', (state: EditorState, dispatch: (tx: Transaction) => void) => { - if (!canEdit(state)) return true; + if (GetEffectiveAcl(props.DataDoc)!=AclEdit && GetEffectiveAcl(props.DataDoc)!=AclAugment && GetEffectiveAcl(props.DataDoc)!=AclAdmin) return true; const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks()); dispatch(splitMetadata(marks, state.tr)); return false; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 5e2e40979..68279372a 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -102,7 +102,6 @@ export const AclUnset = Symbol('AclUnset'); export const AclPrivate = Symbol('AclOwnerOnly'); export const AclReadonly = Symbol('AclReadOnly'); export const AclAugment = Symbol('AclAugment'); -export const AclSelfEdit = Symbol('AclSelfEdit'); export const AclEdit = Symbol('AclEdit'); export const AclAdmin = Symbol('AclAdmin'); export const UpdatingFromServer = Symbol('UpdatingFromServer'); @@ -115,7 +114,6 @@ export enum aclLevel { unshared = 0, viewable = 1, augmentable = 2, - selfEditable = 2.5, editable = 3, admin = 4, } @@ -124,7 +122,6 @@ export const HierarchyMapping: Map<symbol, { level:aclLevel; name: SharingPermis [AclPrivate, { level: aclLevel.unshared, name: SharingPermissions.None }], [AclReadonly, { level: aclLevel.viewable, name: SharingPermissions.View }], [AclAugment, { level: aclLevel.augmentable, name: SharingPermissions.Augment}], - [AclSelfEdit, { level: aclLevel.selfEditable, name: SharingPermissions.SelfEdit }], [AclEdit, { level: aclLevel.editable, name: SharingPermissions.Edit }], [AclAdmin, { level: aclLevel.admin, name: SharingPermissions.Admin }], [AclUnset, { level: aclLevel.unset, name: SharingPermissions.Unset }], diff --git a/src/fields/util.ts b/src/fields/util.ts index c1e1a7111..b0ad4db5d 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -14,7 +14,6 @@ import { aclLevel, AclPrivate, AclReadonly, - AclSelfEdit, AclSym, DataSym, Doc, @@ -87,7 +86,7 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number const fromServer = target[UpdatingFromServer]; const sameAuthor = fromServer || receiver.author === Doc.CurrentUserEmail; const writeToDoc = sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAugment || effectiveAcl === AclAdmin || writeMode !== DocServer.WriteMode.LiveReadonly; - const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAugment || effectiveAcl === AclAdmin || (effectiveAcl === AclSelfEdit && value instanceof RichTextField)) && !DocServer.Control.isReadOnly(); + const writeToServer = (sameAuthor || effectiveAcl === AclEdit || effectiveAcl === AclAugment || effectiveAcl === AclAdmin ) && !DocServer.Control.isReadOnly(); if (writeToDoc) { if (value === undefined) { @@ -171,7 +170,6 @@ export enum SharingPermissions { Unset = 'None', Admin = 'Admin', Edit = 'Edit', - SelfEdit = 'Self-Edit', Augment = 'Augment', View = 'View', None = 'Not-Shared', @@ -330,7 +328,7 @@ export function distributeAcls(key: string, acl: SharingPermissions, target: Doc export function setter(target: any, in_prop: string | symbol | number, value: any, receiver: any): boolean { let prop = in_prop; const effectiveAcl = in_prop === 'constructor' || typeof in_prop === 'symbol' ? AclAdmin : getPropAcl(target, prop); - if (effectiveAcl !== AclEdit && effectiveAcl !== AclAugment && effectiveAcl !== AclAdmin && !(effectiveAcl === AclSelfEdit && value instanceof RichTextField)) return true; + if (effectiveAcl !== AclEdit && effectiveAcl !== AclAugment && effectiveAcl !== AclAdmin ) return true; // if you're trying to change an acl but don't have Admin access / you're trying to change it to something that isn't an acceptable acl, you can't if (typeof prop === 'string' && prop.startsWith('acl') && (effectiveAcl !== AclAdmin || ![...Object.values(SharingPermissions), undefined].includes(value))) return true; |