aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/GroupManager.scss99
-rw-r--r--src/client/util/GroupManager.tsx74
-rw-r--r--src/client/util/GroupMemberView.scss27
-rw-r--r--src/client/util/GroupMemberView.tsx21
-rw-r--r--src/client/util/SharingManager.scss23
-rw-r--r--src/client/util/SharingManager.tsx68
6 files changed, 215 insertions, 97 deletions
diff --git a/src/client/util/GroupManager.scss b/src/client/util/GroupManager.scss
index 2da1f0d95..8a2c616b1 100644
--- a/src/client/util/GroupManager.scss
+++ b/src/client/util/GroupManager.scss
@@ -20,9 +20,10 @@
// border: none;
padding: 8px;
min-width: 100%;
- margin: 4px 0 4px 0;
+ // margin: 4px 0 4px 0;
border: 1px solid hsl(0, 0%, 80%);
outline: none;
+ height: 30;
&:focus {
// border: unset;
@@ -100,59 +101,69 @@
}
}
+ .main-container {
+ display: flex;
+ flex-direction: column;
- .group-body {
- // display: flex;
- justify-content: space-between;
- // max-height: 80%;
- height: 100%;
- background-color: #e8e8e8;
- // flex-direction: column;
+ .sort-groups {
+ text-align: left;
+ margin-left: 5;
+ cursor: pointer;
+ }
- // padding-left: 1em;
- padding-right: 1em;
- justify-content: space-around;
- text-align: left;
+ .group-body {
+ // display: flex;
+ justify-content: space-between;
+ // max-height: 80%;
+ height: 220;
+ background-color: #e8e8e8;
+ // flex-direction: column;
+
+ // padding-left: 1em;
+ padding-right: 1em;
+ justify-content: space-around;
+ text-align: left;
- overflow-y: auto;
- width: 100%;
+ overflow-y: auto;
+ width: 100%;
- .group-row {
- display: flex;
- // position: relative;
- margin-bottom: 5px;
- min-height: 30px;
- // border: 1px solid;
- // border-radius: 10px;
- align-items: center;
-
- .group-name {
+ .group-row {
+ display: flex;
// position: relative;
- max-width: 65%;
- // left: 10;
- margin: 0 10;
- color: black;
- }
+ margin-bottom: 5px;
+ min-height: 30px;
+ // border: 1px solid;
+ // border-radius: 10px;
+ align-items: center;
+
+ .group-name {
+ // position: relative;
+ max-width: 65%;
+ // left: 10;
+ margin: 0 10;
+ color: black;
+ }
- .group-info {
- cursor: pointer;
+ .group-info {
+ cursor: pointer;
+ }
+
+ button {
+ position: absolute;
+ width: 30%;
+ right: 2;
+ margin-top: 0;
+ }
}
- button {
- position: absolute;
- width: 30%;
- right: 2;
- margin-top: 0;
+ input {
+ border-radius: 5px;
+ border: none;
+ padding: 4px;
+ min-width: 100%;
+ margin: 2px 0;
}
- }
- input {
- border-radius: 5px;
- border: none;
- padding: 4px;
- min-width: 100%;
- margin: 2px 0;
}
-
}
} \ No newline at end of file
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index f2b502ae0..2d8930660 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -38,31 +38,38 @@ export default class GroupManager extends React.Component<{}> {
private inputRef: React.RefObject<HTMLInputElement> = React.createRef(); // the ref for the input box.
private currentUserGroups: string[] = [];
@observable private buttonColour: "#979797" | "black" = "#979797";
+ @observable private groupSort: "ascending" | "descending" | "none" = "none";
+
constructor(props: Readonly<{}>) {
super(props);
GroupManager.Instance = this;
}
+ componentDidMount() {
+ this.populateUsers();
+ }
+
/**
* Fetches the list of users stored on the database.
*/
populateUsers = async () => {
+ runInAction(() => this.users = []);
const userList = await RequestPromise.get(Utils.prepend("/getUsers"));
const raw = JSON.parse(userList) as User[];
const evaluating = raw.map(async user => {
- const isCandidate = user.email !== Doc.CurrentUserEmail;
- if (isCandidate) {
- const userDocument = await DocServer.GetRefField(user.userDocumentId);
- if (userDocument instanceof Doc) {
- const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
- runInAction(() => {
- if (notificationDoc instanceof Doc) {
- this.users.push(user.email);
- }
- });
- }
+ // const isCandidate = user.email !== Doc.CurrentUserEmail;
+ // if (isCandidate) {
+ const userDocument = await DocServer.GetRefField(user.userDocumentId);
+ if (userDocument instanceof Doc) {
+ const notificationDoc = await Cast(userDocument.rightSidebarCollection, Doc);
+ runInAction(() => {
+ if (notificationDoc instanceof Doc) {
+ this.users.push(user.email);
+ }
+ });
}
+ // }
});
return Promise.all(evaluating);
}
@@ -99,7 +106,7 @@ export default class GroupManager extends React.Component<{}> {
close = () => {
this.isOpen = false;
this.currentGroup = undefined;
- this.users = [];
+ // this.users = [];
this.createGroupModalOpen = false;
}
@@ -304,6 +311,7 @@ export default class GroupManager extends React.Component<{}> {
</div>
</div>
<input
+ className="group-input"
ref={this.inputRef}
onKeyDown={this.handleKeyDown}
type="text"
@@ -357,6 +365,17 @@ export default class GroupManager extends React.Component<{}> {
* A getter that @returns the main interface for the GroupManager.
*/
private get groupInterface() {
+
+ const sortGroups = (d1: Doc, d2: Doc) => {
+ const g1 = StrCast(d1.groupName);
+ const g2 = StrCast(d2.groupName);
+
+ return g1 < g2 ? -1 : g1 === g2 ? 0 : 1;
+ };
+
+ let groups = this.getAllGroups();
+ groups = this.groupSort === "ascending" ? groups.sort(sortGroups) : this.groupSort === "descending" ? groups.sort(sortGroups).reverse() : groups;
+
return (
<div className="group-interface">
{this.groupCreationModal}
@@ -375,19 +394,30 @@ export default class GroupManager extends React.Component<{}> {
<FontAwesomeIcon icon={fa.faTimes} color={"black"} size={"lg"} />
</div>
</div>
- <div className="group-body">
- {this.getAllGroups().map(group =>
- <div className="group-row">
- <div className="group-name" >{group.groupName}</div>
- <div className="group-info" onClick={action(() => this.currentGroup = group)}>
- <FontAwesomeIcon icon={fa.faInfoCircle} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} />
- </div>
- {/* <button onClick={action(() => this.currentGroup = group)}>
+ <div className="main-container">
+ <div
+ className="sort-groups"
+ onClick={action(() => this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}>
+ Name {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""} {/* → */}
+ </div>
+ <div className="group-body">
+ {groups.map(group =>
+ <div
+ className="group-row"
+ key={StrCast(group.groupName)}
+ >
+ <div className="group-name" >{group.groupName}</div>
+ <div className="group-info" onClick={action(() => this.currentGroup = group)}>
+ <FontAwesomeIcon icon={fa.faInfoCircle} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} />
+ </div>
+ {/* <button onClick={action(() => this.currentGroup = group)}>
{this.hasEditAccess(group) ? "Edit" : "View"}
</button> */}
- </div>
- )}
+ </div>
+ )}
+ </div>
</div>
+
</div>
);
}
diff --git a/src/client/util/GroupMemberView.scss b/src/client/util/GroupMemberView.scss
index 9bdf832e0..a34e5b989 100644
--- a/src/client/util/GroupMemberView.scss
+++ b/src/client/util/GroupMemberView.scss
@@ -8,7 +8,7 @@
// color: black;
hr {
- margin-top: 10;
+ margin-top: 20;
}
button {
@@ -17,7 +17,7 @@
border-radius: 5px;
border: 0px;
color: #fcfbf7;
- // text-transform: uppercase;
+ text-transform: none;
letter-spacing: 2px;
font-size: 75%;
padding: 10px;
@@ -45,15 +45,33 @@
outline: none;
color: black;
margin-top: -5;
+ height: 20;
+ text-overflow: ellipsis;
+
+ &:hover {
+ text-overflow: visible;
+ overflow-x: auto;
+ }
+ }
+
+ .sort-emails {
+ float: left;
+ margin: -18 0 0 5;
+ cursor: pointer;
}
.group-buttons {
display: flex;
margin-top: 5;
+ margin-bottom: 25;
.add-member-dropdown {
width: 65%;
margin: 0 5;
+
+ input {
+ height: 30;
+ }
}
}
}
@@ -61,7 +79,7 @@
.editing-contents {
overflow-y: auto;
// max-height: 67%;
- height: 67%;
+ height: 65%;
width: 100%;
color: black;
margin-top: -15px;
@@ -70,6 +88,7 @@
display: flex;
align-items: center;
margin-bottom: 10px;
+ position: relative;
// border: 1px solid;
// border-radius: 10px;
@@ -83,7 +102,7 @@
.remove-button {
position: absolute;
- right: 30;
+ right: 10;
cursor: pointer;
}
}
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx
index 2462ee4d5..ebe9830ba 100644
--- a/src/client/util/GroupMemberView.tsx
+++ b/src/client/util/GroupMemberView.tsx
@@ -4,7 +4,7 @@ import { observer } from "mobx-react";
import GroupManager, { UserOptions } from "./GroupManager";
import { library } from "@fortawesome/fontawesome-svg-core";
import { StrCast } from "../../fields/Types";
-import { action } from "mobx";
+import { action, observable } from "mobx";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import * as fa from '@fortawesome/free-solid-svg-icons';
import Select from "react-select";
@@ -21,10 +21,17 @@ interface GroupMemberViewProps {
@observer
export default class GroupMemberView extends React.Component<GroupMemberViewProps> {
+ @observable private memberSort: "ascending" | "descending" | "none" = "none";
private get editingInterface() {
- const members: string[] = this.props.group ? JSON.parse(StrCast(this.props.group.members)) : [];
+ let members: string[] = this.props.group ? JSON.parse(StrCast(this.props.group.members)) : [];
+ members = this.memberSort === "ascending" ? members.sort() : this.memberSort === "descending" ? members.sort().reverse() : members;
+
const options: UserOptions[] = this.props.group ? GroupManager.Instance.options.filter(option => !(JSON.parse(StrCast(this.props.group.members)) as string[]).includes(option.value)) : [];
+ console.log(this.props.group, options);
+ console.log(GroupManager.Instance.options);
+
+
return (!this.props.group ? null :
<div className="editing-interface">
<div className="editing-header">
@@ -59,11 +66,19 @@ export default class GroupMemberView extends React.Component<GroupMemberViewProp
<button onClick={() => GroupManager.Instance.deleteGroup(this.props.group)}>Delete group</button>
</div> :
null}
+ <div
+ className="sort-emails"
+ onClick={action(() => this.memberSort = this.memberSort === "ascending" ? "descending" : this.memberSort === "descending" ? "none" : "ascending")}>
+ Emails {this.memberSort === "ascending" ? "↑" : this.memberSort === "descending" ? "↓" : ""} {/* → */}
+ </div>
</div>
<hr />
<div className="editing-contents">
{members.map(member => (
- <div className="editing-row">
+ <div
+ className="editing-row"
+ key={member}
+ >
<div className="user-email">
{member}
</div>
diff --git a/src/client/util/SharingManager.scss b/src/client/util/SharingManager.scss
index ce23ce413..572b94ffb 100644
--- a/src/client/util/SharingManager.scss
+++ b/src/client/util/SharingManager.scss
@@ -1,4 +1,4 @@
-@import "../views/globalCssVariables";
+// @import "../views/globalCssVariables";
.sharing-interface {
// display: flex;
@@ -40,6 +40,10 @@
.user-search {
width: 90%;
+
+ input {
+ height: 30;
+ }
}
.permissions-select {
@@ -68,6 +72,12 @@
display: flex;
flex-direction: column;
+ .user-sort {
+ text-align: left;
+ margin-left: 10;
+ cursor: pointer;
+ }
+
.share-title {
margin-top: 20px;
margin-bottom: 20px;
@@ -103,12 +113,12 @@
}
button {
- background: $darker-alt-accent;
+ // background: $darker-alt-accent;
outline: none;
border-radius: 5px;
border: 0px;
color: #fcfbf7;
- text-transform: uppercase;
+ text-transform: none;
letter-spacing: 2px;
font-size: 75%;
padding: 0 10;
@@ -173,6 +183,10 @@
padding: 0;
align-items: center;
+ .group-info {
+ cursor: pointer;
+ }
+
&:hover .padding {
white-space: unset;
}
@@ -183,12 +197,13 @@
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
- max-width: 48%;
+ max-width: 40%;
}
.permissions-dropdown {
border: none;
height: 25;
+ background-color: #e8e8e8;
}
.edit-actions {
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 6c7c634eb..817b7c6b8 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -75,6 +75,9 @@ export default class SharingManager extends React.Component<{}> {
@observable private overlayOpacity = 0.4;
@observable private selectedUsers: UserOptions[] | null = null;
@observable private permissions: SharingPermissions = SharingPermissions.Edit;
+ @observable private individualSort: "ascending" | "descending" | "none" = "none";
+ @observable private groupSort: "ascending" | "descending" | "none" = "none";
+
// private get linkVisible() {
// return this.sharingDoc ? this.sharingDoc[PublicKey] !== SharingPermissions.None : false;
@@ -151,8 +154,6 @@ export default class SharingManager extends React.Component<{}> {
// group.docsShared ? Doc.IndexOf(target, DocListCast(group.docsShared)) === -1 && (group.docsShared as List<Doc>).push(target) : group.docsShared = new List<Doc>([target]);
users.forEach(({ notificationDoc }) => {
-
- DocListCastAsync(notificationDoc[storage]).then(res => console.log(res));
DocListCastAsync(notificationDoc[storage]).then(resolved => {
if (permission !== SharingPermissions.None) Doc.IndexOf(target, resolved!) === -1 && Doc.AddDocToList(notificationDoc, storage, target);
else Doc.IndexOf(target, resolved!) !== -1 && Doc.RemoveDocFromList(notificationDoc, storage, target);
@@ -353,28 +354,44 @@ export default class SharingManager extends React.Component<{}> {
this.selectedUsers = null;
}
+ sortUsers = (u1: ValidatedUser, u2: ValidatedUser) => {
+ const { email: e1 } = u1.user;
+ const { email: e2 } = u2.user;
+ return e1 < e2 ? -1 : e1 === e2 ? 0 : 1;
+ }
+
+ sortGroups = (group1: Doc, group2: Doc) => {
+ const g1 = StrCast(group1.groupName);
+ const g2 = StrCast(group2.groupName);
+ return g1 < g2 ? -1 : g1 === g2 ? 0 : 1;
+ }
+
private get sharingInterface() {
- const existOtherUsers = this.users.length > 0;
- const existGroups = GroupManager.Instance?.getAllGroups().length > 0;
- // const manager = this.sharingDoc!;
+ const groupList = GroupManager.Instance?.getAllGroups() || [];
+
+ const sortedUsers = this.users.sort(this.sortUsers)
+ .map(({ user: { email } }) => ({ label: email, value: "!indType/" + email }));
+ const sortedGroups = groupList.sort(this.sortGroups)
+ .map(({ groupName }) => ({ label: StrCast(groupName), value: "!groupType/" + StrCast(groupName) }));
const options: GroupOptions[] = GroupManager.Instance ?
[
{
label: 'Individuals',
- options: this.users.map(({ user: { email } }) => ({ label: email, value: "!indType/" + email }))
+ options: sortedUsers
},
{
label: 'Groups',
- options: GroupManager.Instance.getAllGroups().map(({ groupName }) => ({ label: StrCast(groupName), value: "!groupType/" + StrCast(groupName) }))
+ options: sortedGroups
}
]
: [];
- console.log(this.users);
+ const users = this.individualSort === "ascending" ? this.users.sort(this.sortUsers) : this.individualSort === "descending" ? this.users.sort(this.sortUsers).reverse() : this.users;
+ const groups = this.groupSort === "ascending" ? groupList.sort(this.sortGroups) : this.groupSort === "descending" ? groupList.sort(this.sortGroups).reverse() : groupList;
- const userListContents: (JSX.Element | null)[] = this.users.map(({ user, notificationDoc }) => { // can't use async here
+ const userListContents: (JSX.Element | null)[] = users.map(({ user, notificationDoc }) => { // can't use async here
const userKey = user.email.replace('.', '_');
// const userKey = user.userDocumentId;
const permissions = StrCast(this.targetDoc?.[`ACL-${userKey}`], SharingPermissions.None);
@@ -422,7 +439,7 @@ export default class SharingManager extends React.Component<{}> {
)
);
- const groupListContents = GroupManager.Instance?.getAllGroups().map(group => {
+ const groupListContents = groups.map(group => {
const permissions = StrCast(this.targetDoc?.[`ACL-${StrCast(group.groupName)}`], SharingPermissions.None);
// const color = ColorMapping.get(permissions);
@@ -431,7 +448,10 @@ export default class SharingManager extends React.Component<{}> {
key={StrCast(group.groupName)}
className={"container"}
>
- <span className={"padding"}>{group.groupName}</span>
+ <div className={"padding"}>{group.groupName}</div>
+ <div className="group-info" onClick={action(() => GroupManager.Instance.currentGroup = group)}>
+ <FontAwesomeIcon icon={fa.faInfoCircle} color={"#e8e8e8"} size={"sm"} style={{ backgroundColor: "#1e89d7", borderRadius: "100%", border: "1px solid #1e89d7" }} />
+ </div>
<div className="edit-actions">
<select
className={"permissions-dropdown"}
@@ -441,14 +461,13 @@ export default class SharingManager extends React.Component<{}> {
>
{this.sharingOptions}
</select>
- <button onClick={action(() => GroupManager.Instance.currentGroup = group)}>Edit</button>
</div>
</div>
);
});
- const displayUserList = userListContents?.every(user => user === null);
- const displayGroupList = groupListContents?.every(group => group === null);
+ const displayUserList = !userListContents?.every(user => user === null);
+ const displayGroupList = !groupListContents?.every(group => group === null);
return (
<div className={"sharing-interface"}>
@@ -515,10 +534,14 @@ export default class SharingManager extends React.Component<{}> {
}
<div className="main-container">
<div className={"individual-container"}>
- <div>Individuals</div>
- <div className={"users-list"} style={{ display: displayUserList ? "flex" : "block" }}>{/*200*/}
+ <div
+ className="user-sort"
+ onClick={action(() => this.individualSort = this.individualSort === "ascending" ? "descending" : this.individualSort === "descending" ? "none" : "ascending")}>
+ Individuals {this.individualSort === "ascending" ? "↑" : this.individualSort === "descending" ? "↓" : ""} {/* → */}
+ </div>
+ <div className={"users-list"} style={{ display: !displayUserList ? "flex" : "block" }}>{/*200*/}
{
- displayUserList ?
+ !displayUserList ?
<div
className={"none"}
>
@@ -530,10 +553,15 @@ export default class SharingManager extends React.Component<{}> {
</div>
</div>
<div className={"group-container"}>
- <div>Groups</div>
- <div className={"groups-list"} style={{ display: displayGroupList ? "flex" : "block" }}>{/*200*/}
+ <div
+ className="user-sort"
+ onClick={action(() => this.groupSort = this.groupSort === "ascending" ? "descending" : this.groupSort === "descending" ? "none" : "ascending")}>
+ Groups {this.groupSort === "ascending" ? "↑" : this.groupSort === "descending" ? "↓" : ""} {/* → */}
+
+ </div>
+ <div className={"groups-list"} style={{ display: !displayGroupList ? "flex" : "block" }}>{/*200*/}
{
- displayGroupList ?
+ !displayGroupList ?
<div
className={"none"}
>