richie-education 3.2.2-dev43 → 3.2.2-dev52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/i18n/locales/ar-SA.json +8 -4
- package/i18n/locales/es-ES.json +8 -4
- package/i18n/locales/fa-IR.json +8 -4
- package/i18n/locales/fr-CA.json +8 -4
- package/i18n/locales/fr-FR.json +10 -6
- package/i18n/locales/ko-KR.json +8 -4
- package/i18n/locales/pt-PT.json +8 -4
- package/i18n/locales/ru-RU.json +8 -4
- package/i18n/locales/vi-VN.json +8 -4
- package/js/api/auth/keycloak.spec.ts +63 -2
- package/js/api/auth/keycloak.ts +40 -2
- package/js/components/SaleTunnel/SaleTunnelInformation/SaleTunnelInformationGroup.tsx +12 -2
- package/js/components/SaleTunnel/SaleTunnelInformation/SaleTunnelInformationSingular.tsx +85 -4
- package/js/components/SaleTunnel/_styles.scss +8 -0
- package/js/components/SaleTunnel/index.spec.tsx +118 -0
- package/js/hooks/useOpenEdxProfile/index.ts +4 -2
- package/js/index.tsx +1 -1
- package/js/translations/ar-SA.json +1 -1
- package/js/translations/es-ES.json +1 -1
- package/js/translations/fa-IR.json +1 -1
- package/js/translations/fr-CA.json +1 -1
- package/js/translations/fr-FR.json +1 -1
- package/js/translations/ko-KR.json +1 -1
- package/js/translations/pt-PT.json +1 -1
- package/js/translations/ru-RU.json +1 -1
- package/js/translations/vi-VN.json +1 -1
- package/js/types/api.ts +14 -5
- package/js/types/keycloak.ts +8 -0
- package/js/widgets/Dashboard/components/DashboardItem/BatchOrder/index.tsx +17 -6
- package/js/widgets/index.tsx +3 -2
- package/package.json +1 -1
- package/scss/colors/_theme.scss +1 -0
package/i18n/locales/ar-SA.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/es-ES.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/fa-IR.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/fr-CA.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/fr-FR.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Places"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {place} other {places}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assignée"
|
|
@@ -241,7 +245,7 @@
|
|
|
241
245
|
},
|
|
242
246
|
"batchOrder.title.company": {
|
|
243
247
|
"description": "Step label for company information in the batch order form",
|
|
244
|
-
"message": "
|
|
248
|
+
"message": "Organisme"
|
|
245
249
|
},
|
|
246
250
|
"batchOrder.title.financing": {
|
|
247
251
|
"description": "Step label for financing/payment in the batch order form",
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Envoyer la convention pour signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assignée"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Complétée"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Brouillon"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Paiement échoué"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "En attente"
|
|
1621
1625
|
},
|
|
@@ -1793,7 +1797,7 @@
|
|
|
1793
1797
|
},
|
|
1794
1798
|
"components.SaleTunnel.BatchOrderForm.stepCompany": {
|
|
1795
1799
|
"description": "Step label for company information in the batch order form",
|
|
1796
|
-
"message": "
|
|
1800
|
+
"message": "Organisme"
|
|
1797
1801
|
},
|
|
1798
1802
|
"components.SaleTunnel.BatchOrderForm.stepCompanyTitle": {
|
|
1799
1803
|
"description": "Title of the section with company/organization details",
|
package/i18n/locales/ko-KR.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/pt-PT.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/ru-RU.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
package/i18n/locales/vi-VN.json
CHANGED
|
@@ -195,6 +195,10 @@
|
|
|
195
195
|
"description": "Text displayed for seats value in batch order",
|
|
196
196
|
"message": "Seats"
|
|
197
197
|
},
|
|
198
|
+
"batchOrder.seatsCount": {
|
|
199
|
+
"description": "Text displayed for seats count with pluralization in batch order",
|
|
200
|
+
"message": "{seats} {seats, plural, one {seat} other {seats}}"
|
|
201
|
+
},
|
|
198
202
|
"batchOrder.status.assigned": {
|
|
199
203
|
"description": "Status label for an assigned batch order",
|
|
200
204
|
"message": "Assigned"
|
|
@@ -1595,7 +1599,7 @@
|
|
|
1595
1599
|
"description": "Action label to send a contract for signature",
|
|
1596
1600
|
"message": "Send contract for signature"
|
|
1597
1601
|
},
|
|
1598
|
-
"components.OrganizationQuotesTable.state.assigned
|
|
1602
|
+
"components.OrganizationQuotesTable.state.assigned": {
|
|
1599
1603
|
"description": "Batch order state: assigned",
|
|
1600
1604
|
"message": "Assigned"
|
|
1601
1605
|
},
|
|
@@ -1607,15 +1611,15 @@
|
|
|
1607
1611
|
"description": "Batch order state: completed",
|
|
1608
1612
|
"message": "Completed"
|
|
1609
1613
|
},
|
|
1610
|
-
"components.OrganizationQuotesTable.state.draft
|
|
1614
|
+
"components.OrganizationQuotesTable.state.draft": {
|
|
1611
1615
|
"description": "Batch order state: draft",
|
|
1612
1616
|
"message": "Draft"
|
|
1613
1617
|
},
|
|
1614
|
-
"components.OrganizationQuotesTable.state.failedPayment
|
|
1618
|
+
"components.OrganizationQuotesTable.state.failedPayment": {
|
|
1615
1619
|
"description": "Batch order state: failed payment",
|
|
1616
1620
|
"message": "Failed payment"
|
|
1617
1621
|
},
|
|
1618
|
-
"components.OrganizationQuotesTable.state.pending
|
|
1622
|
+
"components.OrganizationQuotesTable.state.pending": {
|
|
1619
1623
|
"description": "Batch order state: pending",
|
|
1620
1624
|
"message": "Pending"
|
|
1621
1625
|
},
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import { RichieContextFactory as mockRichieContextFactory } from 'utils/test/factories/richie';
|
|
2
|
+
import { KeycloakAccountApi } from 'types/api';
|
|
2
3
|
import API from './keycloak';
|
|
3
4
|
|
|
4
5
|
const mockKeycloakInit = jest.fn().mockResolvedValue(true);
|
|
5
6
|
const mockKeycloakLogout = jest.fn().mockResolvedValue(undefined);
|
|
6
7
|
const mockKeycloakLogin = jest.fn().mockResolvedValue(undefined);
|
|
7
8
|
const mockKeycloakLoadUserProfile = jest.fn();
|
|
9
|
+
const mockKeycloakUpdateToken = jest.fn().mockResolvedValue(true);
|
|
10
|
+
const mockKeycloakCreateAccountUrl = jest
|
|
11
|
+
.fn()
|
|
12
|
+
.mockReturnValue('https://keycloak.test/auth/realms/richie-realm/account');
|
|
13
|
+
const mockIdToken = 'mock-id-token-12345';
|
|
14
|
+
const mockIdTokenParsed = {
|
|
15
|
+
preferred_username: 'johndoe',
|
|
16
|
+
firstName: 'John',
|
|
17
|
+
lastName: 'Doe',
|
|
18
|
+
email: 'johndoe@example.com',
|
|
19
|
+
};
|
|
8
20
|
|
|
9
21
|
jest.mock('keycloak-js', () => {
|
|
10
22
|
return jest.fn().mockImplementation(() => ({
|
|
@@ -12,6 +24,10 @@ jest.mock('keycloak-js', () => {
|
|
|
12
24
|
logout: mockKeycloakLogout,
|
|
13
25
|
login: mockKeycloakLogin,
|
|
14
26
|
loadUserProfile: mockKeycloakLoadUserProfile,
|
|
27
|
+
updateToken: mockKeycloakUpdateToken,
|
|
28
|
+
createAccountUrl: mockKeycloakCreateAccountUrl,
|
|
29
|
+
idToken: mockIdToken,
|
|
30
|
+
idTokenParsed: mockIdTokenParsed,
|
|
15
31
|
}));
|
|
16
32
|
});
|
|
17
33
|
|
|
@@ -50,17 +66,40 @@ describe('Keycloak API', () => {
|
|
|
50
66
|
|
|
51
67
|
beforeEach(() => {
|
|
52
68
|
jest.clearAllMocks();
|
|
69
|
+
sessionStorage.clear();
|
|
53
70
|
keycloakApi = API(authConfig);
|
|
54
71
|
});
|
|
55
72
|
|
|
73
|
+
describe('user.accessToken', () => {
|
|
74
|
+
it('returns null when no token is stored', () => {
|
|
75
|
+
const token = keycloakApi.user.accessToken!();
|
|
76
|
+
expect(token).toBeNull();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('returns the token from sessionStorage', () => {
|
|
80
|
+
sessionStorage.setItem('RICHIE_USER_TOKEN', mockIdToken);
|
|
81
|
+
const token = keycloakApi.user.accessToken!();
|
|
82
|
+
expect(token).toEqual(mockIdToken);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
56
86
|
describe('user.me', () => {
|
|
87
|
+
it('returns null when updateToken fails', async () => {
|
|
88
|
+
mockKeycloakUpdateToken.mockRejectedValueOnce(new Error('Token refresh failed'));
|
|
89
|
+
const response = await keycloakApi.user.me();
|
|
90
|
+
expect(response).toBeNull();
|
|
91
|
+
expect(mockKeycloakLoadUserProfile).not.toHaveBeenCalled();
|
|
92
|
+
});
|
|
93
|
+
|
|
57
94
|
it('returns null when loadUserProfile fails', async () => {
|
|
95
|
+
mockKeycloakUpdateToken.mockResolvedValueOnce(true);
|
|
58
96
|
mockKeycloakLoadUserProfile.mockRejectedValueOnce(new Error('Not authenticated'));
|
|
59
97
|
const response = await keycloakApi.user.me();
|
|
60
98
|
expect(response).toBeNull();
|
|
61
99
|
});
|
|
62
100
|
|
|
63
101
|
it('returns user when loadUserProfile succeeds', async () => {
|
|
102
|
+
mockKeycloakUpdateToken.mockResolvedValueOnce(true);
|
|
64
103
|
mockKeycloakLoadUserProfile.mockResolvedValueOnce({
|
|
65
104
|
firstName: 'John',
|
|
66
105
|
lastName: 'Doe',
|
|
@@ -68,10 +107,13 @@ describe('Keycloak API', () => {
|
|
|
68
107
|
});
|
|
69
108
|
|
|
70
109
|
const response = await keycloakApi.user.me();
|
|
110
|
+
expect(mockKeycloakUpdateToken).toHaveBeenCalledWith(30);
|
|
71
111
|
expect(response).toEqual({
|
|
72
112
|
username: 'John Doe',
|
|
73
113
|
email: 'johndoe@example.com',
|
|
114
|
+
access_token: mockIdToken,
|
|
74
115
|
});
|
|
116
|
+
expect(sessionStorage.getItem('RICHIE_USER_TOKEN')).toEqual(mockIdToken);
|
|
75
117
|
});
|
|
76
118
|
});
|
|
77
119
|
|
|
@@ -106,6 +148,24 @@ describe('Keycloak API', () => {
|
|
|
106
148
|
});
|
|
107
149
|
});
|
|
108
150
|
|
|
151
|
+
describe('user.account', () => {
|
|
152
|
+
it('returns profile data from idTokenParsed via account.get()', () => {
|
|
153
|
+
const profile = (keycloakApi.user.account as KeycloakAccountApi).get();
|
|
154
|
+
expect(profile).toEqual({
|
|
155
|
+
username: 'johndoe',
|
|
156
|
+
firstName: 'John',
|
|
157
|
+
lastName: 'Doe',
|
|
158
|
+
email: 'johndoe@example.com',
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('returns the account management URL via account.updateUrl()', () => {
|
|
163
|
+
const url = (keycloakApi.user.account as any).updateUrl();
|
|
164
|
+
expect(url).toBe('https://keycloak.test/auth/realms/richie-realm/account');
|
|
165
|
+
expect(mockKeycloakCreateAccountUrl).toHaveBeenCalled();
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
109
169
|
describe('Keycloak initialization', () => {
|
|
110
170
|
it('initializes keycloak with correct configuration', () => {
|
|
111
171
|
const Keycloak = require('keycloak-js');
|
|
@@ -118,8 +178,9 @@ describe('Keycloak API', () => {
|
|
|
118
178
|
|
|
119
179
|
expect(mockKeycloakInit).toHaveBeenCalledWith({
|
|
120
180
|
checkLoginIframe: false,
|
|
121
|
-
flow: '
|
|
122
|
-
|
|
181
|
+
flow: 'standard',
|
|
182
|
+
onLoad: 'check-sso',
|
|
183
|
+
pkceMethod: 'S256',
|
|
123
184
|
});
|
|
124
185
|
});
|
|
125
186
|
});
|
package/js/api/auth/keycloak.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import Keycloak from 'keycloak-js';
|
|
2
2
|
import { AuthenticationBackend } from 'types/commonDataProps';
|
|
3
3
|
import { APIAuthentication } from 'types/api';
|
|
4
|
+
import { KeycloakApiProfile } from 'types/keycloak';
|
|
4
5
|
import { location } from 'utils/indirection/window';
|
|
5
6
|
import { handle } from 'utils/errors/handle';
|
|
7
|
+
import { RICHIE_USER_TOKEN } from 'settings';
|
|
6
8
|
|
|
7
9
|
const API = (APIConf: AuthenticationBackend): { user: APIAuthentication } => {
|
|
8
10
|
const keycloak = new Keycloak({
|
|
@@ -12,23 +14,46 @@ const API = (APIConf: AuthenticationBackend): { user: APIAuthentication } => {
|
|
|
12
14
|
});
|
|
13
15
|
keycloak.init({
|
|
14
16
|
checkLoginIframe: false,
|
|
15
|
-
flow: '
|
|
16
|
-
|
|
17
|
+
flow: 'standard',
|
|
18
|
+
onLoad: 'check-sso',
|
|
19
|
+
pkceMethod: 'S256',
|
|
17
20
|
});
|
|
18
21
|
|
|
22
|
+
keycloak.onTokenExpired = () => {
|
|
23
|
+
keycloak.updateToken(30).catch(() => {
|
|
24
|
+
sessionStorage.removeItem(RICHIE_USER_TOKEN);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
keycloak.onAuthRefreshSuccess = () => {
|
|
29
|
+
if (keycloak.idToken) {
|
|
30
|
+
sessionStorage.setItem(RICHIE_USER_TOKEN, keycloak.idToken);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
19
34
|
const getRedirectUri = () => {
|
|
20
35
|
return `${location.origin}${location.pathname}`;
|
|
21
36
|
};
|
|
22
37
|
|
|
23
38
|
return {
|
|
24
39
|
user: {
|
|
40
|
+
accessToken: () => sessionStorage.getItem(RICHIE_USER_TOKEN),
|
|
25
41
|
me: async () => {
|
|
42
|
+
try {
|
|
43
|
+
await keycloak.updateToken(30);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
handle(error);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
26
49
|
return keycloak
|
|
27
50
|
.loadUserProfile()
|
|
28
51
|
.then((userProfile) => {
|
|
52
|
+
sessionStorage.setItem(RICHIE_USER_TOKEN, keycloak.idToken!);
|
|
29
53
|
return {
|
|
30
54
|
username: `${userProfile.firstName} ${userProfile.lastName}`,
|
|
31
55
|
email: userProfile.email,
|
|
56
|
+
access_token: keycloak.idToken,
|
|
32
57
|
};
|
|
33
58
|
})
|
|
34
59
|
.catch((error) => {
|
|
@@ -46,8 +71,21 @@ const API = (APIConf: AuthenticationBackend): { user: APIAuthentication } => {
|
|
|
46
71
|
},
|
|
47
72
|
|
|
48
73
|
logout: async () => {
|
|
74
|
+
sessionStorage.removeItem(RICHIE_USER_TOKEN);
|
|
49
75
|
await keycloak.logout({ redirectUri: getRedirectUri() });
|
|
50
76
|
},
|
|
77
|
+
|
|
78
|
+
account: {
|
|
79
|
+
get: (): KeycloakApiProfile => {
|
|
80
|
+
return {
|
|
81
|
+
username: keycloak.idTokenParsed?.preferred_username,
|
|
82
|
+
firstName: keycloak.idTokenParsed?.firstName,
|
|
83
|
+
lastName: keycloak.idTokenParsed?.lastName,
|
|
84
|
+
email: keycloak.idTokenParsed?.email,
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
updateUrl: () => keycloak.createAccountUrl(),
|
|
88
|
+
},
|
|
51
89
|
},
|
|
52
90
|
};
|
|
53
91
|
};
|
|
@@ -68,6 +68,16 @@ const messages = defineMessages({
|
|
|
68
68
|
description: 'Step label for financing/payment in the batch order form',
|
|
69
69
|
defaultMessage: 'Financing',
|
|
70
70
|
},
|
|
71
|
+
previousButton: {
|
|
72
|
+
id: 'components.SaleTunnel.BatchOrderForm.previousButton',
|
|
73
|
+
description: 'Label for the button to go back to the previous step in the batch order form',
|
|
74
|
+
defaultMessage: 'Previous',
|
|
75
|
+
},
|
|
76
|
+
nextButton: {
|
|
77
|
+
id: 'components.SaleTunnel.BatchOrderForm.nextButton',
|
|
78
|
+
description: 'Label for the button to proceed to the next step in the batch order form',
|
|
79
|
+
defaultMessage: 'Next',
|
|
80
|
+
},
|
|
71
81
|
});
|
|
72
82
|
|
|
73
83
|
export const SaleTunnelInformationGroup = () => {
|
|
@@ -258,7 +268,7 @@ const BatchOrderForm = () => {
|
|
|
258
268
|
hidden={activeStep === 0}
|
|
259
269
|
color="secondary"
|
|
260
270
|
>
|
|
261
|
-
|
|
271
|
+
<FormattedMessage {...messages.previousButton} />
|
|
262
272
|
</Button>
|
|
263
273
|
<Button
|
|
264
274
|
onClick={() => {
|
|
@@ -269,7 +279,7 @@ const BatchOrderForm = () => {
|
|
|
269
279
|
disabled={!isCurrentStepValid}
|
|
270
280
|
hidden={activeStep === steps.length - 1}
|
|
271
281
|
>
|
|
272
|
-
|
|
282
|
+
<FormattedMessage {...messages.nextButton} />
|
|
273
283
|
</Button>
|
|
274
284
|
</div>
|
|
275
285
|
</FormProvider>
|