Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-select modules in the Dashboard #1824

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,12 @@ const deleteModule = draftId => ({
promise: apiDeleteModule(draftId).then(apiGetMyModules)
})

const BULK_DELETE_MODULES = 'BULK_DELETE_MODULES'
const bulkDeleteModules = draftIds => ({
type: BULK_DELETE_MODULES,
promise: Promise.all(draftIds.map(id => apiDeleteModule(id))).then(apiGetMyModules)
})

const CREATE_NEW_MODULE = 'CREATE_NEW_MODULE'
const createNewModule = (useTutorial = false) => ({
type: CREATE_NEW_MODULE,
Expand All @@ -222,6 +228,18 @@ const filterModules = searchString => ({
searchString
})

const SELECT_MODULES = 'SELECT_MODULES'
const selectModules = draftIds => ({
type: SELECT_MODULES,
draftIds
})

const DESELECT_MODULES = 'DESELECT_MODULES'
const deselectModules = draftIds => ({
type: DESELECT_MODULES,
draftIds
})

const SHOW_MODULE_MORE = 'SHOW_MODULE_MORE'
const showModuleMore = module => ({
type: SHOW_MODULE_MORE,
Expand Down Expand Up @@ -278,14 +296,20 @@ module.exports = {
CLEAR_PEOPLE_SEARCH_RESULTS,
DELETE_MODULE_PERMISSIONS,
DELETE_MODULE,
BULK_DELETE_MODULES,
FILTER_MODULES,
SELECT_MODULES,
DESELECT_MODULES,
SHOW_MODULE_MORE,
SHOW_VERSION_HISTORY,
RESTORE_VERSION,
IMPORT_MODULE_FILE,
CHECK_MODULE_LOCK,
filterModules,
selectModules,
deselectModules,
deleteModule,
bulkDeleteModules,
closeModal,
deleteModulePermissions,
searchForUser,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,47 @@ describe('Dashboard Actions', () => {
return assertDeleteModuleRunsWithOptions('/api/drafts')
})

const assertBulkDeleteModulesRunsWithOptions = (secondaryLookupUrl, fetchBody, options) => {
global.fetch.mockResolvedValue(standardFetchResponse)
const actionReply = DashboardActions.bulkDeleteModules(
['mockDraftId1', 'mockDraftId2'],
options
)

expect(global.fetch).toHaveBeenCalledTimes(2)
expect(global.fetch).toHaveBeenCalledWith('/api/drafts/mockDraftId1', {
...defaultFetchOptions,
method: 'DELETE',
body: fetchBody
})
expect(global.fetch).toHaveBeenCalledWith('/api/drafts/mockDraftId2', {
...defaultFetchOptions,
method: 'DELETE',
body: fetchBody
})
global.fetch.mockReset()
global.fetch.mockResolvedValueOnce({
json: () => ({ value: 'mockSecondaryResponse' })
})

expect(actionReply).toEqual({
type: DashboardActions.BULK_DELETE_MODULES,
promise: expect.any(Object)
})

return actionReply.promise.then(finalResponse => {
expect(standardFetchResponse.json).toHaveBeenCalled()
expect(global.fetch).toHaveBeenCalledWith(secondaryLookupUrl, defaultFetchOptions)

expect(finalResponse).toEqual({
value: 'mockSecondaryResponse'
})
})
}
test('bulkDeleteModules returns expected output and calls other functions', () => {
return assertBulkDeleteModulesRunsWithOptions('/api/drafts')
})

// three (plus one default) ways of calling createNewModule plus tutorial/normal module
const assertCreateNewModuleRunsWithOptions = (
createUrl,
Expand Down Expand Up @@ -339,6 +380,26 @@ describe('Dashboard Actions', () => {
})
})

test('selectModules returns the expected output', () => {
const actionReply = DashboardActions.selectModules(['mockDraftId1', 'mockDraftId2'])

expect(global.fetch).not.toHaveBeenCalled()
expect(actionReply).toEqual({
type: DashboardActions.SELECT_MODULES,
draftIds: ['mockDraftId1', 'mockDraftId2']
})
})

test('deselectModules returns the expected output', () => {
const actionReply = DashboardActions.deselectModules(['mockDraftId', 'mockDraftId2'])

expect(global.fetch).not.toHaveBeenCalled()
expect(actionReply).toEqual({
type: DashboardActions.DESELECT_MODULES,
draftIds: ['mockDraftId', 'mockDraftId2']
})
})

test('showModuleMore returns the expected output', () => {
const mockModule = {
draftId: 'mockDraftId',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

exports[`Module renders with expected standard props 1`] = `
<div
className="repository--module-icon is-not-open is-not-new"
className="repository--module-icon is-not-open is-not-selected is-not-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
>
<input
checked={false}
className="is-not-multi-select-mode"
onClick={[Function]}
type="checkbox"
/>
<button
onClick={[Function]}
>
Expand Down Expand Up @@ -44,11 +50,17 @@ exports[`Module renders with expected standard props 1`] = `

exports[`Module renders with expected standard props but hasMenu=false 1`] = `
<div
className="repository--module-icon is-not-open is-not-new"
className="repository--module-icon is-not-open is-not-selected is-not-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
>
<input
checked={false}
className="is-not-multi-select-mode"
onClick={[Function]}
type="checkbox"
/>
<a
href="/library/mockDraftId"
>
Expand All @@ -70,13 +82,101 @@ exports[`Module renders with expected standard props but hasMenu=false 1`] = `
</div>
`;

exports[`Module renders with expected standard props but isMultiSelectMode=true 1`] = `
<div
className="repository--module-icon is-not-open is-not-selected is-not-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
>
<input
checked={false}
className="is-multi-select-mode"
onClick={[Function]}
type="checkbox"
/>
<button
onClick={[Function]}
>
<div
className="repository--module-icon--image"
>
<img
height="100%"
src="/library/module-icon/mockDraftId"
width="100%"
/>
</div>
<div
className="repository--module-icon--title"
>
Mock Module Title
</div>
</button>
</div>
`;

exports[`Module renders with expected standard props but isNew=true 1`] = `
<div
className="repository--module-icon is-not-open is-new"
className="repository--module-icon is-not-open is-not-selected is-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
>
<input
checked={false}
className="is-not-multi-select-mode"
onClick={[Function]}
type="checkbox"
/>
<button
onClick={[Function]}
>
<div
className="repository--module-icon--image"
>
<img
height="100%"
src="/library/module-icon/mockDraftId"
width="100%"
/>
</div>
<div
className="repository--module-icon--menu-control-button"
>
<svg
height="32px"
viewBox="0 0 32 32"
width="32px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4,10h24c1.104,0,2-0.896,2-2s-0.896-2-2-2H4C2.896,6,2,6.896,2,8S2.896,10,4,10z M28,14H4c-1.104,0-2,0.896-2,2 s0.896,2,2,2h24c1.104,0,2-0.896,2-2S29.104,14,28,14z M28,22H4c-1.104,0-2,0.896-2,2s0.896,2,2,2h24c1.104,0,2-0.896,2-2 S29.104,22,28,22z"
/>
</svg>
</div>
<div
className="repository--module-icon--title"
>
Mock Module Title
</div>
</button>
</div>
`;

exports[`Module renders with expected standard props but isSelected=true 1`] = `
<div
className="repository--module-icon is-not-open is-selected is-not-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
>
<input
checked={true}
className="is-not-multi-select-mode"
onClick={[Function]}
type="checkbox"
/>
<button
onClick={[Function]}
>
Expand Down
15 changes: 15 additions & 0 deletions packages/app/obojobo-repository/shared/components/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,19 @@
background-color: $color-dangerous-minor;
}
}

&.secondary-button.dangerous-button {
border: 0.1em solid $color-dangerous;
background-color: white;
color: $color-dangerous;

&:hover {
background-color: $color-dangerous;
color: white;
}
}

&.multi-select {
padding: 0.6em 0.8em;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ const {
deleteModulePermissions,
createNewModule,
filterModules,
selectModules,
deselectModules,
deleteModule,
bulkDeleteModules,
showModulePermissions,
showVersionHistory,
restoreVersion,
Expand All @@ -22,7 +25,10 @@ const mapActionsToProps = {
loadUsersForModule,
deleteModulePermissions,
filterModules,
selectModules,
deselectModules,
deleteModule,
bulkDeleteModules,
showModulePermissions,
showVersionHistory,
restoreVersion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ describe('Dashboard HOC', () => {
addUserToModule: DashboardActions.addUserToModule,
loadUsersForModule: DashboardActions.loadUsersForModule,
deleteModulePermissions: DashboardActions.deleteModulePermissions,
deselectModules: DashboardActions.deselectModules,
selectModules: DashboardActions.selectModules,
filterModules: DashboardActions.filterModules,
importModuleFile: DashboardActions.importModuleFile,
deleteModule: DashboardActions.deleteModule,
bulkDeleteModules: DashboardActions.bulkDeleteModules,
showModulePermissions: DashboardActions.showModulePermissions,
showVersionHistory: DashboardActions.showVersionHistory,
checkModuleLock: DashboardActions.checkModuleLock
Expand Down
Loading