[web] Migrate group management to React (#11293)
* Rename manage group entry point * Migrate group management root page to React * Add cypress tests for the group management react page * Fix linting * Add checkbox labels for screen-readers + remove unused classes * Await on add/remove members calls * Display the export CSV link for a full group * Display error message when group is full * Sort locales * Handle the managers management page in React version * Fix missing type in GroupMemberRow * Split members and managers React pages * Build API paths on frontend side + add cypress tests for each page * Fix linting * Update unit tests * Review improvements * Type API errors GitOrigin-RevId: d124a9d24cbf33de8aacc5d69e9d46e7bcda93c5
This commit is contained in:
committed by
Copybot
parent
b1cf4aa1e9
commit
ed40a87cdc
@@ -20,7 +20,7 @@ const SplitTestHandler = require('../SplitTests/SplitTestHandler')
|
||||
const CSVParser = require('json2csv').Parser
|
||||
const logger = require('@overleaf/logger')
|
||||
|
||||
async function index(req, res, next) {
|
||||
async function manageGroupMembers(req, res, next) {
|
||||
try {
|
||||
const assignment = await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
@@ -28,7 +28,7 @@ async function index(req, res, next) {
|
||||
'subscription-pages-react'
|
||||
)
|
||||
if (assignment.variant === 'active') {
|
||||
await _indexReact(req, res, next)
|
||||
await _manageGroupMembersReact(req, res, next)
|
||||
} else {
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
@@ -41,7 +41,85 @@ async function index(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
function _indexReact(req, res, next) {
|
||||
async function manageGroupManagers(req, res, next) {
|
||||
try {
|
||||
const assignment = await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'subscription-pages-react'
|
||||
)
|
||||
if (assignment.variant === 'active') {
|
||||
await _renderManagersPage(
|
||||
req,
|
||||
res,
|
||||
next,
|
||||
'user_membership/group-managers-react'
|
||||
)
|
||||
} else {
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
{ err: error },
|
||||
'failed to get "subscription-pages-react" split test assignment'
|
||||
)
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
async function manageInstitutionManagers(req, res, next) {
|
||||
try {
|
||||
const assignment = await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'subscription-pages-react'
|
||||
)
|
||||
if (assignment.variant === 'active') {
|
||||
await _renderManagersPage(
|
||||
req,
|
||||
res,
|
||||
next,
|
||||
'user_membership/institution-managers-react'
|
||||
)
|
||||
} else {
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
{ err: error },
|
||||
'failed to get "subscription-pages-react" split test assignment'
|
||||
)
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
async function managePublisherManagers(req, res, next) {
|
||||
try {
|
||||
const assignment = await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'subscription-pages-react'
|
||||
)
|
||||
if (assignment.variant === 'active') {
|
||||
await _renderManagersPage(
|
||||
req,
|
||||
res,
|
||||
next,
|
||||
'user_membership/publisher-managers-react'
|
||||
)
|
||||
} else {
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn(
|
||||
{ err: error },
|
||||
'failed to get "subscription-pages-react" split test assignment'
|
||||
)
|
||||
await _indexAngular(req, res, next)
|
||||
}
|
||||
}
|
||||
|
||||
async function _manageGroupMembersReact(req, res, next) {
|
||||
const { entity, entityConfig } = req
|
||||
return entity.fetchV1Data(function (error, entity) {
|
||||
if (error != null) {
|
||||
@@ -60,14 +138,40 @@ function _indexReact(req, res, next) {
|
||||
if (entityConfig.fields.name) {
|
||||
entityName = entity[entityConfig.fields.name]
|
||||
}
|
||||
return res.render('user_membership/index-react', {
|
||||
return res.render('user_membership/group-members-react', {
|
||||
name: entityName,
|
||||
groupId: entityPrimaryKey,
|
||||
users,
|
||||
groupSize: entity.membersLimit,
|
||||
})
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
async function _renderManagersPage(req, res, next, template) {
|
||||
const { entity, entityConfig } = req
|
||||
return entity.fetchV1Data(function (error, entity) {
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
return UserMembershipHandler.getUsers(
|
||||
entity,
|
||||
entityConfig,
|
||||
function (error, users) {
|
||||
let entityName
|
||||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
const entityPrimaryKey =
|
||||
entity[entityConfig.fields.primaryKey].toString()
|
||||
if (entityConfig.fields.name) {
|
||||
entityName = entity[entityConfig.fields.name]
|
||||
}
|
||||
return res.render(template, {
|
||||
name: entityName,
|
||||
users,
|
||||
groupSize: entityConfig.hasMembersLimit
|
||||
? entity.membersLimit
|
||||
: undefined,
|
||||
translations: entityConfig.translations,
|
||||
paths: entityConfig.pathsFor(entityPrimaryKey),
|
||||
groupId: entityPrimaryKey,
|
||||
})
|
||||
}
|
||||
)
|
||||
@@ -108,7 +212,10 @@ function _indexAngular(req, res, next) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
index,
|
||||
manageGroupMembers,
|
||||
manageGroupManagers,
|
||||
manageInstitutionManagers,
|
||||
managePublisherManagers,
|
||||
add(req, res, next) {
|
||||
const { entity, entityConfig } = req
|
||||
const email = EmailHelper.parseEmail(req.body.email)
|
||||
|
||||
@@ -22,7 +22,7 @@ module.exports = {
|
||||
webRouter.get(
|
||||
'/manage/groups/:id/members',
|
||||
UserMembershipMiddleware.requireGroupManagementAccess,
|
||||
UserMembershipController.index
|
||||
UserMembershipController.manageGroupMembers
|
||||
)
|
||||
webRouter.post(
|
||||
'/manage/groups/:id/invites',
|
||||
@@ -51,7 +51,7 @@ module.exports = {
|
||||
webRouter.get(
|
||||
'/manage/groups/:id/managers',
|
||||
UserMembershipMiddleware.requireGroupManagersManagementAccess,
|
||||
UserMembershipController.index
|
||||
UserMembershipController.manageGroupManagers
|
||||
)
|
||||
webRouter.post(
|
||||
'/manage/groups/:id/managers',
|
||||
@@ -68,7 +68,7 @@ module.exports = {
|
||||
webRouter.get(
|
||||
'/manage/institutions/:id/managers',
|
||||
UserMembershipMiddleware.requireInstitutionManagementAccess,
|
||||
UserMembershipController.index
|
||||
UserMembershipController.manageInstitutionManagers
|
||||
)
|
||||
webRouter.post(
|
||||
'/manage/institutions/:id/managers',
|
||||
@@ -85,7 +85,7 @@ module.exports = {
|
||||
webRouter.get(
|
||||
'/manage/publishers/:id/managers',
|
||||
UserMembershipMiddleware.requirePublisherManagementAccess,
|
||||
UserMembershipController.index
|
||||
UserMembershipController.managePublisherManagers
|
||||
)
|
||||
webRouter.post(
|
||||
'/manage/publishers/:id/managers',
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
extends ../layout-marketing
|
||||
|
||||
block entrypointVar
|
||||
- entrypoint = 'pages/user/subscription/group-management/group-managers'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
meta(name="ol-groupId", data-type="string", content=groupId)
|
||||
meta(name="ol-groupName", data-type="string", content=name)
|
||||
|
||||
block content
|
||||
main.content.content-alt#subscription-manage-group-root
|
||||
@@ -0,0 +1,13 @@
|
||||
extends ../layout-marketing
|
||||
|
||||
block entrypointVar
|
||||
- entrypoint = 'pages/user/subscription/group-management/group-members'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
meta(name="ol-groupId", data-type="string", content=groupId)
|
||||
meta(name="ol-groupName", data-type="string", content=name)
|
||||
meta(name="ol-groupSize", data-type="json", content=groupSize)
|
||||
|
||||
block content
|
||||
main.content.content-alt#subscription-manage-group-root
|
||||
@@ -1,12 +0,0 @@
|
||||
extends ../layout-marketing
|
||||
|
||||
block entrypointVar
|
||||
- entrypoint = 'pages/user/membership/groups'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
meta(name="ol-paths", data-type="json", content=paths)
|
||||
meta(name="ol-groupSize", data-type="json", content=groupSize)
|
||||
|
||||
block content
|
||||
main.content.content-alt#subscription-manage-groups-root
|
||||
@@ -0,0 +1,12 @@
|
||||
extends ../layout-marketing
|
||||
|
||||
block entrypointVar
|
||||
- entrypoint = 'pages/user/subscription/group-management/institution-managers'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
meta(name="ol-groupId", data-type="string", content=groupId)
|
||||
meta(name="ol-groupName", data-type="string", content=name)
|
||||
|
||||
block content
|
||||
main.content.content-alt#subscription-manage-group-root
|
||||
@@ -0,0 +1,12 @@
|
||||
extends ../layout-marketing
|
||||
|
||||
block entrypointVar
|
||||
- entrypoint = 'pages/user/subscription/group-management/publisher-managers'
|
||||
|
||||
block append meta
|
||||
meta(name="ol-users", data-type="json", content=users)
|
||||
meta(name="ol-groupId", data-type="string", content=groupId)
|
||||
meta(name="ol-groupName", data-type="string", content=name)
|
||||
|
||||
block content
|
||||
main.content.content-alt#subscription-manage-group-root
|
||||
Reference in New Issue
Block a user