aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CurrentUserUtils.ts44
-rw-r--r--src/client/util/GroupManager.tsx5
-rw-r--r--src/client/util/SelectionManager.ts2
-rw-r--r--src/client/util/SettingsManager.scss18
-rw-r--r--src/client/util/SharingManager.tsx60
5 files changed, 71 insertions, 58 deletions
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 45e074bcf..b7c2d60d8 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -1,6 +1,6 @@
-import { computed, observable, reaction, action } from "mobx";
+import { computed, observable, reaction } from "mobx";
import * as rp from 'request-promise';
-import { DataSym, Doc, DocListCast, DocListCastAsync, AclReadonly } from "../../fields/Doc";
+import { DataSym, Doc, DocListCast, DocListCastAsync } from "../../fields/Doc";
import { Id } from "../../fields/FieldSymbols";
import { List } from "../../fields/List";
import { PrefetchProxy } from "../../fields/Proxy";
@@ -34,7 +34,6 @@ import { SelectionManager } from "./SelectionManager";
import { UndoManager } from "./UndoManager";
import { SnappingManager } from "./SnappingManager";
import { InkTool } from "../../fields/InkField";
-import { computedFn } from "mobx-utils";
import { SharingManager } from "./SharingManager";
@@ -512,13 +511,13 @@ export class CurrentUserUtils {
static async menuBtnDescriptions(doc: Doc) {
return [
{ title: "Dashboards", target: Cast(doc.myDashboards, Doc, null), icon: "desktop", click: 'selectMainMenu(self)' },
- { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
+ { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' },
+ { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' },
{ title: "Import", target: Cast(doc.myImportPanel, Doc, null), icon: "upload", click: 'selectMainMenu(self)' },
+ { title: "Recently Closed", target: Cast(doc.myRecentlyClosedDocs, Doc, null), icon: "archive", click: 'selectMainMenu(self)' },
{ title: "Sharing", target: Cast(doc.mySharedDocs, Doc, null), icon: "users", click: 'selectMainMenu(self)', watchedDocuments: doc.mySharedDocs as Doc },
- { title: "Tools", target: Cast(doc.myTools, Doc, null), icon: "wrench", click: 'selectMainMenu(self)' },
- { title: "Filter", target: Cast(doc.myFilter, Doc, null), icon: "filter", click: 'selectMainMenu(self)' },
+ // { title: "Filter", target: Cast(doc.currentFilter, Doc, null), icon: "filter", click: 'selectMainMenu(self)' },
{ title: "Pres. Trails", target: Cast(doc.myPresentations, Doc, null), icon: "pres-trail", click: 'selectMainMenu(self)' },
- { title: "My Files", target: Cast(doc.myFilesystem, Doc, null), icon: "file", click: 'selectMainMenu(self)' },
{ title: "Help", target: undefined as any, icon: "question-circle", click: 'selectMainMenu(self)' },
{ title: "Settings", target: undefined as any, icon: "cog", click: 'selectMainMenu(self)' },
{ title: "User Doc", target: Cast(doc.myUserDoc, Doc, null), icon: "address-card", click: 'selectMainMenu(self)' },
@@ -804,20 +803,19 @@ export class CurrentUserUtils {
}
}
static setupFilterDocs(doc: Doc) {
- // setup Recently Closed library item
- doc.myFilter === undefined;
- if (doc.myFilter === undefined) {
- doc.myFilter = new PrefetchProxy(Docs.Create.FilterDocument({
- title: "FilterDoc",
+ // setup Filter item
+ if (doc.currentFilter === undefined) {
+ doc.currentFilter = Docs.Create.FilterDocument({
+ title: "unnamed filter", _height: 150,
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "none",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
- _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true
- }));
+ _lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "same", system: true, _autoHeight: true, _fitWidth: true
+ });
+ const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([])`);
+ (doc.currentFilter as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
+ (doc.currentFilter as Doc).contextMenuLabels = new List<string>(["Clear All"]);
+ (doc.currentFilter as Doc).filterBoolean = "AND";
}
- const clearAll = ScriptField.MakeScript(`getProto(self).data = new List([]); scriptContext._docFilters = scriptContext._docRangeFilters = undefined;`, { scriptContext: Doc.name });
- (doc.myFilter as any as Doc).contextMenuScripts = new List<ScriptField>([clearAll!]);
- (doc.myFilter as any as Doc).contextMenuLabels = new List<string>(["Clear All"]);
-
}
static setupUserDoc(doc: Doc) {
@@ -849,7 +847,7 @@ export class CurrentUserUtils {
CurrentUserUtils.setupPresentations(doc);
CurrentUserUtils.setupFilesystem(doc);
CurrentUserUtils.setupRecentlyClosedDocs(doc);
- CurrentUserUtils.setupFilterDocs(doc);
+ // CurrentUserUtils.setupFilterDocs(doc);
CurrentUserUtils.setupUserDoc(doc);
}
@@ -1015,6 +1013,8 @@ export class CurrentUserUtils {
doc["constants-snapThreshold"] = NumCast(doc["constants-snapThreshold"], 10); //
doc["constants-dragThreshold"] = NumCast(doc["constants-dragThreshold"], 4); //
Utils.DRAG_THRESHOLD = NumCast(doc["constants-dragThreshold"]);
+ doc.savedFilters = new List<Doc>();
+ doc.filterDocCount = 0;
this.setupDefaultIconTemplates(doc); // creates a set of icon templates triggered by the document deoration icon
this.setupDocTemplates(doc); // sets up the template menu of templates
this.setupImportSidebar(doc);
@@ -1166,10 +1166,10 @@ export class CurrentUserUtils {
CurrentUserUtils.openDashboard(userDoc, copy);
}
- public static createNewDashboard = (userDoc: Doc, id?: string) => {
- const myPresentations = userDoc.myPresentations as Doc;
+ public static createNewDashboard = async (userDoc: Doc, id?: string) => {
+ const myPresentations = await userDoc.myPresentations as Doc;
const presentation = Doc.MakeCopy(userDoc.emptyPresentation as Doc, true);
- const dashboards = Cast(userDoc.myDashboards, Doc) as Doc;
+ const dashboards = await Cast(userDoc.myDashboards, Doc) as Doc;
const dashboardCount = DocListCast(dashboards.data).length + 1;
const emptyPane = Cast(userDoc.emptyPane, Doc, null);
emptyPane["dragFactory-count"] = NumCast(emptyPane["dragFactory-count"]) + 1;
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 68af67a3b..62d656c5d 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { action, computed, observable, runInAction } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import Select from 'react-select';
@@ -284,8 +284,7 @@ export class GroupManager extends React.Component<{}> {
placeholder="Group name"
onChange={action(() => this.buttonColour = this.inputRef.current?.value ? "black" : "#979797")} />
<Select
- isMulti={true}
- isSearchable={true}
+ isMulti
options={this.options}
onChange={this.handleChange}
placeholder={"Select users"}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index c52127edd..ca5ef75d2 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -66,7 +66,7 @@ export namespace SelectionManager {
manager.SelectSchemaView(colSchema, document);
}
- const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) { // wraapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed
+ const IsSelectedCache = computedFn(function isSelected(doc: DocumentView) { // wrapping get() in a computedFn only generates mobx() invalidations when the return value of the function for the specific get parameters has changed
return manager.SelectedViews.get(doc) ? true : false;
});
// computed functions, such as used in IsSelected generate errors if they're called outside of a
diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss
index 5ca54517c..d8342ea56 100644
--- a/src/client/util/SettingsManager.scss
+++ b/src/client/util/SettingsManager.scss
@@ -75,8 +75,8 @@
width: 130;
color: black;
border-radius: 5px;
- padding:7px;
-
+ padding: 7px;
+
}
}
@@ -169,7 +169,7 @@
}
}
-.prefs-content{
+.prefs-content {
text-align: left;
}
@@ -210,6 +210,7 @@
.preferences-font-controls {
display: flex;
justify-content: space-between;
+ width: 130%;
}
.font-select {
@@ -429,11 +430,12 @@
font-size: 16px;
font-weight: bold;
margin-bottom: 16px;
- }
+ }
- .tab-column-title, .tab-column-content {
- padding-left: 16px;
- }
+ .tab-column-title,
+ .tab-column-content {
+ padding-left: 16px;
+ }
}
@@ -462,4 +464,4 @@
.settings-interface .settings-heading {
font-size: 25;
}
-}
+} \ No newline at end of file
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index ca14154b2..2f8ecd4ee 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -7,7 +7,7 @@ import Select from "react-select";
import * as RequestPromise from "request-promise";
import { AclAddonly, AclAdmin, AclEdit, AclPrivate, AclReadonly, AclSym, AclUnset, DataSym, Doc, DocListCast, DocListCastAsync, Opt } from "../../fields/Doc";
import { List } from "../../fields/List";
-import { Cast, StrCast } from "../../fields/Types";
+import { Cast, NumCast, StrCast } from "../../fields/Types";
import { distributeAcls, GetEffectiveAcl, normalizeEmail, SharingPermissions, TraceMobx } from "../../fields/util";
import { Utils } from "../../Utils";
import { DocServer } from "../DocServer";
@@ -79,7 +79,16 @@ export class SharingManager extends React.Component<{}> {
@observable private showGroupOptions: boolean = false; // // whether to show groups as options when sharing (in the react-select component)
private populating: boolean = false; // whether the list of users is populating or not
@observable private layoutDocAcls: boolean = false; // whether the layout doc or data doc's acls are to be used
- @observable private myDocAcls: boolean = false;
+ @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],
+ [AclAddonly, SharingPermissions.Add],
+ [AclEdit, SharingPermissions.Edit],
+ [AclAdmin, SharingPermissions.Admin]
+ ]);
// private get linkVisible() {
// return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
@@ -155,6 +164,7 @@ export class SharingManager extends React.Component<{}> {
});
}
}
+
/**
* Shares the document with a user.
*/
@@ -165,10 +175,16 @@ export class SharingManager extends React.Component<{}> {
const myAcl = `acl-${Doc.CurrentUserEmailNormalized}`;
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 => {
doc.author === Doc.CurrentUserEmail && !doc[myAcl] && distributeAcls(myAcl, SharingPermissions.Admin, doc);
+
+ if (permission === SharingPermissions.None) {
+ if (doc[acl] && doc[acl] !== SharingPermissions.None) doc.numUsersShared = NumCast(doc.numUsersShared, 1) - 1;
+ }
+ else {
+ if (!doc[acl] || doc[acl] === SharingPermissions.None) doc.numUsersShared = NumCast(doc.numUsersShared, 0) + 1;
+ }
+
distributeAcls(acl, permission as SharingPermissions, doc);
this.setDashboardBackground(doc, permission as SharingPermissions);
@@ -193,6 +209,14 @@ export class SharingManager extends React.Component<{}> {
// ! ensures it returns true if document has been shared successfully, false otherwise
return !docs.map(doc => {
doc.author === Doc.CurrentUserEmail && !doc[`acl-${Doc.CurrentUserEmailNormalized}`] && distributeAcls(`acl-${Doc.CurrentUserEmailNormalized}`, SharingPermissions.Admin, doc);
+
+ if (permission === SharingPermissions.None) {
+ if (doc[acl] && doc[acl] !== SharingPermissions.None) doc.numGroupsShared = NumCast(doc.numGroupsShared, 1) - 1;
+ }
+ else {
+ if (!doc[acl] || doc[acl] === SharingPermissions.None) doc.numGroupsShared = NumCast(doc.numGroupsShared, 0) + 1;
+ }
+
distributeAcls(acl, permission as SharingPermissions, doc);
this.setDashboardBackground(doc, permission as SharingPermissions);
@@ -422,20 +446,12 @@ export class SharingManager extends React.Component<{}> {
}
distributeOverCollection = (targetDoc?: Doc) => {
- const AclMap = new Map<symbol, string>([
- [AclPrivate, SharingPermissions.None],
- [AclReadonly, SharingPermissions.View],
- [AclAddonly, SharingPermissions.Add],
- [AclEdit, SharingPermissions.Edit],
- [AclAdmin, SharingPermissions.Admin]
- ]);
-
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, AclMap.get(value)! as SharingPermissions, target);
+ distributeAcls(key, this.AclMap.get(value)! as SharingPermissions, target);
}
});
}
@@ -496,7 +512,8 @@ export class SharingManager extends React.Component<{}> {
const targetDoc = docs[0];
// tslint:disable-next-line: no-unnecessary-callback-wrapper
- const admin = this.myDocAcls ? Boolean(docs.length) : docs.map(doc => GetEffectiveAcl(doc)).every(acl => acl === AclAdmin); // if the user has admin access to all selected docs
+ 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])));
@@ -560,7 +577,7 @@ export class SharingManager extends React.Component<{}> {
<span className={"padding"}>Me</span>
<div className="edit-actions">
<div className={"permissions-dropdown"}>
- {targetDoc?.[`acl-${Doc.CurrentUserEmailNormalized}`]}
+ {effectiveAcls.every(acl => acl === effectiveAcls[0]) ? this.AclMap.get(effectiveAcls[0])! : "-multiple-"}
</div>
</div>
</div>
@@ -570,7 +587,7 @@ export class SharingManager extends React.Component<{}> {
// the list of groups shared with
const groupListMap: (Doc | { title: string })[] = groups.filter(({ title }) => docs.length > 1 ? commonKeys.includes(`acl-${normalizeEmail(StrCast(title))}`) : true);
- groupListMap.unshift({ title: "Public" }, { title: "Override" });
+ groupListMap.unshift({ title: "Public" });//, { title: "Override" });
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]);
@@ -622,9 +639,10 @@ export class SharingManager extends React.Component<{}> {
{<div className="share-container">
<div className="share-setup">
<Select
- className={"user-search"}
- placeholder={"Enter user or group name..."}
+ className="user-search"
+ placeholder="Enter user or group name..."
isMulti
+ isSearchable
closeMenuOnSelect={false}
options={options}
onChange={this.handleUsersChange}
@@ -648,16 +666,10 @@ export class SharingManager extends React.Component<{}> {
</div>
<div className="acl-container">
- <div className="myDocs-acls">
- <input type="checkbox" onChange={action(() => this.myDocAcls = !this.myDocAcls)} checked={this.myDocAcls} /> <label>My Docs</label>
- </div>
{Doc.UserDoc().noviceMode ? (null) :
<div className="layoutDoc-acls">
<input type="checkbox" onChange={action(() => this.layoutDocAcls = !this.layoutDocAcls)} checked={this.layoutDocAcls} /> <label>Layout</label>
</div>}
- <button className="distribute-button" onClick={() => this.distributeOverCollection()}>
- Distribute
- </button>
</div>
</div>
}