[GH-1539] Implement searching for the individual words in workspaces (#1590)

This commit is contained in:
Tim Borodin 2021-11-22 21:00:26 +02:00 committed by GitHub
parent a46f09501e
commit 26e8625cf3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 1056 additions and 76 deletions

View file

@ -1,6 +1,378 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`pages/dashboard/CenterContent base case 1`] = `
exports[`pages/dashboard/CenterContent base case - find all workspaces 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Foo Bar Baz
</div>
<div
class="small"
>
33 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
team 33
</div>
<div
class="small"
>
14 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace
</div>
<div
class="small"
>
33 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 1
</div>
<div
class="small"
>
1 Board
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 11
</div>
<div
class="small"
>
1 Board
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 2
</div>
<div
class="small"
>
2 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
WS 4
</div>
<div
class="small"
>
3 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 3
</div>
<div
class="small"
>
0 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - 5 matching workspaces 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace
</div>
<div
class="small"
>
33 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 1
</div>
<div
class="small"
>
1 Board
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 11
</div>
<div
class="small"
>
1 Board
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 2
</div>
<div
class="small"
>
2 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 3
</div>
<div
class="small"
>
0 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - number search 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Chat6
</div>
<div
class="small"
>
17 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Title
</div>
<div
class="small"
>
6 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search for all workspaces that contain the word workspace 1`] = `
<div>
<div
class="DashboardCenterContent"
@ -96,6 +468,472 @@ exports[`pages/dashboard/CenterContent base case 1`] = `
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search for amount of boards 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
team 33
</div>
<div
class="small"
>
14 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 3
</div>
<div
class="small"
>
0 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search for foo baz 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Foo Bar Baz
</div>
<div
class="small"
>
33 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search for workspace name and amount of boards 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
team 33
</div>
<div
class="small"
>
14 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
WS 4
</div>
<div
class="small"
>
3 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 3
</div>
<div
class="small"
>
0 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search for workspace name and amount of boards 2 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Foo Bar Baz
</div>
<div
class="small"
>
33 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
team 33
</div>
<div
class="small"
>
14 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace
</div>
<div
class="small"
>
33 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 1
</div>
<div
class="small"
>
1 Board
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 11
</div>
<div
class="small"
>
1 Board
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 2
</div>
<div
class="small"
>
2 Boards
</div>
</div>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 3
</div>
<div
class="small"
>
0 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search for workspace with unique name 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
WS 4
</div>
<div
class="small"
>
3 Boards
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter - search non-existing workspace 1`] = `
<div>
<div
@ -187,71 +1025,3 @@ exports[`pages/dashboard/CenterContent search filter - search non-existing works
</div>
</div>
`;
exports[`pages/dashboard/CenterContent search filter 1`] = `
<div>
<div
class="DashboardCenterContent"
>
<div
class="DashboardPage__header"
>
<h1
class="h1"
>
Dashboard
</h1>
<div
class="DashboardPage__showEmpty"
>
Show empty
<div
class="Switch on"
>
<div
class="octo-switch-inner"
/>
</div>
</div>
<div
class="DashboardPage__search"
>
<i
class="CompassIcon icon-magnify CompassIcon"
/>
<input
placeholder="Search"
type="text"
/>
</div>
</div>
<div
class="DashboardPage__content"
>
<div
class="text-heading3"
>
All Channels
</div>
<div
class="DashboardPage__workspace-container"
>
<div
class="DashboardPage__workspace"
>
<div
class="text-heading2"
>
Workspace 1
</div>
<div
class="small"
>
1 Board
</div>
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -47,14 +47,56 @@ describe('pages/dashboard/CenterContent', () => {
boardCount: 0,
}
test('base case', () => {
const workspace4: UserWorkspace = {
id: 'workspace_4',
title: 'WS 4',
boardCount: 3,
}
const workspace5: UserWorkspace = {
id: 'workspace_5',
title: 'Foo Bar Baz',
boardCount: 33,
}
const workspace6: UserWorkspace = {
id: 'workspace_6',
title: 'Workspace 11',
boardCount: 1,
}
const workspace7: UserWorkspace = {
id: 'workspace_7',
title: 'Workspace',
boardCount: 33,
}
const workspace8: UserWorkspace = {
id: 'workspace_8',
title: 'team 33',
boardCount: 14,
}
const workspace9: UserWorkspace = {
id: 'workspace_9',
title: 'Chat6',
boardCount: 17,
}
const workspace10: UserWorkspace = {
id: 'workspace_10',
title: 'Title',
boardCount: 6,
}
test('base case - find all workspaces', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3),
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace1, workspace2, workspace3))))
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8))))
const component = wrapIntl(
<ReduxProvider store={store}>
@ -65,7 +107,7 @@ describe('pages/dashboard/CenterContent', () => {
expect(container).toMatchSnapshot()
})
test('search filter', () => {
test('search filter - search for all workspaces that contain the word workspace', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3),
@ -93,7 +135,7 @@ describe('pages/dashboard/CenterContent', () => {
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace1, workspace2, workspace3))))
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>())))
const component = wrapIntl(
<ReduxProvider store={store}>
@ -103,7 +145,162 @@ describe('pages/dashboard/CenterContent', () => {
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, 'Non-existing workspace')
userEvent.type(searchInput!, 'Non-existing one')
expect(container).toMatchSnapshot()
})
test('search filter - search for workspace with unique name', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace4))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, 'WS 4')
expect(container).toMatchSnapshot()
})
test('search filter - search for workspace name and amount of boards', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace3, workspace4, workspace8))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, 'SOMETHING 3')
expect(container).toMatchSnapshot()
})
test('search filter - search for workspace name and amount of boards 2', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace1, workspace5, workspace7, workspace8))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, 'work 33')
expect(container).toMatchSnapshot()
})
test('search filter - search for amount of boards', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace3, workspace8))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, '14 0')
expect(container).toMatchSnapshot()
})
test('search filter - search for foo baz', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace5))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, 'foo baz')
expect(container).toMatchSnapshot()
})
test('search filter - 5 matching workspaces', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace6, workspace7, workspace8))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, 'workspace')
expect(container).toMatchSnapshot()
})
test('search filter - number search', () => {
const store = mockStore({
workspace: {
userWorkspaces: new Array<UserWorkspace>(workspace1, workspace2, workspace3, workspace4, workspace5, workspace6, workspace7, workspace8, workspace9, workspace10),
},
})
FetchMock.fn.mockReturnValueOnce(FetchMock.jsonResponse(JSON.stringify(new Array<UserWorkspace>(workspace9))))
const component = wrapIntl(
<ReduxProvider store={store}>
<DashboardCenterContent/>
</ReduxProvider>,
)
const {container} = render(component)
const searchInput = container.querySelector('.DashboardPage__search > input')
expect(searchInput).toBeDefined()
userEvent.type(searchInput!, '6')
expect(container).toMatchSnapshot()
})

View file

@ -17,6 +17,16 @@ import Switch from '../../widgets/switch'
import SearchIcon from '../../widgets/icons/search'
import {UserSettings} from '../../userSettings'
const checkBoardCount = (numsArr: RegExpMatchArray, boardCount: number) => {
for (const n of numsArr) {
if (Number(n) === boardCount) {
return true
}
}
return false
}
const DashboardCenterContent = (): JSX.Element => {
const rawWorkspaces = useAppSelector<UserWorkspace[]>(getUserWorkspaceList) || []
const dispatch = useAppDispatch()
@ -34,8 +44,11 @@ const DashboardCenterContent = (): JSX.Element => {
initializeUserWorkspaces()
}, [])
const titlePattern = new RegExp(searchFilter.split(' ').join('|'), 'i')
const extractedNumbers = searchFilter.match(/(\d+)/g)
const userWorkspaces = rawWorkspaces.
filter((workspace) => (workspace.boardCount > 0 || showEmptyWorkspaces) && (workspace.title.toLowerCase().includes(searchFilter) || workspace.boardCount.toString().includes(searchFilter))).
filter((workspace) => (workspace.boardCount > 0 || showEmptyWorkspaces) && (titlePattern.test(workspace.title) || (extractedNumbers && checkBoardCount(extractedNumbers, workspace.boardCount)))).
sort((a, b) => {
if ((a.boardCount === 0 && b.boardCount === 0) || (a.boardCount !== 0 && b.boardCount !== 0)) {
return a.title.localeCompare(b.title)