From fcdf991f934cd5f60787456a900a9f779373dd10 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Thu, 16 Feb 2023 13:33:41 +0100
Subject: [PATCH 01/18] only redirect to workspace home and toast board not
found error when boardId is undefined
---
src/modules/services/boardSlice.ts | 5 +++--
src/pages/workspace/View.js | 12 ++++++++----
src/pages/workspace/view/Board.js | 10 +++-------
3 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/modules/services/boardSlice.ts b/src/modules/services/boardSlice.ts
index 781f183..2559a65 100644
--- a/src/modules/services/boardSlice.ts
+++ b/src/modules/services/boardSlice.ts
@@ -341,7 +341,7 @@ export const boardApi = api.injectEndpoints({
channel.unbind()
},
providesTags: board => (board ? [board._id, 'Board'] : []),
- async onQueryStarted(args, { dispatch, queryFulfilled }) {
+ async onQueryStarted(boardId, { queryFulfilled }) {
try {
await queryFulfilled
localStorage.setItem(
@@ -349,7 +349,8 @@ export const boardApi = api.injectEndpoints({
window.location.pathname
)
} catch {
- toast('Could not find that Board')
+ if (boardId === undefined)
+ toast('Could not find that Board')
}
}
}),
diff --git a/src/pages/workspace/View.js b/src/pages/workspace/View.js
index 8f12c2e..9e6dd7f 100644
--- a/src/pages/workspace/View.js
+++ b/src/pages/workspace/View.js
@@ -1,7 +1,7 @@
import Board from './view/Board'
import ViewTopMenu from './view/ViewTopMenu'
import { memo, useCallback, useRef, useState } from 'react'
-import { useParams } from 'react-router-dom'
+import { Navigate, useParams } from 'react-router-dom'
import { useFetchWorkspaceQuery } from '../../modules/services/workspaceSlice'
import { LinearProgress } from '@mui/material'
import { useFetchBoardQuery } from '../../modules/services/boardSlice.ts'
@@ -17,7 +17,7 @@ function View({ level, view, sidebarOpen, toggleSideBar }) {
?.boards.find(x => x.name === board)?._id
}, [params.space, params.board, workspace?.spaces, workspace])
const boardId = findBoardId()
- const { isFetching } = useFetchBoardQuery(boardId)
+ const { isFetching, error } = useFetchBoardQuery(boardId)
const viewContainerRef = useRef(null)
const [bla, setBla] = useState(false)
const setViewContainerRef = useCallback(node => {
@@ -27,6 +27,10 @@ function View({ level, view, sidebarOpen, toggleSideBar }) {
}
}, [])
+ if (error && !isFetching && boardId === undefined) {
+ return
+ }
+
if (level === 'list') {
if (view === 'list')
return (
@@ -37,13 +41,13 @@ function View({ level, view, sidebarOpen, toggleSideBar }) {
sideBarClosed={!sidebarOpen}
/>
- {isFetching && }
+ {(isFetching || error) && }
- {viewContainerRef?.current && (
+ {!isFetching && !error && viewContainerRef?.current && (
{
return true
}, [])
- if (error && !isFetching) {
- return
- }
-
return (
Date: Thu, 16 Feb 2023 13:37:07 +0100
Subject: [PATCH 02/18] only show board name in ViewTopMenu if loading has
completed
---
src/pages/workspace/view/ViewTopMenu.js | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/pages/workspace/view/ViewTopMenu.js b/src/pages/workspace/view/ViewTopMenu.js
index 8288c04..225a869 100644
--- a/src/pages/workspace/view/ViewTopMenu.js
+++ b/src/pages/workspace/view/ViewTopMenu.js
@@ -13,7 +13,7 @@ import FilterMenu from './viewTopMenu/FilterMenu.tsx'
import ListIcon from '../../../styles/assets/ListIcon.tsx'
function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
- const { data: board } = useFetchBoardQuery(boardId)
+ const { data: board, isFetching, error } = useFetchBoardQuery(boardId)
const [shareDialogOpen, toggleShareDialogOpen] = useToggleState(false)
const [groupByOpen, setGroupByOpen] = useState(null)
const [search, setSearch] = useAtom(searchAtom)
@@ -56,7 +56,11 @@ function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
-
{board?.name || '...'}
+
+ {!isFetching && !error && board?.name
+ ? board?.name
+ : '...'}
+
{/**/}
{/* {[*/}
From 667c5b1fe351937224bb9311a01d3151b07c8ed2 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Thu, 16 Feb 2023 15:27:34 +0100
Subject: [PATCH 03/18] fix unnecessary setFilters mutation when filters are
unchanged
---
src/pages/workspace/view/viewTopMenu/FilterMenu.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx b/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
index 8c7b270..ef3305f 100644
--- a/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
+++ b/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
@@ -87,6 +87,7 @@ export default function FilterMenu({ boardId }) {
}, [board.filters])
const handleClose = open => {
+ if (filters === board.filters) return
if (!open) {
setFilters({
boardId,
From 1c86d6fdfc2dee9b86a8b7126f50351e8dabd816 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Fri, 17 Feb 2023 09:59:31 +0100
Subject: [PATCH 04/18] automatically close sidebar when changing the current
board on mobile devices
---
src/pages/workspace/SideBar.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/pages/workspace/SideBar.js b/src/pages/workspace/SideBar.js
index 329e861..15e6a0d 100644
--- a/src/pages/workspace/SideBar.js
+++ b/src/pages/workspace/SideBar.js
@@ -326,6 +326,13 @@ function SideBar(props) {
>
{provided => (
{
+ if (
+ window.innerWidth <=
+ 576
+ )
+ props.toggleSideBar()
+ }}
{...provided.draggableProps}
ref={
provided.innerRef
From 590ccab92f17c8c503cc65f6dda15c616d46ce76 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Sat, 18 Feb 2023 14:42:57 +0100
Subject: [PATCH 05/18] add views
---
src/modules/services/boardSlice.ts | 4 +-
src/pages/Workspace.js | 13 ++-
src/pages/workspace/View.js | 25 +++--
src/pages/workspace/topMenu/GroupByPopover.js | 6 +-
src/pages/workspace/topMenu/ShareDialog.js | 10 +-
src/pages/workspace/view/Board.js | 4 +-
src/pages/workspace/view/ViewTopMenu.js | 100 ++++++++++--------
src/pages/workspace/view/board/BoardView.js | 13 ++-
.../view/board/taskGroup/TaskModal.tsx | 6 +-
.../board/taskGroup/taskModal/Activity.js | 2 +-
.../workspace/view/viewTopMenu/FilterMenu.tsx | 12 +--
11 files changed, 113 insertions(+), 82 deletions(-)
diff --git a/src/modules/services/boardSlice.ts b/src/modules/services/boardSlice.ts
index 2559a65..9d6c08c 100644
--- a/src/modules/services/boardSlice.ts
+++ b/src/modules/services/boardSlice.ts
@@ -210,7 +210,7 @@ const setSharing = ({ board, share }) => {
export const boardApi = api.injectEndpoints({
endpoints: builder => ({
fetchBoard: builder.query({
- query: boardId => `board/${boardId}`,
+ query: ({ boardId, viewId = '' }) => `board/${boardId}/${viewId}`,
transformResponse: (response: any, meta, arg) => {
return {
...response,
@@ -218,7 +218,7 @@ export const boardApi = api.injectEndpoints({
}
},
async onCacheEntryAdded(
- boardId,
+ { boardId },
{ updateCachedData, cacheDataLoaded, cacheEntryRemoved }
) {
let channel
diff --git a/src/pages/Workspace.js b/src/pages/Workspace.js
index 0605c7a..0a0f401 100644
--- a/src/pages/Workspace.js
+++ b/src/pages/Workspace.js
@@ -54,7 +54,18 @@ function Workspace(props) {
}
/>
+ }
+ />
+ x.name === board)?._id
}, [params.space, params.board, workspace?.spaces, workspace])
const boardId = findBoardId()
- const { isFetching, error } = useFetchBoardQuery(boardId)
+ const { isFetching, error } = useFetchBoardQuery({ boardId })
const viewContainerRef = useRef(null)
const [bla, setBla] = useState(false)
const setViewContainerRef = useCallback(node => {
@@ -41,20 +41,25 @@ function View({ level, view, sidebarOpen, toggleSideBar }) {
sideBarClosed={!sidebarOpen}
/>
- {(isFetching || error) && }
+ {(!params.view || isFetching || error) && (
+
+ )}
- {!isFetching && !error && viewContainerRef?.current && (
-
- )}
+ {params.view &&
+ !isFetching &&
+ !error &&
+ viewContainerRef?.current && (
+
+ )}
>
)
diff --git a/src/pages/workspace/topMenu/GroupByPopover.js b/src/pages/workspace/topMenu/GroupByPopover.js
index 2ac3ee6..faa9584 100644
--- a/src/pages/workspace/topMenu/GroupByPopover.js
+++ b/src/pages/workspace/topMenu/GroupByPopover.js
@@ -5,7 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { solid } from '@fortawesome/fontawesome-svg-core/import.macro'
import React from 'react'
-function GroupByPopover({ board, groupByOpen, setGroupByOpen }) {
+function GroupByPopover({ view, board, groupByOpen, setGroupByOpen }) {
const [setGroupBy] = useSetGroupByMutation()
const handleClose = () => {
@@ -48,7 +48,7 @@ function GroupByPopover({ board, groupByOpen, setGroupByOpen }) {
}
>
{attribute.name}
- {board?.groupBy === attribute._id && (
+ {view?.groupBy === attribute._id && (
)}
@@ -59,7 +59,7 @@ function GroupByPopover({ board, groupByOpen, setGroupByOpen }) {
onClick={() => handleGroupByChange('none')}
>
None
- {(!board?.groupBy || board?.groupBy === 'none') && (
+ {(!view?.groupBy || view?.groupBy === 'none') && (
)}
diff --git a/src/pages/workspace/topMenu/ShareDialog.js b/src/pages/workspace/topMenu/ShareDialog.js
index 29b01b1..5d9611b 100644
--- a/src/pages/workspace/topMenu/ShareDialog.js
+++ b/src/pages/workspace/topMenu/ShareDialog.js
@@ -6,12 +6,12 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { solid } from '@fortawesome/fontawesome-svg-core/import.macro'
import { useSetSharingMutation } from '../../../modules/services/boardSlice.ts'
-function ShareDialog({ handleClose, open, board }) {
+function ShareDialog({ handleClose, open, boardId, view }) {
const [setSharing] = useSetSharingMutation()
const toggleShare = (e, share) => {
setSharing({
- boardId: board._id,
+ boardId,
share
})
}
@@ -30,14 +30,14 @@ function ShareDialog({ handleClose, open, board }) {
- {board.sharing && (
+ {view.sharing && (
@@ -46,7 +46,7 @@ function ShareDialog({ handleClose, open, board }) {
diff --git a/src/pages/workspace/view/Board.js b/src/pages/workspace/view/Board.js
index bf285bc..99aa5d8 100644
--- a/src/pages/workspace/view/Board.js
+++ b/src/pages/workspace/view/Board.js
@@ -8,7 +8,8 @@ import { forwardRef, useCallback } from 'react'
function Board({ boardId }, viewContainerRef) {
const params = useParams()
const { data: workspace } = useFetchWorkspaceQuery(params.workspace)
- const { data: board } = useFetchBoardQuery(boardId)
+ const { data: board } = useFetchBoardQuery({ boardId, viewId: params.view })
+ const view = board?.views.find(x => x.id === params.view)
const hasPerms = useCallback(permission => {
return true
@@ -19,6 +20,7 @@ function Board({ boardId }, viewContainerRef) {
ref={viewContainerRef}
members={workspace.members}
board={board}
+ view={view}
hasPerms={hasPerms}
/>
)
diff --git a/src/pages/workspace/view/ViewTopMenu.js b/src/pages/workspace/view/ViewTopMenu.js
index 225a869..8fd6a94 100644
--- a/src/pages/workspace/view/ViewTopMenu.js
+++ b/src/pages/workspace/view/ViewTopMenu.js
@@ -8,29 +8,43 @@ import { solid } from '@fortawesome/fontawesome-svg-core/import.macro'
import { useFetchBoardQuery } from '../../../modules/services/boardSlice.ts'
import { useAtom } from 'jotai'
import { searchAtom } from '../../../utils/atoms.ts'
-import { useParams } from 'react-router-dom'
+import { useNavigate, useParams } from 'react-router-dom'
import FilterMenu from './viewTopMenu/FilterMenu.tsx'
import ListIcon from '../../../styles/assets/ListIcon.tsx'
function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
- const { data: board, isFetching, error } = useFetchBoardQuery(boardId)
+ const { data: board, isFetching, error } = useFetchBoardQuery({ boardId })
const [shareDialogOpen, toggleShareDialogOpen] = useToggleState(false)
const [groupByOpen, setGroupByOpen] = useState(null)
+ const navigate = useNavigate()
const [search, setSearch] = useAtom(searchAtom)
const params = useParams()
+ const view = board?.views.find(x => x.id === params?.view)
useEffect(() => {
setSearch('')
}, [params.board])
+ useEffect(() => {
+ if (!params.view && board) {
+ const { workspace, space, board: boardId } = params
+ navigate(`/${workspace}/${space}/${boardId}/${board.views[0].id}`)
+ }
+ }, [params.board, board])
+
const handleChange = e => {
setSearch(e.target.value)
}
+ const handleViewClick = id => {
+ const { workspace, space, board } = params
+ navigate(`/${workspace}/${space}/${board}/${id}`)
+ }
+
const groupBy = () => {
- if (!board?.groupBy || board.groupBy === 'none') return false
+ if (!view?.groupBy || view.groupBy === 'none') return false
return board.attributes.find(
- attribute => attribute._id === board.groupBy
+ attribute => attribute._id === view.groupBy
).name
}
@@ -62,46 +76,34 @@ function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
: '...'}
- {/*
*/}
- {/* {[*/}
- {/* {*/}
- {/* name: 'List',*/}
- {/* icon:
,*/}
- {/* active: true*/}
- {/* },*/}
- {/* {*/}
- {/* name: 'Bugs',*/}
- {/* icon:
,*/}
- {/* active: false*/}
- {/* }*/}
- {/* ].map(({ name, icon, active }) => (*/}
- {/*
*/}
- {/*
*/}
- {/* {icon}*/}
- {/* */}
- {/* {name}*/}
- {/* */}
- {/*
*/}
- {/*
*/}
- {/* ))}*/}
- {/*
*/}
+
+ {board?.views.map(({ name, id }) => (
+
handleViewClick(id)}
+ className="subpixel-antialiased flex justify-center items-center h-[60px] box-border cursor-pointer border-y-[3px] border-y-[white] border-solid"
+ >
+
+
+
+ {name}
+
+
+
+ ))}
+
- {board && (
+ {view && (
@@ -142,7 +145,9 @@ function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
{/**/}
- {board &&
}
+ {board && view && (
+
+ )}
{
if (!board) return
- if (!board.groupBy || board.groupBy === 'none') {
+ const view = board?.views.find(x => x.id === params?.view)
+ if (!view.groupBy || view.groupBy === 'none') {
const fuse = new Fuse(board.tasks, {
keys: ['name'],
shouldSort: false
@@ -59,7 +62,7 @@ function BoardView({ board, members, hasPerms }, viewContainerRef) {
}
const labels = _.cloneDeep(
- board.attributes.find(attribute => attribute._id === board.groupBy)
+ board.attributes.find(attribute => attribute._id === view.groupBy)
.labels
)
@@ -72,7 +75,7 @@ function BoardView({ board, members, hasPerms }, viewContainerRef) {
buildTree(board.tasks).map(task => {
const value = task.options.find(
- option => option.column === board.groupBy
+ option => option.column === view.groupBy
)?.value
const label = labels.find(label => label._id === value)
if (value && label) label.tasks.push(task)
@@ -119,7 +122,9 @@ function BoardView({ board, members, hasPerms }, viewContainerRef) {
const sourceIndex = board.tasks.findIndex(
x => x._id.toString() === result.draggableId
)
- if (!(!board.groupBy || board.groupBy === 'none')) {
+
+ const view = board?.views.find(x => x.id === params?.view)
+ if (!(!view.groupBy || view.groupBy === 'none')) {
const destinationTask = groupedTasks.find(
group => group._id === result.destination.droppableId
).tasks[result.destination.index]
diff --git a/src/pages/workspace/view/board/taskGroup/TaskModal.tsx b/src/pages/workspace/view/board/taskGroup/TaskModal.tsx
index 9881148..c68a580 100644
--- a/src/pages/workspace/view/board/taskGroup/TaskModal.tsx
+++ b/src/pages/workspace/view/board/taskGroup/TaskModal.tsx
@@ -31,7 +31,7 @@ interface Props {
function TaskModal({ task, boardId, hasPerms, members }: Props) {
const navigate = useNavigate()
const params = useParams()
- const { data: board } = useFetchBoardQuery(boardId)
+ const { data: board } = useFetchBoardQuery({ boardId })
const { data: user } = useFetchUserQuery()
const [name, changeName] = useInputState(task.name)
const [anchor, setAnchor] = useState(null)
@@ -44,7 +44,9 @@ function TaskModal({ task, boardId, hasPerms, members }: Props) {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur()
}
- navigate(`/${params.workspace}/${params.space}/${params.board}`)
+ navigate(
+ `/${params.workspace}/${params.space}/${params.board}/${params.view}`
+ )
}
useEffect(() => {
diff --git a/src/pages/workspace/view/board/taskGroup/taskModal/Activity.js b/src/pages/workspace/view/board/taskGroup/taskModal/Activity.js
index bcd2a33..a5d6b15 100644
--- a/src/pages/workspace/view/board/taskGroup/taskModal/Activity.js
+++ b/src/pages/workspace/view/board/taskGroup/taskModal/Activity.js
@@ -4,7 +4,7 @@ import { diffWords } from 'diff'
import { useFetchBoardQuery } from '../../../../../../modules/services/boardSlice.ts'
function Activity({ timestamp, activity, boardId }) {
- const { data: board } = useFetchBoardQuery(boardId)
+ const { data: board } = useFetchBoardQuery({ boardId })
const getDiff = () => {
const groups = diffWords(activity.change.from, activity.change.to)
diff --git a/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx b/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
index ef3305f..04330d6 100644
--- a/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
+++ b/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
@@ -15,8 +15,8 @@ const operations = {
text: ['Contains', 'Does not contain', 'Is set', 'Is not set']
}
-export default function FilterMenu({ boardId }) {
- const { data: board } = useFetchBoardQuery(boardId)
+export default function FilterMenu({ boardId, view }) {
+ const { data: board } = useFetchBoardQuery({ boardId })
const [setFilters] = useSetFiltersMutation()
const [filters, setFiltersState] = useState([])
@@ -81,13 +81,13 @@ export default function FilterMenu({ boardId }) {
}
useEffect(() => {
- if (board?.filters) {
- setFiltersState(board.filters)
+ if (view?.filters) {
+ setFiltersState(view.filters)
}
- }, [board.filters])
+ }, [view.filters])
const handleClose = open => {
- if (filters === board.filters) return
+ if (filters === view.filters) return
if (!open) {
setFilters({
boardId,
From a1fa3464c603fa6a17ccdbb4eabe2b31fc4e0386 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Sat, 18 Feb 2023 16:43:11 +0100
Subject: [PATCH 06/18] add view mutation routes
---
src/modules/services/boardSlice.ts | 30 +++++++++++--------
src/pages/workspace/topMenu/GroupByPopover.js | 2 +-
src/pages/workspace/topMenu/ShareDialog.js | 1 +
.../workspace/view/viewTopMenu/FilterMenu.tsx | 2 +-
4 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/modules/services/boardSlice.ts b/src/modules/services/boardSlice.ts
index 9d6c08c..055a553 100644
--- a/src/modules/services/boardSlice.ts
+++ b/src/modules/services/boardSlice.ts
@@ -5,8 +5,11 @@ import pusher from '../../pusher/pusher.ts'
import handleQueryError from '../../utils/handleQueryError'
import { flatten, removeChildrenOf } from '../../utils/taskUtils.ts'
-const setGroupBy = ({ board, groupBy }) => {
- board.groupBy = groupBy
+const setGroupBy = ({ board, groupBy, viewId }) => {
+ console.log('bla')
+ // console.log('viewId')
+ // console.log(viewId)
+ // board.views.find(x => x._id === viewId).groupBy = groupBy
}
const addTask = ({ board, newTaskName, taskGroupId, _id, author, level }) => {
const task = {
@@ -355,20 +358,23 @@ export const boardApi = api.injectEndpoints({
}
}),
setGroupBy: builder.mutation({
- query: ({ boardId, groupBy }) => ({
- url: `board/${boardId}`,
- method: 'PATCH',
+ query: ({ viewId, groupBy }) => ({
+ url: `view/${viewId}/groupBy`,
+ method: 'PUT',
body: { groupBy }
}),
async onQueryStarted(
- { boardId, groupBy },
+ { boardId, groupBy, viewId },
{ dispatch, queryFulfilled }
) {
+ console.log({ boardId, groupBy, viewId })
const patchResult = dispatch(
boardApi.util.updateQueryData(
'fetchBoard',
boardId,
- board => setGroupBy({ board, groupBy })
+ board => {
+ setGroupBy({ board, groupBy, viewId })
+ }
)
)
try {
@@ -914,9 +920,9 @@ export const boardApi = api.injectEndpoints({
}
}),
setSharing: builder.mutation({
- query: ({ boardId, share }) => ({
- url: `board/share/${boardId}`,
- method: 'PATCH',
+ query: ({ viewId, share }) => ({
+ url: `view/${viewId}/setSharing`,
+ method: 'PUT',
body: { share }
}),
async onQueryStarted(
@@ -963,8 +969,8 @@ export const boardApi = api.injectEndpoints({
}
}),
setFilters: builder.mutation({
- query: ({ boardId, filters }) => ({
- url: `board/${boardId}`,
+ query: ({ viewId, filters }) => ({
+ url: `view/${viewId}/setFilters`,
method: 'PUT',
body: { filters }
}),
diff --git a/src/pages/workspace/topMenu/GroupByPopover.js b/src/pages/workspace/topMenu/GroupByPopover.js
index faa9584..f72f425 100644
--- a/src/pages/workspace/topMenu/GroupByPopover.js
+++ b/src/pages/workspace/topMenu/GroupByPopover.js
@@ -13,7 +13,7 @@ function GroupByPopover({ view, board, groupByOpen, setGroupByOpen }) {
}
const handleGroupByChange = _id => {
- setGroupBy({ boardId: board._id, groupBy: _id })
+ setGroupBy({ boardId: board._id, viewId: view._id, groupBy: _id })
handleClose()
}
diff --git a/src/pages/workspace/topMenu/ShareDialog.js b/src/pages/workspace/topMenu/ShareDialog.js
index 5d9611b..1191151 100644
--- a/src/pages/workspace/topMenu/ShareDialog.js
+++ b/src/pages/workspace/topMenu/ShareDialog.js
@@ -11,6 +11,7 @@ function ShareDialog({ handleClose, open, boardId, view }) {
const toggleShare = (e, share) => {
setSharing({
+ viewId: view._id,
boardId,
share
})
diff --git a/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx b/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
index 04330d6..e9ddb50 100644
--- a/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
+++ b/src/pages/workspace/view/viewTopMenu/FilterMenu.tsx
@@ -90,7 +90,7 @@ export default function FilterMenu({ boardId, view }) {
if (filters === view.filters) return
if (!open) {
setFilters({
- boardId,
+ viewId: view._id,
filters
})
}
From 07a3abdd268ba85701a852e889010533f68a8d21 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Sat, 18 Feb 2023 20:14:02 +0100
Subject: [PATCH 07/18] implement menu to add new views
---
src/modules/services/boardSlice.ts | 25 +++++++-
src/pages/workspace/view/ViewTopMenu.js | 2 +
.../view/viewTopMenu/NewViewMenu.tsx | 64 +++++++++++++++++++
3 files changed, 90 insertions(+), 1 deletion(-)
create mode 100644 src/pages/workspace/view/viewTopMenu/NewViewMenu.tsx
diff --git a/src/modules/services/boardSlice.ts b/src/modules/services/boardSlice.ts
index 055a553..b66f33a 100644
--- a/src/modules/services/boardSlice.ts
+++ b/src/modules/services/boardSlice.ts
@@ -968,6 +968,28 @@ export const boardApi = api.injectEndpoints({
}
}
}),
+ addView: builder.mutation({
+ query: ({ boardId, type }) => ({
+ url: `view/${boardId}/addView`,
+ method: 'POST',
+ body: { type }
+ }),
+ invalidatesTags: (result, error, arg) => [arg.boardId],
+ async onQueryStarted({ boardId }, { dispatch, queryFulfilled }) {
+ const patchResult = dispatch(
+ boardApi.util.updateQueryData(
+ 'fetchBoard',
+ boardId,
+ board => {}
+ )
+ )
+ try {
+ await queryFulfilled
+ } catch (err) {
+ if (handleQueryError({ err })) patchResult.undo()
+ }
+ }
+ }),
setFilters: builder.mutation({
query: ({ viewId, filters }) => ({
url: `view/${viewId}/setFilters`,
@@ -1002,5 +1024,6 @@ export const {
useRemoveWatcherMutation,
useSetSharingMutation,
useAddSubtaskMutation,
- useSetFiltersMutation
+ useSetFiltersMutation,
+ useAddViewMutation
} = boardApi
diff --git a/src/pages/workspace/view/ViewTopMenu.js b/src/pages/workspace/view/ViewTopMenu.js
index 8fd6a94..bd33340 100644
--- a/src/pages/workspace/view/ViewTopMenu.js
+++ b/src/pages/workspace/view/ViewTopMenu.js
@@ -11,6 +11,7 @@ import { searchAtom } from '../../../utils/atoms.ts'
import { useNavigate, useParams } from 'react-router-dom'
import FilterMenu from './viewTopMenu/FilterMenu.tsx'
import ListIcon from '../../../styles/assets/ListIcon.tsx'
+import NewViewMenu from './viewTopMenu/NewViewMenu.tsx'
function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
const { data: board, isFetching, error } = useFetchBoardQuery({ boardId })
@@ -103,6 +104,7 @@ function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
))}
+
diff --git a/src/pages/workspace/view/viewTopMenu/NewViewMenu.tsx b/src/pages/workspace/view/viewTopMenu/NewViewMenu.tsx
new file mode 100644
index 0000000..d1780bd
--- /dev/null
+++ b/src/pages/workspace/view/viewTopMenu/NewViewMenu.tsx
@@ -0,0 +1,64 @@
+import { Menu, Transition } from '@headlessui/react'
+import { Fragment } from 'react'
+import ListIcon from '../../../../styles/assets/ListIcon.tsx'
+import { useAddViewMutation } from '../../../../modules/services/boardSlice.ts'
+import * as React from 'react'
+
+interface NewViewMenuProps {
+ boardId: string
+}
+
+function NewViewMenu({ boardId }: NewViewMenuProps) {
+ const [addView] = useAddViewMutation()
+
+ const handleAddView = (type: string): void => {
+ addView({
+ boardId,
+ type
+ })
+ }
+
+ return (
+
+ )
+}
+
+export default NewViewMenu
From 5e47697516955fb3aff07fe4bb9a7deaaeec404d Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Sat, 18 Feb 2023 20:57:05 +0100
Subject: [PATCH 08/18] add menu to viewItem and ability to delete views
---
src/modules/services/boardSlice.ts | 25 +++-
src/pages/workspace/view/ViewTopMenu.js | 36 ++---
.../view/viewTopMenu/ViewNavItem.tsx | 125 ++++++++++++++++++
3 files changed, 159 insertions(+), 27 deletions(-)
create mode 100644 src/pages/workspace/view/viewTopMenu/ViewNavItem.tsx
diff --git a/src/modules/services/boardSlice.ts b/src/modules/services/boardSlice.ts
index b66f33a..a480eee 100644
--- a/src/modules/services/boardSlice.ts
+++ b/src/modules/services/boardSlice.ts
@@ -990,6 +990,28 @@ export const boardApi = api.injectEndpoints({
}
}
}),
+ deleteView: builder.mutation({
+ query: ({ boardId, viewId }) => ({
+ url: `view/${boardId}/deleteView`,
+ method: 'POST',
+ body: { viewId }
+ }),
+ invalidatesTags: (result, error, arg) => [arg.boardId],
+ async onQueryStarted({ boardId }, { dispatch, queryFulfilled }) {
+ const patchResult = dispatch(
+ boardApi.util.updateQueryData(
+ 'fetchBoard',
+ boardId,
+ board => {}
+ )
+ )
+ try {
+ await queryFulfilled
+ } catch (err) {
+ if (handleQueryError({ err })) patchResult.undo()
+ }
+ }
+ }),
setFilters: builder.mutation({
query: ({ viewId, filters }) => ({
url: `view/${viewId}/setFilters`,
@@ -1025,5 +1047,6 @@ export const {
useSetSharingMutation,
useAddSubtaskMutation,
useSetFiltersMutation,
- useAddViewMutation
+ useAddViewMutation,
+ useDeleteViewMutation
} = boardApi
diff --git a/src/pages/workspace/view/ViewTopMenu.js b/src/pages/workspace/view/ViewTopMenu.js
index bd33340..71195f3 100644
--- a/src/pages/workspace/view/ViewTopMenu.js
+++ b/src/pages/workspace/view/ViewTopMenu.js
@@ -10,8 +10,8 @@ import { useAtom } from 'jotai'
import { searchAtom } from '../../../utils/atoms.ts'
import { useNavigate, useParams } from 'react-router-dom'
import FilterMenu from './viewTopMenu/FilterMenu.tsx'
-import ListIcon from '../../../styles/assets/ListIcon.tsx'
import NewViewMenu from './viewTopMenu/NewViewMenu.tsx'
+import ViewNavItem from './viewTopMenu/ViewNavItem.tsx'
function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
const { data: board, isFetching, error } = useFetchBoardQuery({ boardId })
@@ -78,31 +78,15 @@ function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
- {board?.views.map(({ name, id }) => (
-
handleViewClick(id)}
- className="subpixel-antialiased flex justify-center items-center h-[60px] box-border cursor-pointer border-y-[3px] border-y-[white] border-solid"
- >
-
-
-
- {name}
-
-
-
+ {board?.views.map(({ name, id, _id }) => (
+
))}
diff --git a/src/pages/workspace/view/viewTopMenu/ViewNavItem.tsx b/src/pages/workspace/view/viewTopMenu/ViewNavItem.tsx
new file mode 100644
index 0000000..4b81a17
--- /dev/null
+++ b/src/pages/workspace/view/viewTopMenu/ViewNavItem.tsx
@@ -0,0 +1,125 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import ListIcon from '../../../../styles/assets/ListIcon.tsx'
+import { regular, solid } from '@fortawesome/fontawesome-svg-core/import.macro'
+import { Menu, Transition } from '@headlessui/react'
+import { Fragment } from 'react'
+import * as React from 'react'
+import { useDeleteViewMutation } from '../../../../modules/services/boardSlice.ts'
+
+interface Props {
+ boardId: string
+ _id: string
+ id: string
+ name: string
+ handleViewClick: (id: string) => void
+ active: boolean
+}
+
+export default function ({
+ boardId,
+ _id,
+ active,
+ name,
+ id,
+ handleViewClick
+}: Props) {
+ const [deleteView] = useDeleteViewMutation()
+
+ const handleRename = () => {}
+
+ const handleDelete = () => {
+ deleteView({
+ boardId,
+ viewId: _id
+ })
+ }
+
+ return (
+ handleViewClick(id)}
+ className="subpixel-antialiased flex justify-center items-center h-[60px] box-border cursor-pointer border-y-[3px] border-y-[white] border-solid"
+ >
+
+
+
+ {name}
+
+ {active && (
+
+ )}
+
+
+ )
+}
From 9f6c031bba92def6ca0ce34780e4c54bad098579 Mon Sep 17 00:00:00 2001
From: MarconLP <13001502+MarconLP@users.noreply.github.com>
Date: Sat, 18 Feb 2023 21:40:21 +0100
Subject: [PATCH 09/18] add ability to rename view
---
src/modules/services/boardSlice.ts | 27 +++++++-
src/pages/workspace/view/ViewTopMenu.js | 1 +
.../view/viewTopMenu/ViewNavItem.tsx | 62 +++++++++++++++----
3 files changed, 77 insertions(+), 13 deletions(-)
diff --git a/src/modules/services/boardSlice.ts b/src/modules/services/boardSlice.ts
index a480eee..f499e35 100644
--- a/src/modules/services/boardSlice.ts
+++ b/src/modules/services/boardSlice.ts
@@ -993,7 +993,7 @@ export const boardApi = api.injectEndpoints({
deleteView: builder.mutation({
query: ({ boardId, viewId }) => ({
url: `view/${boardId}/deleteView`,
- method: 'POST',
+ method: 'DELETE',
body: { viewId }
}),
invalidatesTags: (result, error, arg) => [arg.boardId],
@@ -1012,6 +1012,28 @@ export const boardApi = api.injectEndpoints({
}
}
}),
+ renameView: builder.mutation({
+ query: ({ viewId, name }) => ({
+ url: `view/${viewId}/renameView`,
+ method: 'PUT',
+ body: { name }
+ }),
+ invalidatesTags: (result, error, arg) => [arg.boardId],
+ async onQueryStarted({ boardId }, { dispatch, queryFulfilled }) {
+ const patchResult = dispatch(
+ boardApi.util.updateQueryData(
+ 'fetchBoard',
+ boardId,
+ board => {}
+ )
+ )
+ try {
+ await queryFulfilled
+ } catch (err) {
+ if (handleQueryError({ err })) patchResult.undo()
+ }
+ }
+ }),
setFilters: builder.mutation({
query: ({ viewId, filters }) => ({
url: `view/${viewId}/setFilters`,
@@ -1048,5 +1070,6 @@ export const {
useAddSubtaskMutation,
useSetFiltersMutation,
useAddViewMutation,
- useDeleteViewMutation
+ useDeleteViewMutation,
+ useRenameViewMutation
} = boardApi
diff --git a/src/pages/workspace/view/ViewTopMenu.js b/src/pages/workspace/view/ViewTopMenu.js
index 71195f3..d58acf5 100644
--- a/src/pages/workspace/view/ViewTopMenu.js
+++ b/src/pages/workspace/view/ViewTopMenu.js
@@ -80,6 +80,7 @@ function ViewTopMenu({ boardId, sideBarClosed, toggleSideBar }) {
{board?.views.map(({ name, id, _id }) => (
(false)
+ const [newName, changeNewName, , setNewName] = useInputState(name)
+ const [width, setWidth] = useState(100)
+ const ref = useRef()
- const handleRename = () => {}
+ const handleRenameClick = () => {
+ setWidth(ref.current.offsetWidth)
+ setRenaming(true)
+ }
+
+ const handleRename = () => {
+ renameView({
+ viewId: _id,
+ name: newName
+ })
+ setRenaming(false)
+ }
const handleDelete = () => {
deleteView({
@@ -34,6 +54,10 @@ export default function ({
})
}
+ useEffect(() => {
+ setNewName(name)
+ }, [name])
+
return (
-
- {name}
-
+ {renaming ? (
+
{
+ if (['Enter', 'Escape'].includes(e.key))
+ e.currentTarget.blur()
+ }}
+ style={{ width: `${width}px` }}
+ onBlur={handleRename}
+ className="outline-none text-sm leading-[14px] font-medium text-[#4169e1]"
+ value={newName}
+ onChange={changeNewName}
+ autoFocus
+ />
+ ) : (
+
+ {name}
+
+ )}
{active && (