Skip to content

Commit 611ce94

Browse files
[FEATURE] [Pix Admin] Si la date de dernière connexion est vide afficher le message « Non connecté depuis 03/2025 » + renommer l’onglet « Méthodes de connexion » (PIX-17109)
#11851
2 parents c051525 + df5cd9c commit 611ce94

File tree

17 files changed

+334
-127
lines changed

17 files changed

+334
-127
lines changed

admin/app/components/certification-centers/membership-item.gjs

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { LinkTo } from '@ember/routing';
55
import Component from '@glimmer/component';
66
import { tracked } from '@glimmer/tracking';
77
import dayjsFormat from 'ember-dayjs/helpers/dayjs-format';
8+
import { t } from 'ember-intl';
89

910
import MembershipItemActions from './membership-item-actions';
1011
import MembershipItemRole from './membership-item-role';
@@ -86,6 +87,8 @@ export default class CertificationCentersMembershipItemComponent extends Compone
8687
<:cell>
8788
{{#if @certificationCenterMembership.lastAccessedAt}}
8889
{{dayjsFormat @certificationCenterMembership.lastAccessedAt "DD-MM-YYYY - HH:mm:ss"}}
90+
{{else}}
91+
{{t "components.certification-centers.membership-item.no-last-connection-date-info"}}
8992
{{/if}}
9093
</:cell>
9194
</PixTableColumn>

admin/app/components/organizations/member-item.gjs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import PixTableColumn from '@1024pix/pix-ui/components/pix-table-column';
22
import { LinkTo } from '@ember/routing';
3+
import { service } from '@ember/service';
34
import Component from '@glimmer/component';
45
import dayjs from 'dayjs';
56

67
import ActionsOnUsersRoleInOrganization from '../actions-on-users-role-in-organization';
78

89
export default class MemberItem extends Component {
10+
@service intl;
11+
912
get lastAccessedAt() {
1013
if (!this.args.organizationMembership.lastAccessedAt) {
11-
return null;
14+
return this.intl.t('components.organizations.member-items.no-last-connection-date-info');
1215
}
1316
return dayjs(this.args.organizationMembership.lastAccessedAt).format('DD/MM/YYYY HH:mm');
1417
}

admin/app/components/users/certification-centers/membership-item.gjs

+2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ export default class UsersCertificationCentersMembershipItemComponent extends Co
9696
<:cell>
9797
{{#if @certificationCenterMembership.lastAccessedAt}}
9898
{{dayjsFormat @certificationCenterMembership.lastAccessedAt "DD/MM/YYYY"}}
99+
{{else}}
100+
{{t "components.users.certification-centers.memberships.no-last-connection-date-info"}}
99101
{{/if}}
100102
</:cell>
101103
</PixTableColumn>

admin/app/components/users/user-detail-personal-information/authentication-method.gjs

+4-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ export default class AuthenticationMethod extends Component {
126126
}
127127

128128
_displayAuthenticationMethodDate(date) {
129-
if (!date) return null;
129+
if (!date)
130+
return this.intl.t(
131+
'components.users.user-detail-personal-information.authentication-method.no-last-connection-date-info',
132+
);
130133
return this.intl.t('components.users.user-detail-personal-information.authentication-method.last-logged-at', {
131134
date: dayjs(date).format('DD/MM/YYYY'),
132135
});

admin/app/components/users/user-organization-memberships.gjs

+2
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ export default class UserOrganizationMemberships extends Component {
7676
<:cell>
7777
{{#if organizationMembership.lastAccessedAt}}
7878
{{dayjsFormat organizationMembership.lastAccessedAt "DD/MM/YYYY"}}
79+
{{else}}
80+
{{t "components.users.organizations.memberships.no-last-connection-date-info"}}
7981
{{/if}}
8082
</:cell>
8183
</PixTableColumn>

admin/app/components/users/user-overview.gjs

+6-2
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,12 @@ export default class UserOverview extends Component {
369369
{{dayjsFormat @user.userLogin.temporaryBlockedUntil "DD/MM/YYYY HH:mm"}}</li>
370370
{{/if}}
371371
<li>
372-
Date de dernière connexion globale :
373-
{{#if @user.lastLoggedAt}}{{dayjsFormat @user.lastLoggedAt "DD/MM/YYYY"}}{{/if}}
372+
{{t "components.users.user-overview.global-last-login"}}
373+
{{#if @user.lastLoggedAt}}
374+
{{dayjsFormat @user.lastLoggedAt "DD/MM/YYYY"}}
375+
{{else}}
376+
{{t "components.users.user-overview.no-last-connection-date-info"}}
377+
{{/if}}
374378
</li>
375379
</ul>
376380
</div>

admin/app/styles/components/users/user-overview.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
display: flex;
44
flex-direction: row;
55
justify-content: space-between;
6-
max-width: 600px;
6+
max-width: fit-content;
77
}
88

99
&__infogroup {

admin/app/templates/authenticated/users/get.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</LinkTo>
1616

1717
<LinkTo @route="authenticated.users.get.authentication-methods" @model={{@model}}>
18-
{{t "pages.user-details.navbar.authentication-methods"}}
18+
{{t "pages.user-details.navbar.connections"}}
1919
({{@model.authenticationMethodCount}})
2020
</LinkTo>
2121

admin/tests/acceptance/authenticated/users/get-test.js

+12-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ module('Acceptance | authenticated/users/get', function (hooks) {
3232
const expectedParticipationCount = 1;
3333
const expectedCertificationCenterCount = 3;
3434
const expectedAuthenticationMethodCount = 3;
35+
const connectionTabLabel = this.intl.t('pages.user-details.navbar.connections');
3536

3637
// when
3738
const screen = await visit(`/users/${user.id}`);
@@ -42,7 +43,7 @@ module('Acceptance | authenticated/users/get', function (hooks) {
4243
const userNavigation = within(screen.getByLabelText("Navigation de la section détails d'un utilisateur"));
4344
assert.dom(userNavigation.getByRole('link', { name: 'Informations prescrit' })).exists();
4445
assert
45-
.dom(userNavigation.getByRole('link', { name: `Méthodes de connexion (${expectedAuthenticationMethodCount})` }))
46+
.dom(userNavigation.getByRole('link', { name: `${connectionTabLabel} (${expectedAuthenticationMethodCount})` }))
4647
.exists();
4748
assert.dom(userNavigation.getByRole('link', { name: 'Profil' })).exists();
4849
assert.dom(userNavigation.getByRole('link', { name: `Participations (${expectedParticipationCount})` })).exists();
@@ -104,6 +105,7 @@ module('Acceptance | authenticated/users/get', function (hooks) {
104105
module('when administrator click on anonymize button and confirm modal', function () {
105106
test('anonymizes the user and remove all authentication methods', async function (assert) {
106107
// given
108+
this.intl = this.owner.lookup('service:intl');
107109
await _buildAndAuthenticateUser(this.server, {
108110
email: 'john.harry@example.net',
109111
username: 'john.harry121297',
@@ -136,12 +138,12 @@ module('Acceptance | authenticated/users/get', function (hooks) {
136138
});
137139
const expectedAuthenticationMethodCountBeforeAnonymisation = 3;
138140
const expectedAuthenticationMethodCountAfterAnonymisation = 0;
139-
141+
const connectionTabLabel = this.intl.t('pages.user-details.navbar.connections');
140142
const screen = await visit(`/users/${userToAnonymise.id}`);
141143
assert
142144
.dom(
143145
screen.getByRole('link', {
144-
name: `Méthodes de connexion (${expectedAuthenticationMethodCountBeforeAnonymisation})`,
146+
name: `${connectionTabLabel} (${expectedAuthenticationMethodCountBeforeAnonymisation})`,
145147
}),
146148
)
147149
.exists();
@@ -158,7 +160,7 @@ module('Acceptance | authenticated/users/get', function (hooks) {
158160
// when & then #2
159161
await click(
160162
screen.getByRole('link', {
161-
name: `Méthodes de connexion (${expectedAuthenticationMethodCountAfterAnonymisation})`,
163+
name: `${connectionTabLabel} (${expectedAuthenticationMethodCountAfterAnonymisation})`,
162164
}),
163165
);
164166
assert.dom(screen.getByLabelText("L'utilisateur n'a pas de méthode de connexion avec identifiant")).exists();
@@ -238,11 +240,15 @@ module('Acceptance | authenticated/users/get', function (hooks) {
238240

239241
module('when administrator click on remove authentication method button', function () {
240242
test('not displays remove link and display unchecked icon', async function (assert) {
241-
const expectedAuthenticationMethodCount = 2;
242243
// given
244+
this.intl = this.owner.lookup('service:intl');
245+
const expectedAuthenticationMethodCount = 2;
246+
const connectionTabLabel = this.intl.t('pages.user-details.navbar.connections');
243247
const user = await _buildAndAuthenticateUser(this.server, { email: 'john.harry@example.net', username: null });
244248
const screen = await visit(`/users/${user.id}`);
245-
await click(screen.getByRole('link', { name: `Méthodes de connexion (${expectedAuthenticationMethodCount})` }));
249+
250+
await click(screen.getByRole('link', { name: `${connectionTabLabel} (${expectedAuthenticationMethodCount})` }));
251+
246252
// when
247253
await click(screen.getAllByRole('button', { name: 'Supprimer' })[0]);
248254

admin/tests/integration/components/certification-centers/membership-item-test.gjs

+77-41
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { clickByName, render as renderScreen } from '@1024pix/ember-testing-library';
22
import { click } from '@ember/test-helpers';
33
import dayjs from 'dayjs';
4+
import { t } from 'ember-intl/test-support';
45
import MembershipItem from 'pix-admin/components/certification-centers/membership-item';
56
import { module, test } from 'qunit';
67
import sinon from 'sinon';
@@ -20,49 +21,84 @@ module('Integration | Component | certification-centers/membership-item', funct
2021
sinon.restore();
2122
});
2223

23-
test('displays a certification center membership table row item', async function (assert) {
24-
// given
25-
const user = store.createRecord('user', {
26-
id: 1,
27-
firstName: 'Jojo',
28-
lastName: 'La Gringue',
29-
email: 'jojo@example.net',
30-
});
31-
const certificationCenterMembership = store.createRecord('certification-center-membership', {
32-
id: 1,
33-
user,
34-
role: 'MEMBER',
35-
createdAt: new Date('2023-09-13T10:47:07Z'),
36-
lastAccessedAt: new Date('2023-12-30T15:21:09Z'),
24+
module('displays a certification center membership table row item', function () {
25+
test('with last access date if exists', async function (assert) {
26+
// given
27+
const user = store.createRecord('user', {
28+
id: 1,
29+
firstName: 'Jojo',
30+
lastName: 'La Gringue',
31+
email: 'jojo@example.net',
32+
});
33+
const certificationCenterMembership = store.createRecord('certification-center-membership', {
34+
id: 1,
35+
user,
36+
role: 'MEMBER',
37+
createdAt: new Date('2023-09-13T10:47:07Z'),
38+
lastAccessedAt: new Date('2023-12-30T15:21:09Z'),
39+
});
40+
41+
const disableCertificationCenterMembership = sinon.stub();
42+
43+
// when
44+
const screen = await renderScreen(
45+
<template>
46+
<MembershipItem
47+
@certificationCenterMembership={{certificationCenterMembership}}
48+
@disableCertificationCenterMembership={{disableCertificationCenterMembership}}
49+
/>
50+
</template>,
51+
);
52+
53+
// then
54+
const expectedLastAccessDate = dayjs(certificationCenterMembership.lastAccessedAt).format(
55+
'DD-MM-YYYY - HH:mm:ss',
56+
);
57+
const expectedCreationDate = dayjs(certificationCenterMembership.createdAt).format('DD-MM-YYYY - HH:mm:ss');
58+
59+
assert.dom(screen.getByRole('link', { name: certificationCenterMembership.id })).exists();
60+
assert.dom(screen.getByRole('cell', { name: user.firstName })).exists();
61+
assert.dom(screen.getByRole('cell', { name: user.lastName })).exists();
62+
assert.dom(screen.getByRole('cell', { name: user.email })).exists();
63+
assert.dom(screen.getByRole('cell', { name: 'Membre' })).exists();
64+
assert.dom(screen.getByRole('cell', { name: expectedLastAccessDate })).exists();
65+
assert.dom(screen.getByRole('cell', { name: expectedCreationDate })).exists();
66+
assert.dom(screen.getByRole('button', { name: 'Modifier le rôle' })).exists();
67+
assert.dom(screen.getByRole('button', { name: 'Désactiver' })).exists();
3768
});
3869

39-
const disableCertificationCenterMembership = sinon.stub();
40-
41-
// when
42-
const screen = await renderScreen(
43-
<template>
44-
<MembershipItem
45-
@certificationCenterMembership={{certificationCenterMembership}}
46-
@disableCertificationCenterMembership={{disableCertificationCenterMembership}}
47-
/>
48-
</template>,
49-
);
50-
51-
// then
52-
const expectedLastAccessedAtDate = dayjs(certificationCenterMembership.lastAccessedAt).format(
53-
'DD-MM-YYYY - HH:mm:ss',
54-
);
55-
const expectedCreationDate = dayjs(certificationCenterMembership.createdAt).format('DD-MM-YYYY - HH:mm:ss');
56-
57-
assert.dom(screen.getByRole('link', { name: certificationCenterMembership.id })).exists();
58-
assert.dom(screen.getByRole('cell', { name: user.firstName })).exists();
59-
assert.dom(screen.getByRole('cell', { name: user.lastName })).exists();
60-
assert.dom(screen.getByRole('cell', { name: user.email })).exists();
61-
assert.dom(screen.getByRole('cell', { name: 'Membre' })).exists();
62-
assert.dom(screen.getByRole('cell', { name: expectedLastAccessedAtDate })).exists();
63-
assert.dom(screen.getByRole('cell', { name: expectedCreationDate })).exists();
64-
assert.dom(screen.getByRole('button', { name: 'Modifier le rôle' })).exists();
65-
assert.dom(screen.getByRole('button', { name: 'Désactiver' })).exists();
70+
test('with default last access date when there is none', async function (assert) {
71+
// given
72+
const user = store.createRecord('user', {
73+
id: 1,
74+
firstName: 'Jojo',
75+
lastName: 'La Gringue',
76+
email: 'jojo@example.net',
77+
});
78+
const certificationCenterMembership = store.createRecord('certification-center-membership', {
79+
id: 1,
80+
user,
81+
role: 'MEMBER',
82+
createdAt: new Date('2023-09-13T10:47:07Z'),
83+
});
84+
85+
const disableCertificationCenterMembership = sinon.stub();
86+
87+
// when
88+
const screen = await renderScreen(
89+
<template>
90+
<MembershipItem
91+
@certificationCenterMembership={{certificationCenterMembership}}
92+
@disableCertificationCenterMembership={{disableCertificationCenterMembership}}
93+
/>
94+
</template>,
95+
);
96+
97+
// then
98+
const defaultLastAccessDate = t('components.certification-centers.membership-item.no-last-connection-date-info');
99+
100+
assert.dom(screen.getByRole('cell', { name: defaultLastAccessDate })).exists();
101+
});
66102
});
67103

68104
module('when clicking on "Modifier le rôle" button', function () {

admin/tests/integration/components/organizations/member-item-test.gjs

+30
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { render } from '@1024pix/ember-testing-library';
22
import dayjs from 'dayjs';
3+
import { t } from 'ember-intl/test-support';
34
import MemberItem from 'pix-admin/components/organizations/member-item';
45
import { module, test } from 'qunit';
56
import sinon from 'sinon';
@@ -44,4 +45,33 @@ module('Integration | Component | MemberItem', function (hooks) {
4445
assert.dom(screen.getByRole('cell', { name: 'toto@example.net' })).exists();
4546
assert.dom(screen.getByRole('cell', { name: dayjs(now).format('DD/MM/YYYY HH:mm') })).exists();
4647
});
48+
module('if there is no last access date', function () {
49+
test('displays default last access date', async function (assert) {
50+
// given
51+
const member = {
52+
user: {
53+
id: 123,
54+
firstName: 'John',
55+
lastName: 'Doe',
56+
email: 'toto@example.net',
57+
},
58+
};
59+
60+
const screen = await render(<template><MemberItem @organizationMembership={{member}} /></template>);
61+
62+
// then
63+
64+
assert.dom(screen.getByRole('cell', { name: '123' })).exists();
65+
assert.dom(screen.getByRole('cell', { name: 'John' })).exists();
66+
assert.dom(screen.getByRole('cell', { name: 'Doe' })).exists();
67+
assert.dom(screen.getByRole('cell', { name: 'toto@example.net' })).exists();
68+
assert
69+
.dom(
70+
screen.getByRole('cell', {
71+
name: t('components.organizations.member-items.no-last-connection-date-info'),
72+
}),
73+
)
74+
.exists();
75+
});
76+
});
4777
});

0 commit comments

Comments
 (0)