From 66e59d3029195b82bd06216ecc2d3ac4efa24775 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Thu, 8 Oct 2020 20:09:34 -0700
Subject: [PATCH 01/34] Seach text. WIP
---
src/client/boardPage.tsx | 5 ++++
src/client/boardTree.ts | 20 ++++++++++++++
src/client/components/boardComponent.tsx | 35 +++++++++++++++++++++---
src/client/octoTypes.ts | 1 +
4 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/src/client/boardPage.tsx b/src/client/boardPage.tsx
index c7334e3d5..8bb1334e3 100644
--- a/src/client/boardPage.tsx
+++ b/src/client/boardPage.tsx
@@ -227,6 +227,11 @@ class BoardPage implements IPageController {
this.filterAnchorElement = ahchorElement
this.render()
}
+
+ setSearchText(text?: string) {
+ this.boardTree.setSearchText(text)
+ this.render()
+ }
}
export { BoardPage }
diff --git a/src/client/boardTree.ts b/src/client/boardTree.ts
index 74c89dfbb..10459a5bf 100644
--- a/src/client/boardTree.ts
+++ b/src/client/boardTree.ts
@@ -17,6 +17,7 @@ class BoardTree {
activeView?: BoardView
groupByProperty?: IPropertyTemplate
+ private searchText?: string
private allCards: IBlock[] = []
get allBlocks(): IBlock[] {
return [this.board, ...this.views, ...this.allCards]
@@ -93,8 +94,18 @@ class BoardTree {
this.applyFilterSortAndGroup()
}
+ getSearchText(): string | undefined {
+ return this.searchText
+ }
+
+ setSearchText(text?: string) {
+ this.searchText = text
+ this.applyFilterSortAndGroup()
+ }
+
applyFilterSortAndGroup() {
this.cards = this.filterCards(this.allCards)
+ this.cards = this.searchFilterCards(this.cards)
this.cards = this.sortCards(this.cards)
if (this.activeView.groupById) {
@@ -104,6 +115,15 @@ class BoardTree {
}
}
+ private searchFilterCards(cards: IBlock[]) {
+ const { searchText } = this
+ if (!searchText) { return cards.slice() }
+
+ return cards.filter(card => {
+ if (card.title?.toLowerCase().indexOf(searchText) !== -1) { return true }
+ })
+ }
+
private setGroupByProperty(propertyId: string) {
const { board } = this
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index 1b75c6ef3..ef1fca990 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -25,15 +25,26 @@ type Props = {
type State = {
isHoverOnCover: boolean
+ isSearching: boolean
}
class BoardComponent extends React.Component {
private draggedCard: IBlock
private draggedHeaderOption: IPropertyOption
+ private searchFieldRef = React.createRef()
constructor(props: Props) {
super(props)
- this.state = { isHoverOnCover: false }
+ this.state = {
+ isHoverOnCover: false,
+ isSearching: false
+ }
+ }
+
+ componentDidUpdate(prevPros: Props, prevState: State) {
+ if (this.state.isSearching && !prevState.isSearching) {
+ this.searchFieldRef.current.focus()
+ }
}
render() {
@@ -87,9 +98,12 @@ class BoardComponent extends React.Component {
{ this.groupByClicked(e) }}>
Group by {boardTree.groupByProperty?.name}
- { this.filterClicked(e) }}>Filter
- { this.sortClicked(e) }}>Sort
- Search
+ { this.filterClicked(e) }}>Filter
+ { this.sortClicked(e) }}>Sort
+ {this.state.isSearching
+ ? { this.searchChanged(text) }} onKeyDown={(e) => { this.onSearchKeyDown(e) }}>
+ : { this.setState({ ...this.state, isSearching: true }) }}>Search
+ }
{ this.optionsClicked(e) }}>
{ this.addCard(undefined) }}>New
@@ -380,6 +394,19 @@ class BoardComponent extends React.Component {
await mutator.changePropertyOptionOrder(board, boardTree.groupByProperty, draggedHeaderOption, destIndex)
}
}
+
+ onSearchKeyDown(e: React.KeyboardEvent) {
+ if (e.keyCode === 27) { // ESC: Clear search
+ this.searchFieldRef.current.text = ""
+ this.setState({...this.state, isSearching: false})
+ this.props.pageController.setSearchText(undefined)
+ e.preventDefault()
+ }
+ }
+
+ searchChanged(text?: string) {
+ this.props.pageController.setSearchText(text)
+ }
}
export { BoardComponent }
diff --git a/src/client/octoTypes.ts b/src/client/octoTypes.ts
index 1a3f994c2..026046329 100644
--- a/src/client/octoTypes.ts
+++ b/src/client/octoTypes.ts
@@ -26,6 +26,7 @@ interface IPageController {
showCard(card: IBlock): Promise
showView(viewId: string): void
showFilter(anchorElement?: HTMLElement): void
+ setSearchText(text?: string): void
}
export { IProperty, IBlock, IPageController }
From c98ae89b505d5069a244728397a72fa2fe63bd32 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Thu, 8 Oct 2020 20:20:02 -0700
Subject: [PATCH 02/34] Search
---
src/client/components/boardComponent.tsx | 9 +++++++--
src/client/components/editable.tsx | 1 -
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index ef1fca990..c6f41de65 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -101,7 +101,12 @@ class BoardComponent extends React.Component {
{ this.filterClicked(e) }}>Filter
{ this.sortClicked(e) }}>Sort
{this.state.isSearching
- ? { this.searchChanged(text) }} onKeyDown={(e) => { this.onSearchKeyDown(e) }}>
+ ? { this.searchChanged(text) }}
+ onKeyDown={(e) => { this.onSearchKeyDown(e) }}>
: { this.setState({ ...this.state, isSearching: true }) }}>Search
}
{ this.optionsClicked(e) }}>
@@ -398,7 +403,7 @@ class BoardComponent extends React.Component {
onSearchKeyDown(e: React.KeyboardEvent) {
if (e.keyCode === 27) { // ESC: Clear search
this.searchFieldRef.current.text = ""
- this.setState({...this.state, isSearching: false})
+ this.setState({ ...this.state, isSearching: false })
this.props.pageController.setSearchText(undefined)
e.preventDefault()
}
diff --git a/src/client/components/editable.tsx b/src/client/components/editable.tsx
index 5b7b1e028..0c388ff55 100644
--- a/src/client/components/editable.tsx
+++ b/src/client/components/editable.tsx
@@ -102,7 +102,6 @@ class Editable extends React.Component {
this.text = newText
this.elementRef.current.classList.remove("active")
-
if (onBlur) { onBlur() }
}}
From 0bccdc26e91d7c8e28156924f3ae8860ba13935c Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Thu, 8 Oct 2020 20:24:34 -0700
Subject: [PATCH 03/34] Search in TableComponent as well
---
src/client/components/boardComponent.tsx | 5 +---
src/client/components/tableComponent.tsx | 33 ++++++++++++++++++++++--
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index c6f41de65..89acd61e7 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -35,10 +35,7 @@ class BoardComponent extends React.Component {
constructor(props: Props) {
super(props)
- this.state = {
- isHoverOnCover: false,
- isSearching: false
- }
+ this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText() }
}
componentDidUpdate(prevPros: Props, prevState: State) {
diff --git a/src/client/components/tableComponent.tsx b/src/client/components/tableComponent.tsx
index a7328af42..5177099ad 100644
--- a/src/client/components/tableComponent.tsx
+++ b/src/client/components/tableComponent.tsx
@@ -23,16 +23,24 @@ type Props = {
type State = {
isHoverOnCover: boolean
+ isSearching: boolean
}
class TableComponent extends React.Component {
private draggedHeaderTemplate: IPropertyTemplate
private cardIdToRowMap = new Map>()
private cardIdToFocusOnRender: string
+ private searchFieldRef = React.createRef()
constructor(props: Props) {
super(props)
- this.state = { isHoverOnCover: false }
+ this.state = { isHoverOnCover: false, isSearching: !!this.props.boardTree?.getSearchText() }
+ }
+
+ componentDidUpdate(prevPros: Props, prevState: State) {
+ if (this.state.isSearching && !prevState.isSearching) {
+ this.searchFieldRef.current.focus()
+ }
}
render() {
@@ -83,7 +91,15 @@ class TableComponent extends React.Component {
{ this.propertiesClicked(e) }}>Properties
{ this.filterClicked(e) }}>Filter
{ this.sortClicked(e) }}>Sort
- Search
+ {this.state.isSearching
+ ? { this.searchChanged(text) }}
+ onKeyDown={(e) => { this.onSearchKeyDown(e) }}>
+ : { this.setState({ ...this.state, isSearching: true }) }}>Search
+ }
{ this.addCard(true) }}>New
@@ -401,6 +417,19 @@ class TableComponent extends React.Component {
const destIndex = template ? board.cardProperties.indexOf(template) : 0
await mutator.changePropertyTemplateOrder(board, draggedHeaderTemplate, destIndex)
}
+
+ onSearchKeyDown(e: React.KeyboardEvent) {
+ if (e.keyCode === 27) { // ESC: Clear search
+ this.searchFieldRef.current.text = ""
+ this.setState({ ...this.state, isSearching: false })
+ this.props.pageController.setSearchText(undefined)
+ e.preventDefault()
+ }
+ }
+
+ searchChanged(text?: string) {
+ this.props.pageController.setSearchText(text)
+ }
}
export { TableComponent }
From c6463e55349961413936ce1a0abaa9ba7f44a03c Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Thu, 8 Oct 2020 21:05:57 -0700
Subject: [PATCH 04/34] Search color
---
src/client/components/boardComponent.tsx | 1 +
src/client/components/tableComponent.tsx | 1 +
2 files changed, 2 insertions(+)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index 89acd61e7..ba5343b1c 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -102,6 +102,7 @@ class BoardComponent extends React.Component {
ref={this.searchFieldRef}
text={boardTree.getSearchText()}
placeholderText="Search text"
+ style={{ color: "#000000" }}
onChanged={(text) => { this.searchChanged(text) }}
onKeyDown={(e) => { this.onSearchKeyDown(e) }}>
: { this.setState({ ...this.state, isSearching: true }) }}>Search
diff --git a/src/client/components/tableComponent.tsx b/src/client/components/tableComponent.tsx
index 5177099ad..bd05ea44c 100644
--- a/src/client/components/tableComponent.tsx
+++ b/src/client/components/tableComponent.tsx
@@ -96,6 +96,7 @@ class TableComponent extends React.Component {
ref={this.searchFieldRef}
text={boardTree.getSearchText()}
placeholderText="Search text"
+ style={{ color: "#000000" }}
onChanged={(text) => { this.searchChanged(text) }}
onKeyDown={(e) => { this.onSearchKeyDown(e) }}>
: { this.setState({ ...this.state, isSearching: true }) }}>Search
From ae93fe22ced044f7fd4115d445e7ed70013bc044 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 08:52:40 -0700
Subject: [PATCH 05/34] Add Go WebSocket method comments
---
server/main/websockets.go | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/server/main/websockets.go b/server/main/websockets.go
index 317d9a4e8..0316ac3fe 100644
--- a/server/main/websockets.go
+++ b/server/main/websockets.go
@@ -42,12 +42,14 @@ func (ws *WSServer) GetListeners(blockID string) []*websocket.Conn {
return listeners
}
+// WSServer is a WebSocket server
type WSServer struct {
upgrader websocket.Upgrader
listeners map[string][]*websocket.Conn
mu sync.RWMutex
}
+// NewWSServer creates a new WSServer
func NewWSServer() *WSServer {
return &WSServer{
listeners: make(map[string][]*websocket.Conn),
@@ -59,7 +61,7 @@ func NewWSServer() *WSServer {
}
}
-// WebsocketMsg is send on block changes
+// WebsocketMsg is sent on block changes
type WebsocketMsg struct {
Action string `json:"action"`
BlockID string `json:"blockId"`
From 92882fee5ffd79635efe1afbdc645baee5e799cc Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 08:55:59 -0700
Subject: [PATCH 06/34] Case-insensitive search
---
src/client/boardTree.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/client/boardTree.ts b/src/client/boardTree.ts
index 10459a5bf..146a0ed2d 100644
--- a/src/client/boardTree.ts
+++ b/src/client/boardTree.ts
@@ -116,11 +116,11 @@ class BoardTree {
}
private searchFilterCards(cards: IBlock[]) {
- const { searchText } = this
+ const searchText = this.searchText?.toLocaleLowerCase()
if (!searchText) { return cards.slice() }
return cards.filter(card => {
- if (card.title?.toLowerCase().indexOf(searchText) !== -1) { return true }
+ if (card.title?.toLocaleLowerCase().indexOf(searchText) !== -1) { return true }
})
}
From c6a0f7f3e9708620b18600e37101fb6c389b9a15 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 09:22:12 -0700
Subject: [PATCH 07/34] Show selected property on sort menu
---
src/client/components/boardComponent.tsx | 8 +++++++-
src/client/components/tableComponent.tsx | 8 +++++++-
src/client/menu.ts | 13 +++++++++++++
src/static/images.css | 9 ++++++++-
4 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index ba5343b1c..647090ee3 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -282,7 +282,13 @@ class BoardComponent extends React.Component {
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.options = propertyTemplates.map((o) => {
+ return {
+ id: o.id,
+ name: o.name,
+ icon: (sortOption.propertyId === o.id) ? "checked" : undefined
+ }
+ })
Menu.shared.onMenuClicked = async (propertyId: string) => {
let newSortOptions: ISortOption[] = []
if (sortOption && sortOption.propertyId === propertyId) {
diff --git a/src/client/components/tableComponent.tsx b/src/client/components/tableComponent.tsx
index bd05ea44c..3627bfddc 100644
--- a/src/client/components/tableComponent.tsx
+++ b/src/client/components/tableComponent.tsx
@@ -255,7 +255,13 @@ class TableComponent extends React.Component {
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.options = propertyTemplates.map((o) => {
+ return {
+ id: o.id,
+ name: o.name,
+ icon: (sortOption.propertyId === o.id) ? "checked" : undefined
+ }
+ })
Menu.shared.onMenuClicked = async (propertyId: string) => {
let newSortOptions: ISortOption[] = []
if (sortOption && sortOption.propertyId === propertyId) {
diff --git a/src/client/menu.ts b/src/client/menu.ts
index 58912321c..a79445fed 100644
--- a/src/client/menu.ts
+++ b/src/client/menu.ts
@@ -4,6 +4,7 @@ type MenuOption = {
id: string,
name: string,
isOn?: boolean,
+ icon?: "checked" | undefined,
type?: "separator" | "color" | "submenu" | "switch" | undefined
}
@@ -54,6 +55,18 @@ 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" }
+ default: { Utils.assertFailure(`Unsupported menu icon: ${option.icon}`) }
+ }
+ if (iconName) {
+ optionElement.appendChild(Utils.htmlToElement(``))
+ }
+ }
+
optionElement.onmouseenter = () => {
this.hideSubMenu()
}
diff --git a/src/static/images.css b/src/static/images.css
index 23d5390ea..b2c1b2e84 100644
--- a/src/static/images.css
+++ b/src/static/images.css
@@ -6,7 +6,7 @@
}
.imageAdd {
- background-image: url('data:image/svg+xml,');
+ background-image: url('data:image/svg+xml,');
background-size: 100% 100%;
min-width: 24px;
min-height: 24px;
@@ -25,3 +25,10 @@
min-width: 24px;
min-height: 24px;
}
+
+.imageMenuCheck {
+ background-image: url('data:image/svg+xml,');
+ background-size: 100% 100%;
+ min-width: 24px;
+ min-height: 24px;
+}
From 187df20be719c1c89cd86778e20e64f7b3c740a5 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 09:29:49 -0700
Subject: [PATCH 08/34] Show sort direction in sort menu
---
src/client/components/boardComponent.tsx | 2 +-
src/client/components/tableComponent.tsx | 2 +-
src/client/menu.ts | 6 ++++--
src/static/images.css | 16 ++++++++++++++++
4 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index 647090ee3..6456d8497 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -286,7 +286,7 @@ class BoardComponent extends React.Component {
return {
id: o.id,
name: o.name,
- icon: (sortOption.propertyId === o.id) ? "checked" : undefined
+ icon: (sortOption.propertyId === o.id) ? sortOption.reversed ? "sortUp" : "sortDown" : undefined
}
})
Menu.shared.onMenuClicked = async (propertyId: string) => {
diff --git a/src/client/components/tableComponent.tsx b/src/client/components/tableComponent.tsx
index 3627bfddc..042f1319e 100644
--- a/src/client/components/tableComponent.tsx
+++ b/src/client/components/tableComponent.tsx
@@ -259,7 +259,7 @@ class TableComponent extends React.Component {
return {
id: o.id,
name: o.name,
- icon: (sortOption.propertyId === o.id) ? "checked" : undefined
+ icon: (sortOption.propertyId === o.id) ? sortOption.reversed ? "sortUp" : "sortDown" : undefined
}
})
Menu.shared.onMenuClicked = async (propertyId: string) => {
diff --git a/src/client/menu.ts b/src/client/menu.ts
index a79445fed..35f86763b 100644
--- a/src/client/menu.ts
+++ b/src/client/menu.ts
@@ -4,7 +4,7 @@ type MenuOption = {
id: string,
name: string,
isOn?: boolean,
- icon?: "checked" | undefined,
+ icon?: "checked" | "sortUp" | "sortDown" | undefined,
type?: "separator" | "color" | "submenu" | "switch" | undefined
}
@@ -59,7 +59,9 @@ class Menu {
if (option.icon) {
let iconName: string
switch (option.icon) {
- case "checked": { iconName = "imageMenuCheck" }
+ 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) {
diff --git a/src/static/images.css b/src/static/images.css
index b2c1b2e84..4640988b5 100644
--- a/src/static/images.css
+++ b/src/static/images.css
@@ -19,6 +19,8 @@
min-height: 24px;
}
+/*-- Menu images --*/
+
.imageSubmenuTriangle {
background-image: url('data:image/svg+xml,');
background-size: 100% 100%;
@@ -32,3 +34,17 @@
min-width: 24px;
min-height: 24px;
}
+
+.imageMenuSortUp {
+ background-image: url('data:image/svg+xml,');
+ background-size: 100% 100%;
+ min-width: 24px;
+ min-height: 24px;
+}
+
+.imageMenuSortDown {
+ background-image: url('data:image/svg+xml,');
+ background-size: 100% 100%;
+ min-width: 24px;
+ min-height: 24px;
+}
From 63c7763b41b35f2f540ebf19d9e1cf01e6883c66 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 09:32:36 -0700
Subject: [PATCH 09/34] Refactor: Move sort menu to OctoUtils
---
src/client/components/boardComponent.tsx | 34 +--------------------
src/client/components/tableComponent.tsx | 34 +--------------------
src/client/octoUtils.tsx | 39 +++++++++++++++++++++---
3 files changed, 37 insertions(+), 70 deletions(-)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index 6456d8497..16cbbd2d0 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -96,7 +96,7 @@ class BoardComponent extends React.Component {
Group by {boardTree.groupByProperty?.name}
{ this.filterClicked(e) }}>Filter
- { this.sortClicked(e) }}>Sort
+ { OctoUtils.showSortMenu(e, mutator, boardTree) }}>Sort
{this.state.isSearching
? {
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,
- 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)
- }
-
private async optionsClicked(e: React.MouseEvent) {
const { boardTree } = this.props
diff --git a/src/client/components/tableComponent.tsx b/src/client/components/tableComponent.tsx
index 042f1319e..3e1e6c8cc 100644
--- a/src/client/components/tableComponent.tsx
+++ b/src/client/components/tableComponent.tsx
@@ -90,7 +90,7 @@ class TableComponent extends React.Component {
{ this.propertiesClicked(e) }}>Properties
{ this.filterClicked(e) }}>Filter
- { this.sortClicked(e) }}>Sort
+ { OctoUtils.showSortMenu(e, mutator, boardTree) }}>Sort
{this.state.isSearching
? {
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,
- 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)
- }
-
private async optionsClicked(e: React.MouseEvent) {
const { boardTree } = this.props
diff --git a/src/client/octoUtils.tsx b/src/client/octoUtils.tsx
index 10b388ada..8ed264a82 100644
--- a/src/client/octoUtils.tsx
+++ b/src/client/octoUtils.tsx
@@ -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"
@@ -143,7 +143,7 @@ class OctoUtils {
showMenu(e.target as HTMLElement)
}
} : undefined}
- onFocus={mutator ? () => { Menu.shared.hide() } : undefined }
+ onFocus={mutator ? () => { Menu.shared.hide() } : undefined}
>
{finalDisplayValue}
@@ -176,7 +176,7 @@ class OctoUtils {
if (index === 0) {
return block.order / 2
}
- const previousBlock = blocks[index-1]
+ const previousBlock = blocks[index - 1]
return (block.order + previousBlock.order) / 2
}
@@ -185,9 +185,40 @@ class OctoUtils {
if (index === blocks.length - 1) {
return block.order + 1000
}
- const nextBlock = blocks[index+1]
+ 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 }
From 04d4a7beb0f8c5781d69aa16d431d6ed7a3df093 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 09:33:03 -0700
Subject: [PATCH 10/34] cleanup
---
src/client/components/boardComponent.tsx | 1 -
src/client/components/tableComponent.tsx | 1 -
2 files changed, 2 deletions(-)
diff --git a/src/client/components/boardComponent.tsx b/src/client/components/boardComponent.tsx
index 16cbbd2d0..885953c1e 100644
--- a/src/client/components/boardComponent.tsx
+++ b/src/client/components/boardComponent.tsx
@@ -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"
diff --git a/src/client/components/tableComponent.tsx b/src/client/components/tableComponent.tsx
index 3e1e6c8cc..795ba6e39 100644
--- a/src/client/components/tableComponent.tsx
+++ b/src/client/components/tableComponent.tsx
@@ -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"
From fec32947bb0a5d272f9052d7e4f2d2afbf2905a7 Mon Sep 17 00:00:00 2001
From: Chen-I Lim
Date: Mon, 12 Oct 2020 10:01:58 -0700
Subject: [PATCH 11/34] Cleanup boardPage - layout page frame in code
---
html-templates/index.ejs | 6 ------
html-templates/page.ejs | 17 ++---------------
src/client/boardPage.tsx | 27 ++++++++++++++++++++++++++-
src/client/boardsPage.ts | 8 +++++++-
src/client/components/pageHeader.tsx | 16 ++++++++++++++++
src/static/main.css | 14 +++++---------
6 files changed, 56 insertions(+), 32 deletions(-)
create mode 100644 src/client/components/pageHeader.tsx
diff --git a/html-templates/index.ejs b/html-templates/index.ejs
index 024e53969..85f4fd368 100644
--- a/html-templates/index.ejs
+++ b/html-templates/index.ejs
@@ -24,12 +24,6 @@
All Boards
-
-
-
-
-