Module Options
+
Your Access Level: {levelName[props.accessLevel]}
-
- Preview
-
-
View with preview controls.
+
+
+ Preview
+
+
View with preview controls.
+
-
- Edit
-
-
Write, edit, and update.
+ {props.accessLevel !== MINIMAL && (
+
+
+ Edit
+
+
Write, edit, and update.
+
+ )}
-
-
Add or remove collaborators.
+ {props.accessLevel === FULL && (
+
+
+
Add or remove collaborators.
+
+ )}
-
-
View scores by student.
+
+
+
View scores by student.
+
-
-
View and restore previous versions.
+ {props.accessLevel !== MINIMAL && (
+
+
+
View and restore previous versions.
+
+ )}
-
-
Add to or remove from private collections.
+
+
+
Add to or remove from private collections.
+
-
-
Download a copy in JSON format.
+ {props.accessLevel !== MINIMAL && (
+
+
+
Download a copy in JSON format.
+
+ )}
-
-
Download a copy in XML format.
+ {props.accessLevel !== MINIMAL && (
+
+
+
Download a copy in XML format.
+
+ )}
-
- Public Page
-
-
Visit this modules public page.
+
+
+ Public Page
+
+
Visit this modules public page.
+
-
-
Say farewell.
+ {props.accessLevel === FULL && (
+
+
+
Say farewell.
+
+ )}
Module Access
-
People who can edit this module
+
People who can access this module
Add People
diff --git a/packages/app/obojobo-repository/shared/components/module-permissions-dialog.scss b/packages/app/obojobo-repository/shared/components/module-permissions-dialog.scss
index 46243b642e..2eb5914ff4 100644
--- a/packages/app/obojobo-repository/shared/components/module-permissions-dialog.scss
+++ b/packages/app/obojobo-repository/shared/components/module-permissions-dialog.scss
@@ -52,6 +52,11 @@
.wrapper {
padding-left: 1.25em;
padding-right: 1.25em;
+
+ p {
+ font-size: 0.8em;
+ margin: 0;
+ }
}
.title {
@@ -75,49 +80,78 @@
$dimensions-avatar: 1.8em;
$dimensions-close-button: 1.2em;
- text-align: left;
+ // text-align: left;
height: 11.5em;
- overflow-y: scroll;
+ overflow-y: auto;
list-style: none;
font-size: 0.9em;
padding: 0;
margin: 0;
li {
- max-width: 75%;
+ max-width: 95%;
&:first-child {
- margin-top: 1em;
+ margin-top: 0.5em;
}
&:last-child {
- margin-bottom: 1em;
+ margin-bottom: 0.5em;
}
}
}
- .delete-button,
- .delete-label {
- margin-top: 1em;
+ .access-level-dropdown {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin: 5px;
+ font-size: 0.8em;
+ flex: 2;
+
+ select {
+ font-family: 'Libre Franklin', Arial, sans-serif;
+ border-radius: 0.25em;
+ background-color: #ffffff;
+ padding: 0.7em 3em 0.7em 0.5em;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+
+ /* prettier-ignore */
+ background-image:
+ linear-gradient(
+ 45deg,
+ transparent 50%,
+ gray 50%
+ ),
+ linear-gradient(135deg, gray 50%, transparent 50%);
+
+ /* prettier-ignore */
+ background-position:
+ calc(100% - 1.5em) 1.1em,
+ calc(100% - 1.1em) 1.1em,
+ calc(100% - 2.5em) 0.5em;
+
+ // stylelint-disable unit-disallowed-list
+ background-size: 0.4em 0.4em, 0.4em 0.4em, 0.1em 1.5em;
+ background-repeat: no-repeat;
+ cursor: pointer;
+ position: relative;
+ align-self: center;
+ margin-left: 10px;
+ font-size: 0.9em;
+
+ &:disabled {
+ cursor: not-allowed;
+ }
+ }
}
- .buttons-with-labels {
- text-align: left;
- margin: 2em 0;
+ .button-label-group {
display: grid;
grid-template-columns: 8em auto;
- grid-gap: 0.6em;
+ margin: 0.6em;
align-items: center;
-
- .label {
- font-size: 0.8em;
- }
-
- .repository--button {
- min-width: 10.5em;
- display: inline-block;
- text-align: center;
- margin-right: 1em;
- }
}
}
diff --git a/packages/app/obojobo-repository/shared/components/module-permissions-dialog.test.js b/packages/app/obojobo-repository/shared/components/module-permissions-dialog.test.js
index 9053b90bda..9ce93ff56b 100644
--- a/packages/app/obojobo-repository/shared/components/module-permissions-dialog.test.js
+++ b/packages/app/obojobo-repository/shared/components/module-permissions-dialog.test.js
@@ -9,6 +9,8 @@ import React from 'react'
import ReactModal from 'react-modal'
import { create, act } from 'react-test-renderer'
+import { FULL, PARTIAL, MINIMAL } from 'obojobo-express/server/constants'
+
import ModulePermissionsDialog from './module-permissions-dialog'
import PeopleSearchDialog from './people-search-dialog-hoc'
import PeopleListItem from './people-list-item'
@@ -30,6 +32,7 @@ describe('ModulePermissionsDialog', () => {
loadUsersForModule: jest.fn(),
addUserToModule: jest.fn(),
deleteModulePermissions: jest.fn(),
+ changeAccessLevel: jest.fn(),
onClose: jest.fn()
}
})
@@ -209,6 +212,33 @@ describe('ModulePermissionsDialog', () => {
expect(defaultProps.deleteModulePermissions).toHaveBeenCalledWith('mockDraftId', 1)
})
+ test('props.changeAccessLevel is called when a peopleListItem access level is changed', () => {
+ defaultProps.draftPermissions['mockDraftId'] = {
+ items: [{ id: 1, accessLevel: FULL }, { id: 99, accessLevel: MINIMAL }]
+ }
+ const reusableComponent =
+ let component
+ act(() => {
+ component = create(reusableComponent)
+ })
+
+ expectLoadUsersForModuleToBeCalledOnceWithId()
+
+ const peopleListItems = component.root.findAllByType(PeopleListItem)
+ expect(peopleListItems.length).toBe(2)
+ expect(peopleListItems[0].props.id).toBe(1)
+ expect(peopleListItems[0].props.isMe).toBe(false)
+ expect(peopleListItems[1].props.id).toBe(99)
+ expect(peopleListItems[1].props.isMe).toBe(true)
+
+ act(() => {
+ peopleListItems[0].findByType('select').props.onChange({ target: { value: PARTIAL } })
+ })
+
+ expect(defaultProps.changeAccessLevel).toHaveBeenCalledTimes(1)
+ expect(defaultProps.changeAccessLevel).toHaveBeenCalledWith('mockDraftId', 1, PARTIAL)
+ })
+
test('confirmation window denied when "x" button is clicked on peopleList item for current user', () => {
window.confirm = jest.fn()
window.confirm.mockReturnValue(false)
diff --git a/packages/app/obojobo-repository/shared/components/module.jsx b/packages/app/obojobo-repository/shared/components/module.jsx
index f365668aa1..497e205b2d 100644
--- a/packages/app/obojobo-repository/shared/components/module.jsx
+++ b/packages/app/obojobo-repository/shared/components/module.jsx
@@ -67,7 +67,12 @@ const Module = props => {
)}
{isMenuOpen && !props.isDeleted ? (
-
+
) : null}
{props.children}
diff --git a/packages/app/obojobo-repository/shared/components/people-list-item.jsx b/packages/app/obojobo-repository/shared/components/people-list-item.jsx
index 1caae1d866..d3d1b7a991 100644
--- a/packages/app/obojobo-repository/shared/components/people-list-item.jsx
+++ b/packages/app/obojobo-repository/shared/components/people-list-item.jsx
@@ -3,18 +3,20 @@ require('./people-list-item.scss')
const React = require('react')
const Avatar = require('./avatar')
-const PeopleListItem = props => (
-
-
-
-
- {`${props.firstName} ${props.lastName}`} {props.isMe ?
(me) : null}
+const PeopleListItem = props => {
+ return (
+
+
+
+
+ {`${props.firstName} ${props.lastName}`} {props.isMe ? (me) : null}
+
+
{props.username}
- {props.username}
-
- {props.children}
-
-)
+ {props.children}
+
+ )
+}
PeopleListItem.defaultProps = {
firstName: '',
diff --git a/packages/app/obojobo-repository/shared/components/people-list-item.scss b/packages/app/obojobo-repository/shared/components/people-list-item.scss
index ee3f14d998..5b18999259 100644
--- a/packages/app/obojobo-repository/shared/components/people-list-item.scss
+++ b/packages/app/obojobo-repository/shared/components/people-list-item.scss
@@ -4,10 +4,12 @@
$dimensions-avatar: 1.8em;
$dimensions-close-button: 1.2em;
- padding: 0.3em;
+ display: flex;
margin: 0 auto;
position: relative;
border-radius: 0.25em;
+ text-align: left;
+ align-items: center;
&:hover {
background-color: lighten($color-banner-bg, 2%);
@@ -38,6 +40,7 @@
.user-info {
padding-left: 2.5em;
padding-right: 2.5em;
+ flex: 2;
}
> button {
@@ -52,9 +55,7 @@
min-width: $dimensions-close-button;
line-height: $dimensions-close-button;
background-color: inherit;
- position: absolute;
- right: 0.5em;
- top: 50%;
transform: translate(0, -50%);
+ flex: 1;
}
}
diff --git a/packages/obonode/obojobo-sections-assessment/server/express.js b/packages/obonode/obojobo-sections-assessment/server/express.js
index b9c892a451..0fb760fd11 100644
--- a/packages/obonode/obojobo-sections-assessment/server/express.js
+++ b/packages/obonode/obojobo-sections-assessment/server/express.js
@@ -214,9 +214,9 @@ router
.get((req, res) => {
let currentUserHasPermissionToDraft
- return DraftPermissions.userHasPermissionToDraft(req.currentUser.id, req.params.draftId)
+ return DraftPermissions.getUserAccessLevelToDraft(req.currentUser.id, req.params.draftId)
.then(result => {
- currentUserHasPermissionToDraft = result
+ currentUserHasPermissionToDraft = result !== null
// Users must either have some level of permissions to this draft, or have
// the canViewSystemStats permission
diff --git a/packages/obonode/obojobo-sections-assessment/server/express.test.js b/packages/obonode/obojobo-sections-assessment/server/express.test.js
index 74930f2e16..37e3103aa4 100644
--- a/packages/obonode/obojobo-sections-assessment/server/express.test.js
+++ b/packages/obonode/obojobo-sections-assessment/server/express.test.js
@@ -42,6 +42,7 @@ const assessmentExpress = require('./express')
const express_response_decorator = require('obojobo-express/server/express_response_decorator')
const express = require('express')
const { ERROR_INVALID_ATTEMPT_END, ERROR_INVALID_ATTEMPT_RESUME } = require('./error-constants')
+const { FULL } = require('obojobo-express/server/constants')
const DraftPermissions = require('../../../app/obojobo-repository/server/models/draft_permissions')
let app
@@ -488,7 +489,7 @@ describe('server/express', () => {
}
next()
})
- DraftPermissions.userHasPermissionToDraft.mockResolvedValueOnce(true)
+ DraftPermissions.getUserAccessLevelToDraft.mockResolvedValueOnce(FULL)
AssessmentModel.fetchAttemptHistoryDetails.mockResolvedValueOnce(mockReturnValue)
const response = await request(app)
@@ -530,7 +531,7 @@ describe('server/express', () => {
}
next()
})
- DraftPermissions.userHasPermissionToDraft.mockResolvedValueOnce(true)
+ DraftPermissions.getUserAccessLevelToDraft.mockResolvedValueOnce(FULL)
AssessmentModel.fetchAttemptHistoryDetails.mockResolvedValueOnce(mockReturnValue)
const response = await request(app)
@@ -587,7 +588,7 @@ describe('server/express', () => {
}
next()
})
- DraftPermissions.userHasPermissionToDraft.mockResolvedValueOnce(false)
+ DraftPermissions.getUserAccessLevelToDraft.mockResolvedValueOnce(null)
AssessmentModel.fetchAttemptHistoryDetails.mockResolvedValueOnce(mockReturnValue)
const response = await request(app)
@@ -642,7 +643,7 @@ describe('server/express', () => {
}
next()
})
- DraftPermissions.userHasPermissionToDraft.mockResolvedValueOnce(false)
+ DraftPermissions.getUserAccessLevelToDraft.mockResolvedValueOnce(null)
AssessmentModel.fetchAttemptHistoryDetails.mockResolvedValueOnce(mockReturnValue)
const response = await request(app)
@@ -662,7 +663,7 @@ describe('server/express', () => {
test('GET /api/assessments/:draftId/details fails', async () => {
expect.hasAssertions()
- DraftPermissions.userHasPermissionToDraft.mockResolvedValueOnce(true)
+ DraftPermissions.getUserAccessLevelToDraft.mockResolvedValueOnce(FULL)
AssessmentModel.fetchAttemptHistoryDetails.mockRejectedValueOnce(Error('Oops!'))
const response = await request(app)