diff --git a/src/components/Assignments/ShadowAssignmentPointsTable/ShadowAssignmentPointsTable.js b/src/components/Assignments/ShadowAssignmentPointsTable/ShadowAssignmentPointsTable.js index 27e5c6705..fc6b220fa 100644 --- a/src/components/Assignments/ShadowAssignmentPointsTable/ShadowAssignmentPointsTable.js +++ b/src/components/Assignments/ShadowAssignmentPointsTable/ShadowAssignmentPointsTable.js @@ -194,6 +194,7 @@ class ShadowAssignmentPointsTable extends Component { userId={student.id} showEmail="icon" link={GROUP_USER_SOLUTIONS_URI_FACTORY(groupId, student.id)} + listItem /> {points !== null ? points : } diff --git a/src/components/Exercises/ExercisesListItem/ExercisesListItem.js b/src/components/Exercises/ExercisesListItem/ExercisesListItem.js index 7e310936d..e6358b084 100644 --- a/src/components/Exercises/ExercisesListItem/ExercisesListItem.js +++ b/src/components/Exercises/ExercisesListItem/ExercisesListItem.js @@ -70,7 +70,7 @@ const ExercisesListItem = ({ - + {runtimeEnvironments && } diff --git a/src/components/Exercises/ReferenceSolutionsTable/ReferenceSolutionsTableRow.js b/src/components/Exercises/ReferenceSolutionsTable/ReferenceSolutionsTableRow.js index a8273503f..b8429c455 100644 --- a/src/components/Exercises/ReferenceSolutionsTable/ReferenceSolutionsTableRow.js +++ b/src/components/Exercises/ReferenceSolutionsTable/ReferenceSolutionsTableRow.js @@ -81,7 +81,7 @@ const ReferenceSolutionsTableRow = ({ )} - + diff --git a/src/components/Groups/ResultsTable/ResultsTable.js b/src/components/Groups/ResultsTable/ResultsTable.js index 1d132f13c..2cb113db1 100644 --- a/src/components/Groups/ResultsTable/ResultsTable.js +++ b/src/components/Groups/ResultsTable/ResultsTable.js @@ -256,6 +256,7 @@ class ResultsTable extends Component { currentUserId={loggedUser.id} showEmail="icon" showExternalIdentifiers + listItem link={ isTeacher || user.id === loggedUser.id ? GROUP_USER_SOLUTIONS_URI_FACTORY(group.id, user.id) diff --git a/src/components/Instances/InstancesTable/InstancesTable.js b/src/components/Instances/InstancesTable/InstancesTable.js index 460fdc5dc..9a32743dc 100644 --- a/src/components/Instances/InstancesTable/InstancesTable.js +++ b/src/components/Instances/InstancesTable/InstancesTable.js @@ -32,7 +32,7 @@ const InstancesTable = ({ instances, links: { INSTANCE_URI_FACTORY }, intl }) => {name} - + diff --git a/src/components/Pipelines/PipelineExercisesList/PipelineExercisesList.js b/src/components/Pipelines/PipelineExercisesList/PipelineExercisesList.js index e499db54d..c3f2e3d2d 100644 --- a/src/components/Pipelines/PipelineExercisesList/PipelineExercisesList.js +++ b/src/components/Pipelines/PipelineExercisesList/PipelineExercisesList.js @@ -97,6 +97,7 @@ const PipelineExercisesList = ({ showEmail="icon" noAvatar={exercises.length > COLLAPSE_LIMIT} noAutoload + listItem /> diff --git a/src/components/Pipelines/PipelinesListItem/PipelinesListItem.js b/src/components/Pipelines/PipelinesListItem/PipelinesListItem.js index 637f4733b..71403bfbb 100644 --- a/src/components/Pipelines/PipelinesListItem/PipelinesListItem.js +++ b/src/components/Pipelines/PipelinesListItem/PipelinesListItem.js @@ -123,7 +123,7 @@ const PipelinesListItem = ({ {name} - {showAuthor && {author ? : ReCodEx}} + {showAuthor && {author ? : ReCodEx}} {showCreatedAt && ( diff --git a/src/components/Users/StudentsListItem/StudentsListItem.js b/src/components/Users/StudentsListItem/StudentsListItem.js index 9cb0a0c7b..36cacbb78 100644 --- a/src/components/Users/StudentsListItem/StudentsListItem.js +++ b/src/components/Users/StudentsListItem/StudentsListItem.js @@ -15,7 +15,7 @@ const StudentsListItem = ({ }) => ( - + {stats && ( diff --git a/src/components/Users/SupervisorsListItem/SupervisorsListItem.js b/src/components/Users/SupervisorsListItem/SupervisorsListItem.js index f63cfcecb..801ef2b43 100644 --- a/src/components/Users/SupervisorsListItem/SupervisorsListItem.js +++ b/src/components/Users/SupervisorsListItem/SupervisorsListItem.js @@ -88,7 +88,7 @@ const SupervisorsListItem = ({ )} - + {showButtons && ( diff --git a/src/components/Users/UsersListItem/UsersListItem.js b/src/components/Users/UsersListItem/UsersListItem.js index 29025c24f..c557bd610 100644 --- a/src/components/Users/UsersListItem/UsersListItem.js +++ b/src/components/Users/UsersListItem/UsersListItem.js @@ -27,6 +27,7 @@ const UsersListItem = ({ user, emailColumn = false, createdAtColumn = false, cre showEmail={emailColumn ? null : 'full'} showExternalIdentifiers link + listItem /> diff --git a/src/components/Users/UsersName/UsersName.js b/src/components/Users/UsersName/UsersName.js index 81fdf9d57..511a3a5fa 100644 --- a/src/components/Users/UsersName/UsersName.js +++ b/src/components/Users/UsersName/UsersName.js @@ -7,6 +7,7 @@ import { defaultMemoize } from 'reselect'; import AvatarContainer from '../../../containers/AvatarContainer/AvatarContainer'; import { UserRoleIcon } from '../../helpers/usersRoles'; +import { UserUIDataContext } from '../../../helpers/contexts'; import NotVerified from './NotVerified'; import Icon, { MailIcon, BanIcon } from '../../icons'; import withLinks from '../../../helpers/withLinks'; @@ -25,11 +26,25 @@ const userNameStyle = defaultMemoize((size, large) => ({ const resolveLink = (link, id, USER_URI_FACTORY) => typeof link === 'function' ? link(id) : link === true ? USER_URI_FACTORY(id) : link; +const assembleName = ({ titlesBeforeName = '', firstName, lastName, titlesAfterName = '' }, lastNameFirst = false) => { + const fullName = lastNameFirst ? [lastName, ' ', firstName] : [firstName, ' ', lastName]; + if (titlesBeforeName) { + if (lastNameFirst) { + fullName.push(', ', titlesBeforeName); + } else { + fullName.unshift(titlesBeforeName, ' '); + } + } + if (titlesAfterName) { + fullName.push(', ', titlesAfterName); + } + return fullName.join(''); +}; + const UsersName = ({ id, - fullName, avatarUrl, - name: { firstName }, + name, size = null, large = false, isVerified, @@ -40,103 +55,117 @@ const UsersName = ({ showExternalIdentifiers = false, showRoleIcon = false, currentUserId, + listItem = false, links: { USER_URI_FACTORY }, }) => { if (size === null) { size = large ? 45 : 20; } + const email = privateData && privateData.email && showEmail && encodeURIComponent(privateData.email); const externalIds = privateData && privateData.externalIds; + return ( - - {(!privateData || privateData.isAllowed) && !noAvatar && ( - - - - )} - - {privateData && !privateData.isAllowed && ( - - - - }> - - - )} + + {({ lastNameFirst = true }) => { + const fullName = assembleName(name, listItem && lastNameFirst); + return ( + + {(!privateData || privateData.isAllowed) && !noAvatar && ( + + + + )} + + {privateData && !privateData.isAllowed && ( + + + + }> + + + )} - {link ? {fullName} : {fullName}} + {link ? {fullName} : {fullName}} - {showRoleIcon && privateData && ( - - )} + {showRoleIcon && privateData && ( + + )} - {showExternalIdentifiers && externalIds && Object.keys(externalIds).length > 0 && ( - - - - - - - - {Object.keys(externalIds).map(service => ( - - - - - ))} - -
{service}: - - {Array.isArray(externalIds[service]) - ? externalIds[service].join(', ') - : externalIds[service]} - -
-
- - }> - -
- )} - {privateData && privateData.email && showEmail === 'icon' && ( - - - - )} - {privateData && privateData.email && showEmail === 'full' && ( - - {'('} - {privateData.email} - {')'} - - )} - - {!isVerified && } - -
-
+ {showExternalIdentifiers && externalIds && Object.keys(externalIds).length > 0 && ( + + + + + + + + {Object.keys(externalIds).map(service => ( + + + + + ))} + +
{service}: + + {Array.isArray(externalIds[service]) + ? externalIds[service].join(', ') + : externalIds[service]} + +
+
+ + }> + +
+ )} + {privateData && privateData.email && showEmail === 'icon' && ( + + + + )} + {privateData && privateData.email && showEmail === 'full' && ( + + {'('} + {privateData.email} + {')'} + + )} + + {!isVerified && } + +
+
+ ); + }} + ); }; UsersName.propTypes = { id: PropTypes.string.isRequired, - fullName: PropTypes.string.isRequired, - name: PropTypes.shape({ firstName: PropTypes.string.isRequired }).isRequired, + name: PropTypes.shape({ + titlesBeforeName: PropTypes.string, + firstName: PropTypes.string.isRequired, + lastName: PropTypes.string.isRequired, + titlesAfterName: PropTypes.string, + }).isRequired, avatarUrl: PropTypes.string, isVerified: PropTypes.bool.isRequired, privateData: PropTypes.object, @@ -148,6 +177,7 @@ UsersName.propTypes = { showExternalIdentifiers: PropTypes.bool, showRoleIcon: PropTypes.bool, currentUserId: PropTypes.string.isRequired, + listItem: PropTypes.bool, links: PropTypes.object, }; diff --git a/src/components/forms/EditUserUIDataForm/EditUserUIDataForm.js b/src/components/forms/EditUserUIDataForm/EditUserUIDataForm.js index dc067caf0..79da56620 100644 --- a/src/components/forms/EditUserUIDataForm/EditUserUIDataForm.js +++ b/src/components/forms/EditUserUIDataForm/EditUserUIDataForm.js @@ -99,6 +99,18 @@ const EditUserUIDataForm = ({ } /> + + } + /> + ) } @@ -79,6 +81,7 @@ UsersNameContainer.propTypes = { showRoleIcon: PropTypes.bool, noAutoload: PropTypes.bool, loadUserIfNeeded: PropTypes.func.isRequired, + listItem: PropTypes.bool, }; export default connect( diff --git a/src/locales/cs.json b/src/locales/cs.json index 9225e97e0..3f2db5316 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -613,6 +613,7 @@ "app.editUserUIData.defaultPage.instance": "Detail instance", "app.editUserUIData.editorFontSize": "Velikost fontu v textovém editoru:", "app.editUserUIData.failed": "Nebylo možné uložit nastavení vzhledu.", + "app.editUserUIData.lastNameFirst": "V seznamech zobrazovat uživatelům nejprve příjmení", "app.editUserUIData.openedSidebar": "Postraní panel je ve výchozím stavu rozbalený", "app.editUserUIData.title": "Nastavení vzhledu", "app.editUserUIData.useGravatar": "Používat službu Gravatar pro zobrazování avatarů ostatních uživatelů", diff --git a/src/locales/en.json b/src/locales/en.json index f0a1e8e83..5f00ebaa1 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -613,6 +613,7 @@ "app.editUserUIData.defaultPage.instance": "Instance overview", "app.editUserUIData.editorFontSize": "Code editor font size:", "app.editUserUIData.failed": "Cannot save visual settings of the user.", + "app.editUserUIData.lastNameFirst": "In listings, show last names of users first", "app.editUserUIData.openedSidebar": "Sidebar is unfolded by default", "app.editUserUIData.title": "Visual Settings", "app.editUserUIData.useGravatar": "Use Gravatar service for fetching user avatars", diff --git a/src/pages/AssignmentStats/AssignmentStats.js b/src/pages/AssignmentStats/AssignmentStats.js index 399758bce..f82505c03 100644 --- a/src/pages/AssignmentStats/AssignmentStats.js +++ b/src/pages/AssignmentStats/AssignmentStats.js @@ -97,6 +97,7 @@ const prepareTableColumnDescriptors = defaultMemoize((loggedUserId, assignmentId showEmail="icon" showExternalIdentifiers link={GROUP_USER_SOLUTIONS_URI_FACTORY(groupId, user.id)} + listItem /> ), }), diff --git a/src/pages/EditUser/EditUser.js b/src/pages/EditUser/EditUser.js index e52dd499e..ad6787409 100644 --- a/src/pages/EditUser/EditUser.js +++ b/src/pages/EditUser/EditUser.js @@ -48,6 +48,7 @@ const prepareUserUIDataInitialValues = defaultMemoize( ({ darkTheme = true, vimMode = false, + lastNameFirst = true, openedSidebar = true, useGravatar = true, defaultPage = null, @@ -56,6 +57,7 @@ const prepareUserUIDataInitialValues = defaultMemoize( }) => ({ darkTheme, vimMode, + lastNameFirst, openedSidebar, useGravatar, defaultPage: defaultPage || '',