Show sort direction on sort menu
This commit is contained in:
parent
87413c3ad9
commit
b5053c5292
5 changed files with 76 additions and 61 deletions
|
@ -4,7 +4,6 @@ import { Block } from "../block"
|
|||
import { BlockIcons } from "../blockIcons"
|
||||
import { IPropertyOption } from "../board"
|
||||
import { BoardTree } from "../boardTree"
|
||||
import { ISortOption } from "../boardView"
|
||||
import { CardFilter } from "../cardFilter"
|
||||
import { Constants } from "../constants"
|
||||
import { Menu } from "../menu"
|
||||
|
@ -96,7 +95,7 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
Group by <span style={groupByStyle} id="groupByLabel">{boardTree.groupByProperty?.name}</span>
|
||||
</div>
|
||||
<div className={hasFilter ? "octo-button active" : "octo-button"} onClick={(e) => { this.filterClicked(e) }}>Filter</div>
|
||||
<div className={hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { this.sortClicked(e) }}>Sort</div>
|
||||
<div className={hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { OctoUtils.showSortMenu(e, mutator, boardTree) }}>Sort</div>
|
||||
{this.state.isSearching
|
||||
? <Editable
|
||||
ref={this.searchFieldRef}
|
||||
|
@ -275,32 +274,6 @@ class BoardComponent extends React.Component<Props, State> {
|
|||
pageController.showFilter(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
private async sortClicked(e: React.MouseEvent) {
|
||||
const { mutator, boardTree } = this.props
|
||||
const { activeView } = boardTree
|
||||
const { sortOptions } = activeView
|
||||
const sortOption = sortOptions.length > 0 ? sortOptions[0] : undefined
|
||||
|
||||
const propertyTemplates = boardTree.board.cardProperties
|
||||
Menu.shared.options = propertyTemplates.map((o) => { return { id: o.id, name: o.name } })
|
||||
Menu.shared.onMenuClicked = async (propertyId: string) => {
|
||||
let newSortOptions: ISortOption[] = []
|
||||
if (sortOption && sortOption.propertyId === propertyId) {
|
||||
// Already sorting by name, so reverse it
|
||||
newSortOptions = [
|
||||
{ propertyId, reversed: !sortOption.reversed }
|
||||
]
|
||||
} else {
|
||||
newSortOptions = [
|
||||
{ propertyId, reversed: false }
|
||||
]
|
||||
}
|
||||
|
||||
await mutator.changeViewSortOptions(activeView, newSortOptions)
|
||||
}
|
||||
Menu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
private async optionsClicked(e: React.MouseEvent) {
|
||||
const { boardTree } = this.props
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Block } from "../block"
|
|||
import { BlockIcons } from "../blockIcons"
|
||||
import { IPropertyTemplate } from "../board"
|
||||
import { BoardTree } from "../boardTree"
|
||||
import { ISortOption } from "../boardView"
|
||||
import { CsvExporter } from "../csvExporter"
|
||||
import { Menu } from "../menu"
|
||||
import { Mutator } from "../mutator"
|
||||
|
@ -90,7 +89,7 @@ class TableComponent extends React.Component<Props, State> {
|
|||
<div className="octo-spacer"></div>
|
||||
<div className="octo-button" onClick={(e) => { this.propertiesClicked(e) }}>Properties</div>
|
||||
<div className={ hasFilter ? "octo-button active" : "octo-button"} onClick={(e) => { this.filterClicked(e) }}>Filter</div>
|
||||
<div className={ hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { this.sortClicked(e) }}>Sort</div>
|
||||
<div className={ hasSort ? "octo-button active" : "octo-button"} onClick={(e) => { OctoUtils.showSortMenu(e, mutator, boardTree) }}>Sort</div>
|
||||
{this.state.isSearching
|
||||
? <Editable
|
||||
ref={this.searchFieldRef}
|
||||
|
@ -248,32 +247,6 @@ class TableComponent extends React.Component<Props, State> {
|
|||
pageController.showFilter(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
private async sortClicked(e: React.MouseEvent) {
|
||||
const { mutator, boardTree } = this.props
|
||||
const { activeView } = boardTree
|
||||
const { sortOptions } = activeView
|
||||
const sortOption = sortOptions.length > 0 ? sortOptions[0] : undefined
|
||||
|
||||
const propertyTemplates = boardTree.board.cardProperties
|
||||
Menu.shared.options = propertyTemplates.map((o) => { return { id: o.id, name: o.name } })
|
||||
Menu.shared.onMenuClicked = async (propertyId: string) => {
|
||||
let newSortOptions: ISortOption[] = []
|
||||
if (sortOption && sortOption.propertyId === propertyId) {
|
||||
// Already sorting by name, so reverse it
|
||||
newSortOptions = [
|
||||
{ propertyId, reversed: !sortOption.reversed }
|
||||
]
|
||||
} else {
|
||||
newSortOptions = [
|
||||
{ propertyId, reversed: false }
|
||||
]
|
||||
}
|
||||
|
||||
await mutator.changeViewSortOptions(activeView, newSortOptions)
|
||||
}
|
||||
Menu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
private async optionsClicked(e: React.MouseEvent) {
|
||||
const { boardTree } = this.props
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ type MenuOption = {
|
|||
id: string,
|
||||
name: string,
|
||||
isOn?: boolean,
|
||||
icon?: "checked" | "sortUp" | "sortDown" | undefined,
|
||||
type?: "separator" | "color" | "submenu" | "switch" | undefined
|
||||
}
|
||||
|
||||
|
@ -54,6 +55,20 @@ class Menu {
|
|||
this.showSubMenu(rect.right - bodyRect.left, rect.top - bodyRect.top, option.id)
|
||||
}
|
||||
} else {
|
||||
|
||||
if (option.icon) {
|
||||
let iconName: string
|
||||
switch (option.icon) {
|
||||
case "checked": { iconName = "imageMenuCheck"; break }
|
||||
case "sortUp": { iconName = "imageMenuSortUp"; break }
|
||||
case "sortDown": { iconName = "imageMenuSortDown"; break }
|
||||
default: { Utils.assertFailure(`Unsupported menu icon: ${option.icon}`) }
|
||||
}
|
||||
if (iconName) {
|
||||
optionElement.appendChild(Utils.htmlToElement(`<div class="${iconName}" style="float: right;"></div>`))
|
||||
}
|
||||
}
|
||||
|
||||
optionElement.onmouseenter = () => {
|
||||
this.hideSubMenu()
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react"
|
||||
import { IPropertyTemplate } from "./board"
|
||||
import { BoardTree } from "./boardTree"
|
||||
import { BoardView } from "./boardView"
|
||||
import { BoardView, ISortOption } from "./boardView"
|
||||
import { Editable } from "./components/editable"
|
||||
import { Menu, MenuOption } from "./menu"
|
||||
import { Mutator } from "./mutator"
|
||||
|
@ -188,6 +188,37 @@ class OctoUtils {
|
|||
const nextBlock = blocks[index + 1]
|
||||
return (block.order + nextBlock.order) / 2
|
||||
}
|
||||
|
||||
static showSortMenu(e: React.MouseEvent, mutator: Mutator, boardTree: BoardTree) {
|
||||
const { activeView } = boardTree
|
||||
const { sortOptions } = activeView
|
||||
const sortOption = sortOptions.length > 0 ? sortOptions[0] : undefined
|
||||
|
||||
const propertyTemplates = boardTree.board.cardProperties
|
||||
Menu.shared.options = propertyTemplates.map((o) => {
|
||||
return {
|
||||
id: o.id,
|
||||
name: o.name,
|
||||
icon: (sortOption.propertyId === o.id) ? sortOption.reversed ? "sortUp" : "sortDown" : undefined
|
||||
}
|
||||
})
|
||||
Menu.shared.onMenuClicked = async (propertyId: string) => {
|
||||
let newSortOptions: ISortOption[] = []
|
||||
if (sortOption && sortOption.propertyId === propertyId) {
|
||||
// Already sorting by name, so reverse it
|
||||
newSortOptions = [
|
||||
{ propertyId, reversed: !sortOption.reversed }
|
||||
]
|
||||
} else {
|
||||
newSortOptions = [
|
||||
{ propertyId, reversed: false }
|
||||
]
|
||||
}
|
||||
|
||||
await mutator.changeViewSortOptions(activeView, newSortOptions)
|
||||
}
|
||||
Menu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
}
|
||||
|
||||
export { OctoUtils }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
|
||||
.imageAdd {
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:4;" stroke-opacity="50%"><polyline points="30,50 70,50" /><polyline points="50,30 50,70" /></svg>');
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:4;" fill="none" stroke-opacity="50%"><polyline points="30,50 70,50" /><polyline points="50,30 50,70" /></svg>');
|
||||
background-size: 100% 100%;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
|
@ -19,9 +19,32 @@
|
|||
min-height: 24px;
|
||||
}
|
||||
|
||||
/*-- Menu images --*/
|
||||
|
||||
.imageSubmenuTriangle {
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><polygon points="50,35 75,50 50,65" style="fill:black;stroke:none;" fill-opacity="70%" /></svg>');
|
||||
background-size: 100% 100%;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.imageMenuCheck {
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:8;" fill="none" stroke-opacity="50%"><polyline points="20,60 40,80 80,40" /></svg>');
|
||||
background-size: 100% 100%;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.imageMenuSortUp {
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:8;" fill="none" stroke-opacity="50%"><polyline points="50,20 50,80" /><polyline points="30,40 50,20 70,40" /></svg>');
|
||||
background-size: 100% 100%;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
.imageMenuSortDown {
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="stroke:black;stroke-width:8;" fill="none" stroke-opacity="50%"><polyline points="50,20 50,80" /><polyline points="30,60 50,80 70,60" /></svg>');
|
||||
background-size: 100% 100%;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue