Skip to content

Commit e4d0aff

Browse files
xav-caralicegoarnisson
authored andcommitted
feat(orga): add pix navigation
1 parent 7bc62e6 commit e4d0aff

25 files changed

+338
-382
lines changed

high-level-tests/e2e/cypress/support/step_definitions/login-logout.js

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ When(`je me déconnecte`, () => {
8585
});
8686

8787
When(`je me déconnecte de Pix Orga`, () => {
88-
cy.get('[aria-label="Ouvrir le menu utilisateur"]').click();
8988
cy.contains("Se déconnecter").click();
9089
});
9190

orga/app/components/layout/organization-places-or-credit-info.gjs

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import PixIcon from '@1024pix/pix-ui/components/pix-icon';
22
import PixTooltip from '@1024pix/pix-ui/components/pix-tooltip';
3-
import { LinkTo } from '@ember/routing';
43
import { service } from '@ember/service';
54
import Component from '@glimmer/component';
65
import { t } from 'ember-intl';
@@ -10,30 +9,27 @@ export default class OrganizationPlacesOrCreditInfo extends Component {
109
@service currentUser;
1110

1211
get canShowCredit() {
13-
return this.currentUser.isAdminInOrganization && this.currentUser.organization.credit > 0;
12+
const canShow = this.currentUser.isAdminInOrganization && this.currentUser.organization.credit > 0;
13+
this.args.onCanShowCredit?.(canShow);
14+
return canShow;
1415
}
1516

1617
<template>
1718
{{#if this.currentUser.prescriber.placesManagement}}
18-
<div class="organization-places-or-credit-info hide-on-mobile">
19+
<div class="organization-places-or-credit-info">
1920
{{#if (eq @placesCount 0)}}
2021
<span class="organization-places-or-credit-info__warning">
2122
<PixIcon @name="warning" @plainIcon={{true}} class="warning-icon" />
2223
{{t "navigation.places.number" count=@placesCount}}</span>
2324
{{else}}
2425
<span>{{t "navigation.places.number" count=@placesCount}}</span>
2526
{{/if}}
26-
{{#if this.currentUser.isAdminInOrganization}}
27-
<LinkTo @route="authenticated.places" class="organization-places-or-credit-info__link">
28-
{{t "navigation.places.link"}}
29-
</LinkTo>
30-
{{/if}}
3127
</div>
3228
{{else if this.canShowCredit}}
33-
<div class="organization-places-or-credit-info organization-places-or-credit-info--inline hide-on-mobile">
29+
<div class="organization-places-or-credit-info">
3430
<span>{{t "navigation.credits.number" count=this.currentUser.organization.credit}}</span>
3531

36-
<PixTooltip @id="credit-info-tooltip" @position="bottom-left" @isWide={{true}} @isLight={{true}}>
32+
<PixTooltip @id="credit-info-tooltip" @position="bottom" @isWide={{true}} @isLight={{true}}>
3733
<:triggerElement>
3834
<PixIcon
3935
@name="help"
+42-60
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,67 @@
1-
<aside class="sidebar">
2-
<header class="sidebar__logo hide-on-mobile">
1+
<PixNavigation @variant="orga" @navigationAriaLabel={{t "navigation.main.aria-label"}} @menuLabel="Menu">
2+
<:brand>
33
<LinkTo @route={{this.redirectionRoute}}>
4-
<img src="{{this.rootUrl}}/pix-orga.svg" alt="{{t 'common.home-page'}}" />
4+
<img src="{{this.rootUrl}}/pix-orga.svg" class="pix-orga-logo" alt="{{t 'common.home-page'}}" />
55
</LinkTo>
6-
</header>
7-
8-
<nav class="sidebar-nav" aria-label={{t "navigation.main.aria-label"}}>
6+
</:brand>
7+
<:navElements>
98
{{#if this.shouldDisplayCampaignsEntry}}
10-
<LinkTo @route="authenticated.campaigns" class="sidebar-nav__item">
11-
<span class="sidebar-nav__item-icon">
12-
<PixIcon @name="conversionPath" role="none" />
13-
</span>
14-
{{t "navigation.main.campaigns"}}
15-
</LinkTo>
9+
<PixNavigationButton @route={{this.redirectionRoute}} @icon="conversionPath">
10+
{{t "navigation.main.campaigns"}}</PixNavigationButton>
1611
{{/if}}
17-
1812
{{#if this.shouldDisplayCertificationsEntry}}
19-
<LinkTo @route="authenticated.certifications" class="sidebar-nav__item">
20-
<span class="sidebar-nav__item-icon">
21-
<PixIcon @name="awards" role="none" />
22-
</span>
23-
{{t "navigation.main.certifications"}}
24-
</LinkTo>
13+
<PixNavigationButton @route="authenticated.certifications" @icon="awards">
14+
{{t "navigation.main.certifications"}}</PixNavigationButton>
2515
{{/if}}
2616
{{#if this.shouldDisplayAttestationsEntry}}
27-
<LinkTo @route="authenticated.attestations" class="sidebar-nav__item">
28-
<span class="sidebar-nav__item-icon">
29-
<PixIcon @name="assignment" role="none" />
30-
</span>
31-
{{t "navigation.main.attestations"}}
32-
</LinkTo>
17+
<PixNavigationButton @route="authenticated.attestations" @icon="awards">
18+
{{t "navigation.main.attestations"}}</PixNavigationButton>
3319
{{/if}}
3420
{{#if this.shouldDisplayMissionsEntry}}
35-
<LinkTo @route="authenticated.missions" class="sidebar-nav__item">
36-
<span class="sidebar-nav__item-icon">
37-
<PixIcon @name="conversionPath" role="none" />
38-
</span>
21+
<PixNavigationButton @route="authenticated.missions" @icon="conversionPath">
3922
{{t "navigation.main.missions"}}
40-
</LinkTo>
23+
</PixNavigationButton>
4124
{{/if}}
42-
<LinkTo @route={{this.organizationLearnersList.route}} class="sidebar-nav__item">
43-
<span class="sidebar-nav__item-icon">
44-
<PixIcon @name="infoUser" role="none" />
45-
</span>
25+
26+
<PixNavigationButton @route={{this.organizationLearnersList.route}} @icon="infoUser">
4627
{{t this.organizationLearnersList.label}}
47-
</LinkTo>
48-
<LinkTo @route="authenticated.team" class="sidebar-nav__item">
49-
<span class="sidebar-nav__item-icon">
50-
<PixIcon @name="users" role="none" />
51-
</span>
28+
</PixNavigationButton>
29+
30+
<PixNavigationButton @route="authenticated.team" @icon="users">
5231
{{t "navigation.main.team"}}
53-
</LinkTo>
32+
</PixNavigationButton>
33+
5434
{{#if this.shouldDisplayPlacesEntry}}
55-
<LinkTo @route="authenticated.places" class="sidebar-nav__item">
56-
<span class="sidebar-nav__item-icon">
57-
<PixIcon @name="seat" role="none" />
58-
</span>
35+
<PixNavigationButton @route="authenticated.places" @icon="seat">
5936
{{t "navigation.main.places"}}
60-
</LinkTo>
37+
</PixNavigationButton>
6138
{{/if}}
39+
6240
{{#if this.documentationUrl}}
63-
<a class="sidebar-nav__item" href={{this.documentationUrl}} target="_blank" rel="noopener noreferrer">
64-
<span class="sidebar-nav__item-icon">
65-
<PixIcon @name="book" role="none" />
66-
</span>
41+
<PixNavigationButton href={{this.documentationUrl}} @target="_blank" rel="noopener noreferrer" @icon="book">
6742
{{t "navigation.main.documentation"}}
68-
</a>
43+
</PixNavigationButton>
6944
{{/if}}
7045
{{#if this.shouldDisplayMissionsEntry}}
71-
<a
46+
<PixNavigationButton
7247
href="https://pix.fr/support/enseignement-scolaire/1er-degre"
73-
target="_blank"
74-
class="sidebar-nav__item"
48+
@target="_blank"
7549
rel="noopener noreferrer"
50+
@icon="help"
7651
>
77-
<span class="sidebar-nav__item-icon">
78-
<PixIcon @name="help" role="none" />
79-
</span>
8052
{{t "navigation.main.support"}}
81-
</a>
53+
</PixNavigationButton>
8254
{{/if}}
83-
84-
</nav>
85-
</aside>
55+
</:navElements>
56+
<:footer>
57+
<Layout::OrganizationPlacesOrCreditInfo
58+
@placesCount={{@placesCount}}
59+
@onCanShowCredit={{this.handleCanShowCredit}}
60+
/>
61+
<Layout::SchoolSessionManagement />
62+
{{#if this.shouldDisplaySeparator}}
63+
<PixNavigationSeparator />
64+
{{/if}}
65+
<Layout::UserLoggedMenu @onChangeOrganization={{@onChangeOrganization}} />
66+
</:footer>
67+
</PixNavigation>

orga/app/components/layout/sidebar.js

+11
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import { service } from '@ember/service';
22
import Component from '@glimmer/component';
3+
import { tracked } from '@glimmer/tracking';
34

45
export default class SidebarMenu extends Component {
56
@service currentUser;
67
@service url;
78

9+
@tracked canShowCredit;
10+
11+
handleCanShowCredit = (value) => {
12+
this.canShowCredit = value;
13+
};
14+
815
get redirectionRoute() {
916
if (this.shouldDisplayMissionsEntry) {
1017
return 'authenticated.missions';
@@ -37,6 +44,10 @@ export default class SidebarMenu extends Component {
3744
return this.currentUser.canAccessCampaignsPage;
3845
}
3946

47+
get shouldDisplaySeparator() {
48+
return this.shouldDisplayMissionsEntry || this.shouldDisplayPlacesEntry || this.canShowCredit;
49+
}
50+
4051
get organizationLearnersList() {
4152
if (this.currentUser.isSCOManagingStudents) {
4253
return {
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,17 @@
1-
<button
2-
type="button"
3-
{{on "click" this.toggleUserMenu}}
4-
aria-haspopup="listbox"
5-
aria-expanded="{{this.isMenuOpen}}"
6-
aria-label={{t "navigation.user-logged-menu.button"}}
7-
class="user-logged-button"
8-
...attributes
9-
>
10-
<span class="user-logged-button__text">
11-
<span>{{this.currentUser.prescriber.firstName}} {{this.currentUser.prescriber.lastName}}</span>
12-
<span>{{this.organizationNameAndExternalId}}</span>
13-
</span>
14-
<PixIcon @name={{if this.isMenuOpen "chevronTop" "chevronBottom"}} />
15-
</button>
16-
17-
<Dropdown::Content @display={{this.isMenuOpen}} @close={{this.closeMenu}} class="user-logged-menu">
18-
{{#each this.eligibleOrganizations as |organization|}}
19-
<Dropdown::Item @onClick={{fn this.onOrganizationChange organization}}>
20-
{{organization.name}}
21-
{{#if organization.externalId}}({{organization.externalId}}){{/if}}
22-
</Dropdown::Item>
23-
{{/each}}
24-
<Dropdown::ItemLink @linkTo="logout">
25-
<PixIcon @name="logout" class="user-logged-menu__icon" />
26-
{{t "navigation.user-logged-menu.logout"}}
27-
</Dropdown::ItemLink>
28-
</Dropdown::Content>
1+
<p>
2+
<strong>
3+
{{this.currentUser.prescriber.firstName}}
4+
{{this.currentUser.prescriber.lastName}}
5+
</strong>
6+
<br />
7+
{{this.organizationNameAndExternalId}}
8+
</p>
9+
{{#if this.belongsToSeveralOrganizations}}
10+
<PixStructureSwitcher
11+
@value={{this.currentUser.organization.id}}
12+
@structures={{this.eligibleOrganizations}}
13+
@label={{t "navigation.user-logged-menu.button"}}
14+
@onChange={{this.onOrganizationChange}}
15+
/>
16+
{{/if}}
17+
<PixButtonLink @variant="tertiary" class="" @route="logout">{{t "navigation.user-logged-menu.logout"}}</PixButtonLink>
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
import { action } from '@ember/object';
22
import { service } from '@ember/service';
33
import Component from '@glimmer/component';
4-
import { tracked } from '@glimmer/tracking';
54

65
export default class UserLoggedMenu extends Component {
76
@service currentUser;
87
@service router;
98
@service store;
109

11-
@tracked isMenuOpen = false;
12-
1310
get organizationNameAndExternalId() {
1411
const organization = this.currentUser.organization;
1512
if (organization.externalId) {
@@ -25,19 +22,15 @@ export default class UserLoggedMenu extends Component {
2522
}
2623
return memberships
2724
.slice()
28-
.map((membership) => membership.organization)
29-
.filter((organization) => organization.get('id') !== this.currentUser.organization.id)
30-
.sort((a, b) => a.get('name').localeCompare(b.get('name')));
31-
}
32-
33-
@action
34-
toggleUserMenu() {
35-
this.isMenuOpen = !this.isMenuOpen;
25+
.map((membership) => ({
26+
label: `${membership.organization.get('name')} (${membership.organization.get('externalId')})`,
27+
value: membership.organization.get('id'),
28+
}))
29+
.sort((a, b) => a.label.localeCompare(b.label));
3630
}
3731

38-
@action
39-
closeMenu() {
40-
this.isMenuOpen = false;
32+
get belongsToSeveralOrganizations() {
33+
return this.eligibleOrganizations.length > 1;
4134
}
4235

4336
@action
@@ -46,7 +39,7 @@ export default class UserLoggedMenu extends Component {
4639
const userOrgaSettingsId = prescriber.userOrgaSettings.get('id');
4740

4841
const userOrgaSettings = await this.store.peekRecord('user-orga-setting', userOrgaSettingsId);
49-
const selectedOrganization = await this.store.peekRecord('organization', organization.get('id'));
42+
const selectedOrganization = await this.store.peekRecord('organization', organization.value);
5043

5144
userOrgaSettings.organization = selectedOrganization;
5245
await userOrgaSettings.save({ adapterOptions: { userId: prescriber.id } });
@@ -57,7 +50,5 @@ export default class UserLoggedMenu extends Component {
5750

5851
await this.currentUser.load();
5952
this.args.onChangeOrganization();
60-
61-
this.closeMenu();
6253
}
6354
}

orga/app/styles/app.scss

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
@import 'globals/errors';
1111
@import 'globals/forms';
1212
@import 'globals/icons';
13-
@import 'globals/pages';
1413
@import 'globals/panels';
1514
@import 'globals/pix-loader';
1615
@import 'globals/tables';

orga/app/styles/components/layout/organization-places-or-credit-info.scss

+10-8
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,21 @@
22
@extend %pix-body-s;
33

44
display: flex;
5-
flex-direction: column;
6-
padding: 0 30px;
7-
color: var(--pix-neutral-900);
5+
justify-content: center;
6+
padding: 0 var(--pix-spacing-4x);
87
font-weight: var(--pix-font-bold);
98

10-
&--inline {
11-
flex-direction: row;
12-
}
13-
149
&__warning {
10+
display: flex;
11+
gap: 8px;
12+
align-items: center;
13+
justify-content: center;
14+
padding: var(--pix-spacing-1x) var(--pix-spacing-2x);
1515
color: var(--pix-error-700);
1616
font-weight: var(--pix-font-medium);
17+
font-weight: 500;
18+
background-color: rgb(var(--pix-neutral-0) / 70%);
19+
border-radius: var(--radius-xs, 4px);
1720
}
1821

1922
&__link {
@@ -28,7 +31,6 @@
2831
}
2932

3033
.warning-icon {
31-
margin: 0 var(--pix-spacing-1x);
3234
fill: var(--pix-error-700);
3335
}
3436
}

orga/app/styles/components/layout/sidebar.scss

+1
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@
6565
height: auto;
6666
}
6767
}
68+

orga/app/styles/globals/pages.scss

-15
This file was deleted.

0 commit comments

Comments
 (0)