aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts1
-rw-r--r--src/client/util/DocumentManager.ts21
-rw-r--r--src/client/util/LinkManager.ts8
-rw-r--r--src/client/util/SerializationHelper.ts39
-rw-r--r--src/client/util/SharingManager.tsx56
5 files changed, 48 insertions, 77 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 5549769aa..afa9e7de3 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -601,7 +601,6 @@ export class CurrentUserUtils {
};
reaction(() => UndoManager.redoStack.slice(), () => Doc.GetProto(btns.find(btn => btn.title === "redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4, { fireImmediately: true });
reaction(() => UndoManager.undoStack.slice(), () => {
- console.log(UndoManager.undoStack)
Doc.GetProto(btns.find(btn => btn.title === "undo")!).opacity = UndoManager.CanUndo() ? 1 : 0.4;
}, { fireImmediately: true });
return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns);
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index d2e9e17b4..235b80cdd 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -2,7 +2,7 @@ import { action, observable, runInAction } from 'mobx';
import { Doc, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { listSpec } from '../../fields/Schema';
-import { Cast, DocCast } from '../../fields/Types';
+import { Cast } from '../../fields/Types';
import { AudioField } from '../../fields/URLField';
import { returnFalse } from '../../Utils';
import { DocumentType } from '../documents/DocumentTypes';
@@ -146,15 +146,9 @@ export class DocumentManager {
}
public getDocumentView(toFind: Doc, preferredCollection?: CollectionView): DocumentView | undefined {
- const found =
- Array.from(DocumentManager.Instance.DocumentViews).find(
- dv =>
- ((dv.rootDoc.data as any)?.url?.href && (dv.rootDoc.data as any)?.url?.href === (toFind.data as any)?.url?.href) ||
- ((DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href && (DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href === (DocCast(toFind.annotationOn)?.data as any)?.url?.href)
- )?.rootDoc ?? toFind;
- return this.getDocumentViewById(found[Id], preferredCollection);
+ return this.getDocumentViewById(toFind[Id], preferredCollection);
}
-
+
public getLightboxDocumentView = (toFind: Doc, originatingDoc: Opt<Doc> = undefined): DocumentView | undefined => {
const views: DocumentView[] = [];
Array.from(DocumentManager.Instance.DocumentViews).map(view => LightboxView.IsLightboxDocView(view.docViewPath) && Doc.AreProtosEqual(view.rootDoc, toFind) && views.push(view));
@@ -165,14 +159,7 @@ export class DocumentManager {
const views = this.getDocumentViews(toFind).filter(view => view.rootDoc !== originatingDoc);
return views?.find(view => view.ContentDiv?.getBoundingClientRect().width && view.props.focus !== returnFalse) || views?.find(view => view.props.focus !== returnFalse) || (views.length ? views[0] : undefined);
};
- public getDocumentViews(toFindIn: Doc): DocumentView[] {
- const toFind =
- Array.from(DocumentManager.Instance.DocumentViews).find(
- dv =>
- ((dv.rootDoc.data as any)?.url?.href && (dv.rootDoc.data as any)?.url?.href === (toFindIn.data as any)?.url?.href) ||
- ((DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href && (DocCast(dv.rootDoc.annotationOn)?.data as any)?.url?.href === (DocCast(toFindIn.annotationOn)?.data as any)?.url?.href)
- )?.rootDoc ?? toFindIn;
-
+ public getDocumentViews(toFind: Doc): DocumentView[] {
const toReturn: DocumentView[] = [];
const docViews = Array.from(DocumentManager.Instance.DocumentViews).filter(view => !LightboxView.IsLightboxDocView(view.docViewPath));
const lightViews = Array.from(DocumentManager.Instance.DocumentViews).filter(view => LightboxView.IsLightboxDocView(view.docViewPath));
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index 588664dec..2b0ce1d3d 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -44,7 +44,6 @@ export class LinkManager {
if (a1 instanceof Doc && a2 instanceof Doc && ((a1.author !== undefined && a2.author !== undefined) || link.author === Doc.CurrentUserEmail)) {
Doc.GetProto(a1)[DirectLinksSym].add(link);
Doc.GetProto(a2)[DirectLinksSym].add(link);
- //Doc.GetProto(link)[DirectLinksSym].add(link); // bcz: links are not linked to themself, so this was a hack
}
})
);
@@ -147,12 +146,7 @@ export class LinkManager {
return this.relatedLinker(anchor);
} // finds all links that contain the given anchor
public getAllDirectLinks(anchor: Doc): Doc[] {
- // FIXME:glr Why is Doc undefined?
- if (Doc.GetProto(anchor)[DirectLinksSym]) {
- return Array.from(Doc.GetProto(anchor)[DirectLinksSym]);
- } else {
- return [];
- }
+ return Array.from(Doc.GetProto(anchor)[DirectLinksSym] ?? []);
} // finds all links that contain the given anchor
relatedLinker = computedFn(function relatedLinker(this: any, anchor: Doc): Doc[] {
diff --git a/src/client/util/SerializationHelper.ts b/src/client/util/SerializationHelper.ts
index 2d598c1ac..2d1f61cfb 100644
--- a/src/client/util/SerializationHelper.ts
+++ b/src/client/util/SerializationHelper.ts
@@ -1,6 +1,6 @@
-import { PropSchema, serialize, deserialize, custom, setDefaultModelSchema, getDefaultModelSchema } from "serializr";
-import { Field } from "../../fields/Doc";
-import { ClientUtils } from "./ClientUtils";
+import { PropSchema, serialize, deserialize, custom, setDefaultModelSchema, getDefaultModelSchema } from 'serializr';
+import { Field } from '../../fields/Doc';
+import { ClientUtils } from './ClientUtils';
let serializing = 0;
export function afterDocDeserialize(cb: (err: any, val: any) => void, err: any, newValue: any) {
@@ -25,7 +25,7 @@ export namespace SerializationHelper {
serializing++;
if (!(obj.constructor.name in reverseMap)) {
serializing--;
- throw Error("Error: " + `type '${obj.constructor.name}' not registered. Make sure you register it using a @Deserializable decorator`);
+ throw Error('Error: ' + `type '${obj.constructor.name}' not registered. Make sure you register it using a @Deserializable decorator`);
}
const json = serialize(obj);
@@ -59,24 +59,24 @@ export namespace SerializationHelper {
const type = serializationTypes[obj.__type];
const value = await new Promise(res => deserialize(type.ctor, obj, (err, result) => res(result)));
if (type.afterDeserialize) {
- await type.afterDeserialize(value);
+ type.afterDeserialize(value);
}
return value;
}
}
-const serializationTypes: { [name: string]: { ctor: { new(): any }, afterDeserialize?: (obj: any) => void | Promise<any> } } = {};
+const serializationTypes: { [name: string]: { ctor: { new (): any }; afterDeserialize?: (obj: any) => void | Promise<any> } } = {};
const reverseMap: { [ctor: string]: string } = {};
export interface DeserializableOpts {
- (constructor: { new(...args: any[]): any }): void;
+ (constructor: { new (...args: any[]): any }): void;
withFields(fields: string[]): Function;
}
export function Deserializable(name: string, afterDeserialize?: (obj: any) => void | Promise<any>): DeserializableOpts;
-export function Deserializable(constructor: { new(...args: any[]): any }): void;
-export function Deserializable(constructor: { new(...args: any[]): any } | string, afterDeserialize?: (obj: any) => void): DeserializableOpts | void {
- function addToMap(name: string, ctor: { new(...args: any[]): any }) {
+export function Deserializable(constructor: { new (...args: any[]): any }): void;
+export function Deserializable(constructor: { new (...args: any[]): any } | string, afterDeserialize?: (obj: any) => void): DeserializableOpts | void {
+ function addToMap(name: string, ctor: { new (...args: any[]): any }) {
const schema = getDefaultModelSchema(ctor) as any;
if (schema.targetClass !== ctor) {
const newSchema = { ...schema, factory: () => new ctor() };
@@ -89,17 +89,20 @@ export function Deserializable(constructor: { new(...args: any[]): any } | strin
throw new Error(`Name ${name} has already been registered as deserializable`);
}
}
- if (typeof constructor === "string") {
- return Object.assign((ctor: { new(...args: any[]): any }) => {
- addToMap(constructor, ctor);
- }, { withFields: (fields: string[]) => Deserializable.withFields(fields, constructor, afterDeserialize) });
+ if (typeof constructor === 'string') {
+ return Object.assign(
+ (ctor: { new (...args: any[]): any }) => {
+ addToMap(constructor, ctor);
+ },
+ { withFields: (fields: string[]) => Deserializable.withFields(fields, constructor, afterDeserialize) }
+ );
}
addToMap(constructor.name, constructor);
}
export namespace Deserializable {
export function withFields(fields: string[], name?: string, afterDeserialize?: (obj: any) => void | Promise<any>) {
- return function (constructor: { new(...fields: any[]): any }) {
+ return function (constructor: { new (...fields: any[]): any }) {
Deserializable(name || constructor.name, afterDeserialize)(constructor);
let schema = getDefaultModelSchema(constructor);
if (schema) {
@@ -128,7 +131,7 @@ export namespace Deserializable {
factory: context => {
const args = fields.map(key => context.json[key]);
return new constructor(...args);
- }
+ },
};
setDefaultModelSchema(constructor, schema);
}
@@ -138,7 +141,7 @@ export namespace Deserializable {
export function autoObject(): PropSchema {
return custom(
- (s) => SerializationHelper.Serialize(s),
+ s => SerializationHelper.Serialize(s),
(json: any, context: any, oldValue: any, cb: (err: any, result: any) => void) => SerializationHelper.Deserialize(json).then(res => cb(null, res))
);
-} \ No newline at end of file
+}
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 8b50a3b85..ae4524b5e 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -5,7 +5,8 @@ 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 { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from '../../fields/util';
@@ -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;
// }
@@ -137,7 +127,6 @@ export class SharingManager extends React.Component<{}> {
* Populates the list of validated users (this.users) by adding registered users which have a sharingDocument.
*/
populateUsers = async () => {
- return;
if (!this.populating && Doc.UserDoc()[Id] !== '__guest__') {
this.populating = true;
const userList = await RequestPromise.get(Utils.prepend('/getUsers'));
@@ -164,7 +153,7 @@ export class SharingManager extends React.Component<{}> {
for (const sharer of sharingDocs) {
if (!this.users.find(user => user.user.email === sharer.user.email)) {
this.users.push(sharer);
- // LinkManager.addLinkDB(sharer.linkDatabase);
+ LinkManager.addLinkDB(sharer.linkDatabase);
}
}
});
@@ -185,6 +174,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);
@@ -218,6 +208,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);
@@ -284,6 +275,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);
});
}
};
@@ -291,14 +283,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;
}
@@ -373,7 +369,7 @@ 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.SelfEdit].includes(permission as any))
.map(permission => (
@@ -459,17 +455,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.
*/
@@ -492,6 +477,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
@@ -524,21 +510,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 : (
@@ -574,7 +560,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
@@ -585,7 +571,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 : (