Skip to content

Commit

Permalink
Move contact sort selector to list header (#3103)
Browse files Browse the repository at this point in the history
* Move contact sort selector to list header, #989
  • Loading branch information
johnbotris committed Aug 11, 2021
1 parent c963b8b commit 4c4985c
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 42 deletions.
45 changes: 39 additions & 6 deletions src/contacts/view/ContactListView.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @flow
import m from "mithril"
import stream from "mithril/stream/stream.js"
import {ContactView} from "./ContactView"
import {List} from "../../gui/base/List"
import {load, loadAll} from "../../api/main/Entity"
Expand All @@ -12,7 +13,9 @@ import {NotFoundError} from "../../api/common/error/RestError"
import {size} from "../../gui/size"
import {locator} from "../../api/main/MainLocator"
import {GENERATED_MAX_ID} from "../../api/common/utils/EntityUtils";
import type {ContactComparator} from "./ContactGuiUtils"
import {ListColumnWrapper} from "../../gui/ListColumnWrapper"
import {DropDownSelectorN} from "../../gui/base/DropDownSelectorN"
import {compareContacts} from "./ContactGuiUtils"
import {ofClass} from "../../api/common/utils/PromiseUtils"

assertMainOrNode()
Expand All @@ -24,11 +27,14 @@ export class ContactListView {
contactView: ContactView;
list: List<Contact, ContactRow>;
view: Function;
contactComparator: boolean;
oncreate: Function;
onbeforeremove: Function;

constructor(contactListId: Id, contactView: ContactView, contactComparator: ContactComparator) {
constructor(contactListId: Id, contactView: ContactView) {
this.listId = contactListId
this.contactView = contactView

const sortByFirstName = stream(true)
this.list = new List({
rowHeight: size.list_row_height,
fetch: (startId, count) => {
Expand All @@ -52,8 +58,7 @@ export class ContactListView {
return null
}))
},
sortCompare: contactComparator,

sortCompare: (c1, c2) => compareContacts(c1, c2, sortByFirstName()),
elementSelected: (entities, elementClicked, selectionChanged, multiSelectionActive) => contactView.elementSelected(entities, elementClicked, selectionChanged, multiSelectionActive),
createVirtualRow: () => new ContactRow(),
showStatus: false,
Expand All @@ -69,8 +74,36 @@ export class ContactListView {
emptyMessage: lang.get("noContacts_msg")
})


this.view = (): VirtualElement => {
return m(this.list)
return m(ListColumnWrapper, {
headerContent: m(DropDownSelectorN, {
label: () => "Sort by",
selectedValue: sortByFirstName,
items: [
{
name: lang.get("firstName_placeholder"),
value: true
},
{
name: lang.get("lastName_placeholder"),
value: false
}
],
class: "mt-m ml mb-xs",
doShowBorder: false
}),
padHorizontal: false
}, m(this.list))
}

let sortModeChangedListener
this.oncreate = () => {
sortModeChangedListener = sortByFirstName.map(() => this.list.sort())
}

this.onbeforeremove = () => {
sortModeChangedListener.end(true)
}
}

Expand Down
35 changes: 5 additions & 30 deletions src/contacts/view/ContactView.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,7 @@ import type {ContactModel} from "../model/ContactModel"
import {createDropDownButton} from "../../gui/base/Dropdown";
import {ActionBar} from "../../gui/base/ActionBar"
import {SidebarSection} from "../../gui/SidebarSection"
import type {DropDownSelectorAttrs} from "../../gui/base/DropDownSelectorN"
import {DropDownSelectorN} from "../../gui/base/DropDownSelectorN"
import {compareContacts} from "./ContactGuiUtils"
import {ofClass, promiseMap} from "../../api/common/utils/PromiseUtils"

assertMainOrNode()

export class ContactView implements CurrentView {
Expand All @@ -66,27 +62,9 @@ export class ContactView implements CurrentView {
oncreate: Function;
onremove: Function;
_throttledSetUrl: (string) => void;
_doSortByFirstName: Stream<boolean>

constructor() {
this._doSortByFirstName = stream(true)
const sortSelectorAttrs: DropDownSelectorAttrs<boolean> = {
label: () => "Sort by",
selectedValue: this._doSortByFirstName,
items: [
{
name: lang.get("firstName_placeholder"),
value: true
},
{
name: lang.get("lastName_placeholder"),
value: false
}
],
}


const contactsExpanded = stream(true)
this._throttledSetUrl = throttleRoute()

this.folderColumn = new ViewColumn({
Expand All @@ -98,7 +76,6 @@ export class ContactView implements CurrentView {
click: () => this.createNewContact(),
},
content: [
m(".plr", m(DropDownSelectorN, sortSelectorAttrs)),
m(SidebarSection, {
name: () => getGroupInfoDisplayName(logins.getUserController().userGroupInfo)
}, this.createContactFoldersExpanderChildren())
Expand Down Expand Up @@ -415,17 +392,15 @@ export class ContactView implements CurrentView {
})
} else if (!this._contactList && args.listId) {
// we have to check if the given list id is correct
locator.contactModel.contactListId().then(contactListId => {
locator.contactModel.contactListId().then(async contactListId => {
if (args.listId !== contactListId) {
contactListId && this._setUrl(`/contact/${contactListId}`)
} else {
this._contactList = new ContactListView(args.listId, (this: any), (a, b) => compareContacts(a, b, this._doSortByFirstName())) // cast to avoid error in WebStorm
this._contactList.list.loadInitial(args.contactId)
this._doSortByFirstName.map(_ => {
this._contactList && this._contactList.list.sort()
})
this._contactList = new ContactListView(args.listId, this)
await this._contactList.list.loadInitial(args.contactId)
}
}).then(m.redraw)
m.redraw()
})
} else if (this._contactList && args.listId === this._contactList.listId && args.contactId
&& !this._contactList.list.isEntitySelected(args.contactId)) {
this._contactList.list.scrollToIdAndSelect(args.contactId)
Expand Down
6 changes: 4 additions & 2 deletions src/gui/ListColumnWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import m from "mithril"

export type ListColumnAttrs = {
headerContent: Children
headerContent: Children,
padHorizontal?: ?boolean
}

export class ListColumnWrapper implements MComponent<ListColumnAttrs> {
view(vnode: Vnode<ListColumnAttrs>): Children {
return m(".flex.flex-column.fill-absolute", [
m(".flex.flex-column.justify-center.plr-l.list-border-right.list-bg.list-header", vnode.attrs.headerContent),
m(".flex.flex-column.justify-center.list-border-right.list-bg.list-header"
+ (vnode.attrs.padHorizontal !== false ? ".plr-l" : ""), vnode.attrs.headerContent),
m(".rel.flex-grow", vnode.children)
])
}
Expand Down
6 changes: 4 additions & 2 deletions src/gui/base/DropDownSelectorN.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export type DropDownSelectorAttrs<T> = {
dropdownWidth?: number,
icon?: AllIconsEnum,
disabled?: boolean,
class?: string
class?: string,
doShowBorder?: ?boolean
}

export class DropDownSelectorN<T> implements MComponent<DropDownSelectorAttrs<T>> {
Expand All @@ -56,7 +57,8 @@ export class DropDownSelectorN<T> implements MComponent<DropDownSelectorAttrs<T>
icon: () => a.icon ? a.icon : BootIcons.Expand,
click: noOp,
colors: ButtonColors.DrawerNav
})
}),
doShowBorder: a.doShowBorder
})
}

Expand Down
8 changes: 6 additions & 2 deletions src/gui/base/TextFieldN.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export type TextFieldAttrs = {
class?: string,
disabled?: boolean,
oninput?: (value: string, input: HTMLInputElement) => mixed,
onclick?: clickHandler
onclick?: clickHandler,
doShowBorder?: ?boolean
}

export const Type = Object.freeze({
Expand Down Expand Up @@ -61,6 +62,9 @@ export class TextFieldN implements MComponent<TextFieldAttrs> {
const a = vnode.attrs
const labelBase = !this.active && a.value() === "" && !a.disabled && !this._didAutofill && !a.injectionsLeft
const labelTransitionSpeed = DefaultAnimationTime / 2
const doShowBorder = a.doShowBorder !== false
const borderWidth = this.active ? "2px" : "1px"
const borderColor = this.active ? theme.content_accent : theme.content_border
return m(".text-field.rel.overflow-hidden", {
id: vnode.attrs.id,
oncreate: (vnode) => this._domWrapper = vnode.dom,
Expand All @@ -83,7 +87,7 @@ export class TextFieldN implements MComponent<TextFieldAttrs> {
style: {
'min-height': px(size.button_height + 2), // 2 px border
'padding-bottom': this.active ? px(0) : px(1),
'border-bottom': this.active ? `2px solid ${theme.content_accent}` : `1px solid ${theme.content_border}`,
'border-bottom': doShowBorder ? `${borderWidth} solid ${borderColor}` : "",
},
}, [
a.injectionsLeft ? a.injectionsLeft() : null,
Expand Down

0 comments on commit 4c4985c

Please sign in to comment.