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

Highlights newly created module #1630

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 @@ -2,7 +2,7 @@

exports[`Module renders with expected standard props 1`] = `
<div
className="repository--module-icon is-not-open"
className="repository--module-icon is-not-open is-not-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
Expand Down Expand Up @@ -62,7 +62,7 @@ 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"
className="repository--module-icon is-not-open is-not-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
Expand Down Expand Up @@ -105,3 +105,63 @@ exports[`Module renders with expected standard props but hasMenu=false 1`] = `
</a>
</div>
`;

exports[`Module renders with expected standard props but isNew=true 1`] = `
<div
className="repository--module-icon is-not-open is-new"
onBlur={[Function]}
onFocus={[Function]}
onMouseLeave={[Function]}
>
<button
onClick={[Function]}
>
<div
className="repository--module-icon--image"
>
<svg
version="1.1"
viewBox="0 0 130 150"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<pattern
dangerouslySetInnerHTML={
Object {
"__html": "<image xlink:href=\\"/library/module-icon/mockDraftId\\" width=\\"150\\" height=\\"150\\" />",
}
}
height="150"
id="module-img-id-mockDraftId"
patternUnits="userSpaceOnUse"
width="150"
/>
</defs>
<path
d="M56.29165124598851 4.999999999999999Q64.9519052838329 0 73.61215932167728 4.999999999999999L121.24355652982142 32.5Q129.9038105676658 37.5 129.9038105676658 47.5L129.9038105676658 102.5Q129.9038105676658 112.5 121.24355652982142 117.5L73.61215932167728 145Q64.9519052838329 150 56.29165124598851 145L8.660254037844387 117.5Q0 112.5 0 102.5L0 47.5Q0 37.5 8.660254037844387 32.5Z"
fill="url(#module-img-id-mockDraftId)"
/>
</svg>
</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>
`;
23 changes: 18 additions & 5 deletions packages/app/obojobo-repository/shared/components/dashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,25 @@ const getSortMethod = sortOrder => {
return sortFn
}

const renderModules = (modules, sortOrder) => {
const renderModules = (modules, sortOrder, newModuleId) => {
const sortFn = getSortMethod(sortOrder)
return modules.sort(sortFn).map(draft => <Module key={draft.draftId} hasMenu={true} {...draft} />)
return modules
.sort(sortFn)
.map(draft => (
<Module isNew={draft.draftId === newModuleId} key={draft.draftId} hasMenu={true} {...draft} />
))
}

const Dashboard = props => {
const [sortOrder, setSortOrder] = useState(props.sortOrder)
const [newModuleId, setNewModuleId] = useState(null)

const handleCreateNewModule = useTutorial => {
props.createNewModule(useTutorial).then(data => {
data.payload.value.sort(getSortMethod('newest'))
setNewModuleId(data.payload.value[0].draftId)
})
}

// Set a cookie when sortOrder changes on the client
// can't undefine document to test this 'else' case without breaking everything - maybe later
Expand All @@ -142,8 +154,8 @@ const Dashboard = props => {
<section className="repository--main-content">
<div className="repository--main-content--control-bar">
<MultiButton title="New Module">
<Button onClick={() => props.createNewModule(false)}>New Module</Button>
<Button onClick={() => props.createNewModule(true)}>New Tutorial</Button>
<Button onClick={() => handleCreateNewModule(false)}>New Module</Button>
<Button onClick={() => handleCreateNewModule(true)}>New Tutorial</Button>
<Button onClick={props.importModuleFile}>Upload...</Button>
</MultiButton>
<Search
Expand All @@ -169,7 +181,8 @@ const Dashboard = props => {
<div className="repository--item-list--collection--item--multi-wrapper">
{renderModules(
props.filteredModules ? props.filteredModules : props.myModules,
sortOrder
sortOrder,
newModuleId
)}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,23 +292,45 @@ describe('Dashboard', () => {
})

test('"New Module" and "Upload..." buttons call functions appropriately', () => {
const newModule = {
payload: {
value: [
{
draftId: 'mockId1',
createdAt: 1
},
{
draftId: 'mockId2',
createdAt: 2
}
]
}
}
dashboardProps.createNewModule = jest.fn()
dashboardProps.importModuleFile = jest.fn()
const component = create(<Dashboard {...dashboardProps} />)

const setNewModuleId = jest.fn()
const handleClick = jest.spyOn(React, 'useState')
handleClick.mockImplementation(newModuleId => [newModuleId, setNewModuleId])

// three buttons under the 'New Module +' MultiButton component
const multiButton = component.root.findByType(MultiButton).children[0]

// 'New Module' button should call createNewModule with false
expect(multiButton.children[0].children[0].children[0]).toBe('New Module')
dashboardProps.createNewModule.mockResolvedValue(newModule)
multiButton.children[0].props.onClick()
expect(dashboardProps.createNewModule).toHaveBeenCalledTimes(1)
expect(setNewModuleId).toBeTruthy()
dashboardProps.createNewModule.mockReset()

// 'New Tutorial' button should call createNewModule with true
expect(multiButton.children[1].children[0].children[0]).toBe('New Tutorial')
dashboardProps.createNewModule.mockResolvedValue(newModule)
multiButton.children[1].props.onClick()
expect(dashboardProps.createNewModule).toHaveBeenCalledTimes(1)
expect(setNewModuleId).toBeTruthy()
dashboardProps.createNewModule.mockReset()

// 'Upload...' button should call importModuleFile with no arguments
Expand Down
6 changes: 5 additions & 1 deletion packages/app/obojobo-repository/shared/components/module.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ const Module = props => {
return (
<div
onMouseLeave={onCloseMenu}
className={'repository--module-icon ' + (isMenuOpen ? 'is-open' : 'is-not-open')}
className={
'repository--module-icon ' +
(isMenuOpen ? 'is-open ' : 'is-not-open ') +
(props.isNew ? 'is-new' : 'is-not-new')
}
onBlur={onBlurHandler}
onFocus={onFocusHandler}
>
Expand Down
8 changes: 8 additions & 0 deletions packages/app/obojobo-repository/shared/components/module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@
background-color: $color-banner-bg;
}

&.is-new {
background-color: lighten($color-action-minor, 15%);

.repository--module-icon--title {
font-weight: bold;
}
}

&:hover {
border-color: $color-banner-bg;

Expand Down
27 changes: 24 additions & 3 deletions packages/app/obojobo-repository/shared/components/module.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ describe('Module', () => {
defaultProps = {
draftId: 'mockDraftId',
title: 'Mock Module Title',
hasMenu: true
hasMenu: true,
isNew: false
}
})

Expand All @@ -27,7 +28,9 @@ describe('Module', () => {

expect(component.root.findAllByType(ModuleMenu).length).toBe(0)

expect(component.root.children[0].props.className).toBe('repository--module-icon is-not-open')
expect(component.root.children[0].props.className).toBe(
'repository--module-icon is-not-open is-not-new'
)

const mainChildComponent = component.root.children[0].children[0]
expect(mainChildComponent.type).toBe('button')
Expand All @@ -41,7 +44,9 @@ describe('Module', () => {

expect(component.root.findAllByType(ModuleMenu).length).toBe(0)

expect(component.root.children[0].props.className).toBe('repository--module-icon is-not-open')
expect(component.root.children[0].props.className).toBe(
'repository--module-icon is-not-open is-not-new'
)

const mainChildComponent = component.root.children[0].children[0]
expect(mainChildComponent.type).toBe('a')
Expand All @@ -50,6 +55,22 @@ describe('Module', () => {
expect(component.toJSON()).toMatchSnapshot()
})

test('renders with expected standard props but isNew=true', () => {
defaultProps.isNew = true
const component = create(<Module {...defaultProps} />)

expect(component.root.findAllByType(ModuleMenu).length).toBe(0)

expect(component.root.children[0].props.className).toBe(
'repository--module-icon is-not-open is-new'
)

const mainChildComponent = component.root.children[0].children[0]
expect(mainChildComponent.type).toBe('button')

expect(component.toJSON()).toMatchSnapshot()
})

test('clicking the main child component when hasMenu=true renders the module menu', () => {
const reusableComponent = <Module {...defaultProps} />
let component
Expand Down