mirror of
https://github.com/overleaf/overleaf.git
synced 2025-01-26 23:21:10 +00:00
Merge pull request #3095 from overleaf/hb-last-login-date-groups-csv
Last login date for groups csv GitOrigin-RevId: c615db3086ec84f2a33710fc0117d711862b6f6c
This commit is contained in:
parent
d932c153c0
commit
0cec198a08
5 changed files with 37 additions and 17 deletions
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable
|
||||
max-len,
|
||||
*/
|
||||
max-len,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
|
@ -14,6 +14,7 @@ const AuthenticationController = require('../Authentication/AuthenticationContro
|
|||
const UserMembershipHandler = require('./UserMembershipHandler')
|
||||
const Errors = require('../Errors/Errors')
|
||||
const EmailHelper = require('../Helpers/EmailHelper')
|
||||
const CSVParser = require('json2csv').Parser
|
||||
|
||||
module.exports = {
|
||||
index(req, res, next) {
|
||||
|
@ -133,6 +134,7 @@ module.exports = {
|
|||
|
||||
exportCsv(req, res, next) {
|
||||
const { entity, entityConfig } = req
|
||||
const fields = ['email', 'last_logged_in_at']
|
||||
|
||||
return UserMembershipHandler.getUsers(entity, entityConfig, function(
|
||||
error,
|
||||
|
@ -141,13 +143,10 @@ module.exports = {
|
|||
if (error != null) {
|
||||
return next(error)
|
||||
}
|
||||
let csvOutput = ''
|
||||
for (let user of Array.from(users)) {
|
||||
csvOutput += user.email + '\n'
|
||||
}
|
||||
const csvParser = new CSVParser({ fields })
|
||||
res.header('Content-Disposition', 'attachment; filename=Group.csv')
|
||||
res.contentType('text/csv')
|
||||
return res.send(csvOutput)
|
||||
return res.send(csvParser.parse(users))
|
||||
})
|
||||
},
|
||||
|
||||
|
|
|
@ -33,7 +33,12 @@ module.exports = UserMembershipViewModel = {
|
|||
}
|
||||
|
||||
const userId = userOrIdOrEmail
|
||||
const projection = { email: 1, first_name: 1, last_name: 1 }
|
||||
const projection = {
|
||||
email: 1,
|
||||
first_name: 1,
|
||||
last_name: 1,
|
||||
lastLoggedIn: 1
|
||||
}
|
||||
return UserGetter.getUser(userId, projection, function(error, user) {
|
||||
if (error != null || user == null) {
|
||||
return callback(null, buildUserViewModelWithId(userId.toString()))
|
||||
|
@ -52,6 +57,7 @@ var buildUserViewModel = function(user, isInvite) {
|
|||
email: user.email || null,
|
||||
first_name: user.first_name || null,
|
||||
last_name: user.last_name || null,
|
||||
last_logged_in_at: user.lastLoggedIn || null,
|
||||
invite: isInvite
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,14 +30,16 @@ block content
|
|||
)
|
||||
li.container-fluid
|
||||
.row
|
||||
.col-md-5
|
||||
.col-md-4
|
||||
input.select-all(
|
||||
select-all,
|
||||
type="checkbox"
|
||||
)
|
||||
span.header #{translate("email")}
|
||||
.col-md-5
|
||||
.col-md-4
|
||||
span.header #{translate("name")}
|
||||
.col-md-2
|
||||
span.header #{translate("last_login")}
|
||||
.col-md-2
|
||||
span.header #{translate("accepted_invite")}
|
||||
li.container-fluid(
|
||||
|
@ -45,15 +47,17 @@ block content
|
|||
ng-controller="UserMembershipListItemController"
|
||||
)
|
||||
.row
|
||||
.col-md-5
|
||||
.col-md-4
|
||||
input.select-item(
|
||||
select-individual,
|
||||
type="checkbox",
|
||||
ng-model="user.selected"
|
||||
)
|
||||
span.email {{ user.email }}
|
||||
.col-md-5
|
||||
.col-md-4
|
||||
span.name {{ user.first_name }} {{ user.last_name }}
|
||||
.col-md-2
|
||||
span.lastLogin {{ user.last_logged_in_at | formatDate:'Do MMM YYYY' }}
|
||||
.col-md-2
|
||||
span.registered
|
||||
i.fa.fa-check.text-success(ng-show="!user.invite" aria-hidden="true")
|
||||
|
@ -102,7 +106,7 @@ block content
|
|||
.row
|
||||
.col-xs-2.col-xs-offset-10(ng-if="paths.exportMembers", ng-cloak)
|
||||
a(href=paths.exportMembers) #{translate('export_csv')}
|
||||
|
||||
|
||||
|
||||
script(type="text/javascript").
|
||||
window.users = !{StringHelper.stringifyJsonForScript(users)};
|
||||
|
|
|
@ -45,8 +45,16 @@ describe('UserMembershipController', function() {
|
|||
}
|
||||
}
|
||||
this.users = [
|
||||
{ _id: 'mock-member-id-1', email: 'mock-email-1@foo.com' },
|
||||
{ _id: 'mock-member-id-2', email: 'mock-email-2@foo.com' }
|
||||
{
|
||||
_id: 'mock-member-id-1',
|
||||
email: 'mock-email-1@foo.com',
|
||||
last_logged_in_at: '2020-08-09T12:43:11.467Z'
|
||||
},
|
||||
{
|
||||
_id: 'mock-member-id-2',
|
||||
email: 'mock-email-2@foo.com',
|
||||
last_logged_in_at: '2020-05-20T10:41:11.407Z'
|
||||
}
|
||||
]
|
||||
|
||||
this.AuthenticationController = {
|
||||
|
@ -311,7 +319,7 @@ describe('UserMembershipController', function() {
|
|||
it('should export the correct csv', function() {
|
||||
return assertCalledWith(
|
||||
this.res.send,
|
||||
'mock-email-1@foo.com\nmock-email-2@foo.com\n'
|
||||
'"email","last_logged_in_at"\n"mock-email-1@foo.com","2020-08-09T12:43:11.467Z"\n"mock-email-2@foo.com","2020-05-20T10:41:11.407Z"'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -38,7 +38,8 @@ describe('UserMembershipViewModel', function() {
|
|||
this.user = {
|
||||
_id: 'mock-user-id',
|
||||
email: 'mock-email@baz.com',
|
||||
first_name: 'Name'
|
||||
first_name: 'Name',
|
||||
lastLoggedIn: '2020-05-20T10:41:11.407Z'
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -48,6 +49,7 @@ describe('UserMembershipViewModel', function() {
|
|||
return expect(viewModel).to.deep.equal({
|
||||
email: this.email,
|
||||
invite: true,
|
||||
last_logged_in_at: null,
|
||||
first_name: null,
|
||||
last_name: null,
|
||||
_id: null
|
||||
|
@ -58,6 +60,7 @@ describe('UserMembershipViewModel', function() {
|
|||
const viewModel = this.UserMembershipViewModel.build(this.user)
|
||||
expect(viewModel._id).to.equal(this.user._id)
|
||||
expect(viewModel.email).to.equal(this.user.email)
|
||||
expect(viewModel.last_logged_in_at).to.equal(this.user.lastLoggedIn)
|
||||
return expect(viewModel.invite).to.equal(false)
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue