richie-education 3.4.1-dev14 → 3.4.1-dev18
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 +58 -6
- package/i18n/locales/es-ES.json +58 -6
- package/i18n/locales/fa-IR.json +58 -6
- package/i18n/locales/fr-CA.json +58 -6
- package/i18n/locales/fr-FR.json +55 -3
- package/i18n/locales/ko-KR.json +58 -6
- package/i18n/locales/pt-PT.json +58 -6
- package/i18n/locales/ru-RU.json +58 -6
- package/i18n/locales/vi-VN.json +58 -6
- package/js/api/joanie.ts +10 -4
- package/js/components/DownloadBatchOrderSeatsButton/index.tsx +36 -19
- package/js/components/Icon/index.tsx +1 -0
- package/js/components/SaleTunnel/_styles.scss +4 -1
- package/js/hooks/useDownloadBatchOrderSeats/index.spec.tsx +28 -0
- package/js/hooks/useDownloadBatchOrderSeats/index.tsx +15 -5
- 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/utils/errors/HttpError.ts +1 -0
- package/js/widgets/Dashboard/components/DashboardItem/BatchOrder/BatchOrderSeatInfo.tsx +22 -18
- package/js/widgets/Slider/components/SlidePanel.tsx +13 -1
- package/js/widgets/Slider/index.spec.tsx +3 -5
- package/package.json +1 -1
- package/scss/components/templates/richie/slider/_slider.scss +10 -0
- package/scss/objects/_dashboard.scss +8 -1
package/i18n/locales/pt-PT.json
CHANGED
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
"description": "Label for the field asking the company address",
|
|
28
28
|
"message": "Endereço"
|
|
29
29
|
},
|
|
30
|
+
"batchOrder.agreement.organizationSignedOn": {
|
|
31
|
+
"description": "Label displayed once the organization has counter-signed the agreement",
|
|
32
|
+
"message": "Signed by the organization on {date}."
|
|
33
|
+
},
|
|
34
|
+
"batchOrder.agreement.title": {
|
|
35
|
+
"description": "Step label for the agreement document in the batch order detail",
|
|
36
|
+
"message": "Agreement"
|
|
37
|
+
},
|
|
38
|
+
"batchOrder.agreement.waitingOrganization": {
|
|
39
|
+
"description": "Label displayed when the agreement is waiting for the organization counter-signature",
|
|
40
|
+
"message": "Waiting for the organization to counter-sign the agreement."
|
|
41
|
+
},
|
|
30
42
|
"batchOrder.bankTransfer": {
|
|
31
43
|
"description": "Option label for selecting bank transfer payment",
|
|
32
44
|
"message": "Transferência bancária"
|
|
@@ -59,6 +71,26 @@
|
|
|
59
71
|
"description": "Label for the field asking the email address of the contact person",
|
|
60
72
|
"message": "E-mail"
|
|
61
73
|
},
|
|
74
|
+
"batchOrder.enrollmentManagement.enrolledParticipants": {
|
|
75
|
+
"description": "Progress label showing enrolled participants out of total seats",
|
|
76
|
+
"message": "{seats_owned}/{nb_seats} enrolled participants"
|
|
77
|
+
},
|
|
78
|
+
"batchOrder.enrollmentManagement.loadMore": {
|
|
79
|
+
"description": "Button to load more seats",
|
|
80
|
+
"message": "Load {count} more"
|
|
81
|
+
},
|
|
82
|
+
"batchOrder.enrollmentManagement.noResults": {
|
|
83
|
+
"description": "Message shown when the student search returns no results",
|
|
84
|
+
"message": "No student matches your search."
|
|
85
|
+
},
|
|
86
|
+
"batchOrder.enrollmentManagement.searchPlaceholder": {
|
|
87
|
+
"description": "Placeholder for the seat search input (student name or voucher)",
|
|
88
|
+
"message": "Student name"
|
|
89
|
+
},
|
|
90
|
+
"batchOrder.enrollmentManagement.title": {
|
|
91
|
+
"description": "Title for enrollment management section",
|
|
92
|
+
"message": "Enrollment"
|
|
93
|
+
},
|
|
62
94
|
"batchOrder.firstName": {
|
|
63
95
|
"description": "Label for the field asking the first name of the contact person",
|
|
64
96
|
"message": "Nome próprio"
|
|
@@ -197,11 +229,11 @@
|
|
|
197
229
|
},
|
|
198
230
|
"batchOrder.seats": {
|
|
199
231
|
"description": "Text displayed for seats value in batch order",
|
|
200
|
-
"message": "
|
|
232
|
+
"message": "{nb_seats} seats"
|
|
201
233
|
},
|
|
202
234
|
"batchOrder.seatsCount": {
|
|
203
|
-
"description": "Text displayed for seats count
|
|
204
|
-
"message": "{
|
|
235
|
+
"description": "Text displayed for seats count in batch order (owned / total)",
|
|
236
|
+
"message": "{seats_owned}/{nb_seats} seats"
|
|
205
237
|
},
|
|
206
238
|
"batchOrder.status.assigned": {
|
|
207
239
|
"description": "Status label for an assigned batch order",
|
|
@@ -1371,6 +1403,26 @@
|
|
|
1371
1403
|
"description": "Accessible label for user menu button",
|
|
1372
1404
|
"message": "Acesso às suas configurações de perfil"
|
|
1373
1405
|
},
|
|
1406
|
+
"components.DownloadAgreementButton.download": {
|
|
1407
|
+
"description": "Label for the button to download a signed agreement PDF",
|
|
1408
|
+
"message": "Download agreement"
|
|
1409
|
+
},
|
|
1410
|
+
"components.DownloadAgreementButton.generating": {
|
|
1411
|
+
"description": "Accessible label displayed while agreement PDF is being downloaded.",
|
|
1412
|
+
"message": "Downloading..."
|
|
1413
|
+
},
|
|
1414
|
+
"components.DownloadBatchOrderSeatsButton.download": {
|
|
1415
|
+
"description": "Label for the button to export batch order seats as CSV",
|
|
1416
|
+
"message": "Export CSV"
|
|
1417
|
+
},
|
|
1418
|
+
"components.DownloadBatchOrderSeatsButton.generating": {
|
|
1419
|
+
"description": "Accessible label displayed while CSV export is being generated.",
|
|
1420
|
+
"message": "Generating export..."
|
|
1421
|
+
},
|
|
1422
|
+
"components.DownloadBatchOrderSeatsButton.noSeatsOwned": {
|
|
1423
|
+
"description": "Error message displayed when trying to export seats but no seats are owned yet.",
|
|
1424
|
+
"message": "No participants have claimed their seat yet. The export will be available once at least one participant has enrolled."
|
|
1425
|
+
},
|
|
1374
1426
|
"components.DownloadCertificateButton.download": {
|
|
1375
1427
|
"description": "Label for the download button of a certificate",
|
|
1376
1428
|
"message": "Descarregar"
|
|
@@ -2137,7 +2189,7 @@
|
|
|
2137
2189
|
},
|
|
2138
2190
|
"components.SaleTunnelSuccess.successDetailMessage": {
|
|
2139
2191
|
"description": "Text to explain when the user will be able to start its training.",
|
|
2140
|
-
"message": "
|
|
2192
|
+
"message": "You’ll be able to start your training once the first installment has been paid, or once access opens if no payment is required."
|
|
2141
2193
|
},
|
|
2142
2194
|
"components.SaleTunnelSuccess.successMessage": {
|
|
2143
2195
|
"description": "Message to confirm that order has been created",
|
|
@@ -2457,7 +2509,7 @@
|
|
|
2457
2509
|
},
|
|
2458
2510
|
"components.TeacherDashboard.TeacherDashboardRoutes.course.product.learnerList.label": {
|
|
2459
2511
|
"description": "Label to display the product's learner list view.",
|
|
2460
|
-
"message": "
|
|
2512
|
+
"message": "Buyers"
|
|
2461
2513
|
},
|
|
2462
2514
|
"components.TeacherDashboard.TeacherDashboardRoutes.generalInformation.label": {
|
|
2463
2515
|
"description": "Label of the course general information view.",
|
|
@@ -2489,7 +2541,7 @@
|
|
|
2489
2541
|
},
|
|
2490
2542
|
"components.TeacherDashboard.TeacherDashboardRoutes.organization.course.product.learnerList.label": {
|
|
2491
2543
|
"description": "Label to display the organization product's learner list view.",
|
|
2492
|
-
"message": "
|
|
2544
|
+
"message": "Buyers"
|
|
2493
2545
|
},
|
|
2494
2546
|
"components.TeacherDashboard.TeacherDashboardRoutes.organization.courses.label": {
|
|
2495
2547
|
"description": "Label of the organization courses view.",
|
package/i18n/locales/ru-RU.json
CHANGED
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
"description": "Label for the field asking the company address",
|
|
28
28
|
"message": "Address"
|
|
29
29
|
},
|
|
30
|
+
"batchOrder.agreement.organizationSignedOn": {
|
|
31
|
+
"description": "Label displayed once the organization has counter-signed the agreement",
|
|
32
|
+
"message": "Signed by the organization on {date}."
|
|
33
|
+
},
|
|
34
|
+
"batchOrder.agreement.title": {
|
|
35
|
+
"description": "Step label for the agreement document in the batch order detail",
|
|
36
|
+
"message": "Agreement"
|
|
37
|
+
},
|
|
38
|
+
"batchOrder.agreement.waitingOrganization": {
|
|
39
|
+
"description": "Label displayed when the agreement is waiting for the organization counter-signature",
|
|
40
|
+
"message": "Waiting for the organization to counter-sign the agreement."
|
|
41
|
+
},
|
|
30
42
|
"batchOrder.bankTransfer": {
|
|
31
43
|
"description": "Option label for selecting bank transfer payment",
|
|
32
44
|
"message": "Bank transfer"
|
|
@@ -59,6 +71,26 @@
|
|
|
59
71
|
"description": "Label for the field asking the email address of the contact person",
|
|
60
72
|
"message": "Email"
|
|
61
73
|
},
|
|
74
|
+
"batchOrder.enrollmentManagement.enrolledParticipants": {
|
|
75
|
+
"description": "Progress label showing enrolled participants out of total seats",
|
|
76
|
+
"message": "{seats_owned}/{nb_seats} enrolled participants"
|
|
77
|
+
},
|
|
78
|
+
"batchOrder.enrollmentManagement.loadMore": {
|
|
79
|
+
"description": "Button to load more seats",
|
|
80
|
+
"message": "Load {count} more"
|
|
81
|
+
},
|
|
82
|
+
"batchOrder.enrollmentManagement.noResults": {
|
|
83
|
+
"description": "Message shown when the student search returns no results",
|
|
84
|
+
"message": "No student matches your search."
|
|
85
|
+
},
|
|
86
|
+
"batchOrder.enrollmentManagement.searchPlaceholder": {
|
|
87
|
+
"description": "Placeholder for the seat search input (student name or voucher)",
|
|
88
|
+
"message": "Student name"
|
|
89
|
+
},
|
|
90
|
+
"batchOrder.enrollmentManagement.title": {
|
|
91
|
+
"description": "Title for enrollment management section",
|
|
92
|
+
"message": "Enrollment"
|
|
93
|
+
},
|
|
62
94
|
"batchOrder.firstName": {
|
|
63
95
|
"description": "Label for the field asking the first name of the contact person",
|
|
64
96
|
"message": "First name"
|
|
@@ -197,11 +229,11 @@
|
|
|
197
229
|
},
|
|
198
230
|
"batchOrder.seats": {
|
|
199
231
|
"description": "Text displayed for seats value in batch order",
|
|
200
|
-
"message": "
|
|
232
|
+
"message": "{nb_seats} seats"
|
|
201
233
|
},
|
|
202
234
|
"batchOrder.seatsCount": {
|
|
203
|
-
"description": "Text displayed for seats count
|
|
204
|
-
"message": "{
|
|
235
|
+
"description": "Text displayed for seats count in batch order (owned / total)",
|
|
236
|
+
"message": "{seats_owned}/{nb_seats} seats"
|
|
205
237
|
},
|
|
206
238
|
"batchOrder.status.assigned": {
|
|
207
239
|
"description": "Status label for an assigned batch order",
|
|
@@ -1371,6 +1403,26 @@
|
|
|
1371
1403
|
"description": "Accessible label for user menu button",
|
|
1372
1404
|
"message": "Доступ к настройкам вашего профиля"
|
|
1373
1405
|
},
|
|
1406
|
+
"components.DownloadAgreementButton.download": {
|
|
1407
|
+
"description": "Label for the button to download a signed agreement PDF",
|
|
1408
|
+
"message": "Download agreement"
|
|
1409
|
+
},
|
|
1410
|
+
"components.DownloadAgreementButton.generating": {
|
|
1411
|
+
"description": "Accessible label displayed while agreement PDF is being downloaded.",
|
|
1412
|
+
"message": "Downloading..."
|
|
1413
|
+
},
|
|
1414
|
+
"components.DownloadBatchOrderSeatsButton.download": {
|
|
1415
|
+
"description": "Label for the button to export batch order seats as CSV",
|
|
1416
|
+
"message": "Export CSV"
|
|
1417
|
+
},
|
|
1418
|
+
"components.DownloadBatchOrderSeatsButton.generating": {
|
|
1419
|
+
"description": "Accessible label displayed while CSV export is being generated.",
|
|
1420
|
+
"message": "Generating export..."
|
|
1421
|
+
},
|
|
1422
|
+
"components.DownloadBatchOrderSeatsButton.noSeatsOwned": {
|
|
1423
|
+
"description": "Error message displayed when trying to export seats but no seats are owned yet.",
|
|
1424
|
+
"message": "No participants have claimed their seat yet. The export will be available once at least one participant has enrolled."
|
|
1425
|
+
},
|
|
1374
1426
|
"components.DownloadCertificateButton.download": {
|
|
1375
1427
|
"description": "Label for the download button of a certificate",
|
|
1376
1428
|
"message": "Download"
|
|
@@ -2137,7 +2189,7 @@
|
|
|
2137
2189
|
},
|
|
2138
2190
|
"components.SaleTunnelSuccess.successDetailMessage": {
|
|
2139
2191
|
"description": "Text to explain when the user will be able to start its training.",
|
|
2140
|
-
"message": "You
|
|
2192
|
+
"message": "You’ll be able to start your training once the first installment has been paid, or once access opens if no payment is required."
|
|
2141
2193
|
},
|
|
2142
2194
|
"components.SaleTunnelSuccess.successMessage": {
|
|
2143
2195
|
"description": "Message to confirm that order has been created",
|
|
@@ -2457,7 +2509,7 @@
|
|
|
2457
2509
|
},
|
|
2458
2510
|
"components.TeacherDashboard.TeacherDashboardRoutes.course.product.learnerList.label": {
|
|
2459
2511
|
"description": "Label to display the product's learner list view.",
|
|
2460
|
-
"message": "
|
|
2512
|
+
"message": "Buyers"
|
|
2461
2513
|
},
|
|
2462
2514
|
"components.TeacherDashboard.TeacherDashboardRoutes.generalInformation.label": {
|
|
2463
2515
|
"description": "Label of the course general information view.",
|
|
@@ -2489,7 +2541,7 @@
|
|
|
2489
2541
|
},
|
|
2490
2542
|
"components.TeacherDashboard.TeacherDashboardRoutes.organization.course.product.learnerList.label": {
|
|
2491
2543
|
"description": "Label to display the organization product's learner list view.",
|
|
2492
|
-
"message": "
|
|
2544
|
+
"message": "Buyers"
|
|
2493
2545
|
},
|
|
2494
2546
|
"components.TeacherDashboard.TeacherDashboardRoutes.organization.courses.label": {
|
|
2495
2547
|
"description": "Label of the organization courses view.",
|
package/i18n/locales/vi-VN.json
CHANGED
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
"description": "Label for the field asking the company address",
|
|
28
28
|
"message": "Address"
|
|
29
29
|
},
|
|
30
|
+
"batchOrder.agreement.organizationSignedOn": {
|
|
31
|
+
"description": "Label displayed once the organization has counter-signed the agreement",
|
|
32
|
+
"message": "Signed by the organization on {date}."
|
|
33
|
+
},
|
|
34
|
+
"batchOrder.agreement.title": {
|
|
35
|
+
"description": "Step label for the agreement document in the batch order detail",
|
|
36
|
+
"message": "Agreement"
|
|
37
|
+
},
|
|
38
|
+
"batchOrder.agreement.waitingOrganization": {
|
|
39
|
+
"description": "Label displayed when the agreement is waiting for the organization counter-signature",
|
|
40
|
+
"message": "Waiting for the organization to counter-sign the agreement."
|
|
41
|
+
},
|
|
30
42
|
"batchOrder.bankTransfer": {
|
|
31
43
|
"description": "Option label for selecting bank transfer payment",
|
|
32
44
|
"message": "Bank transfer"
|
|
@@ -59,6 +71,26 @@
|
|
|
59
71
|
"description": "Label for the field asking the email address of the contact person",
|
|
60
72
|
"message": "Email"
|
|
61
73
|
},
|
|
74
|
+
"batchOrder.enrollmentManagement.enrolledParticipants": {
|
|
75
|
+
"description": "Progress label showing enrolled participants out of total seats",
|
|
76
|
+
"message": "{seats_owned}/{nb_seats} enrolled participants"
|
|
77
|
+
},
|
|
78
|
+
"batchOrder.enrollmentManagement.loadMore": {
|
|
79
|
+
"description": "Button to load more seats",
|
|
80
|
+
"message": "Load {count} more"
|
|
81
|
+
},
|
|
82
|
+
"batchOrder.enrollmentManagement.noResults": {
|
|
83
|
+
"description": "Message shown when the student search returns no results",
|
|
84
|
+
"message": "No student matches your search."
|
|
85
|
+
},
|
|
86
|
+
"batchOrder.enrollmentManagement.searchPlaceholder": {
|
|
87
|
+
"description": "Placeholder for the seat search input (student name or voucher)",
|
|
88
|
+
"message": "Student name"
|
|
89
|
+
},
|
|
90
|
+
"batchOrder.enrollmentManagement.title": {
|
|
91
|
+
"description": "Title for enrollment management section",
|
|
92
|
+
"message": "Enrollment"
|
|
93
|
+
},
|
|
62
94
|
"batchOrder.firstName": {
|
|
63
95
|
"description": "Label for the field asking the first name of the contact person",
|
|
64
96
|
"message": "First name"
|
|
@@ -197,11 +229,11 @@
|
|
|
197
229
|
},
|
|
198
230
|
"batchOrder.seats": {
|
|
199
231
|
"description": "Text displayed for seats value in batch order",
|
|
200
|
-
"message": "
|
|
232
|
+
"message": "{nb_seats} seats"
|
|
201
233
|
},
|
|
202
234
|
"batchOrder.seatsCount": {
|
|
203
|
-
"description": "Text displayed for seats count
|
|
204
|
-
"message": "{
|
|
235
|
+
"description": "Text displayed for seats count in batch order (owned / total)",
|
|
236
|
+
"message": "{seats_owned}/{nb_seats} seats"
|
|
205
237
|
},
|
|
206
238
|
"batchOrder.status.assigned": {
|
|
207
239
|
"description": "Status label for an assigned batch order",
|
|
@@ -1371,6 +1403,26 @@
|
|
|
1371
1403
|
"description": "Accessible label for user menu button",
|
|
1372
1404
|
"message": "Access to your profile settings"
|
|
1373
1405
|
},
|
|
1406
|
+
"components.DownloadAgreementButton.download": {
|
|
1407
|
+
"description": "Label for the button to download a signed agreement PDF",
|
|
1408
|
+
"message": "Download agreement"
|
|
1409
|
+
},
|
|
1410
|
+
"components.DownloadAgreementButton.generating": {
|
|
1411
|
+
"description": "Accessible label displayed while agreement PDF is being downloaded.",
|
|
1412
|
+
"message": "Downloading..."
|
|
1413
|
+
},
|
|
1414
|
+
"components.DownloadBatchOrderSeatsButton.download": {
|
|
1415
|
+
"description": "Label for the button to export batch order seats as CSV",
|
|
1416
|
+
"message": "Export CSV"
|
|
1417
|
+
},
|
|
1418
|
+
"components.DownloadBatchOrderSeatsButton.generating": {
|
|
1419
|
+
"description": "Accessible label displayed while CSV export is being generated.",
|
|
1420
|
+
"message": "Generating export..."
|
|
1421
|
+
},
|
|
1422
|
+
"components.DownloadBatchOrderSeatsButton.noSeatsOwned": {
|
|
1423
|
+
"description": "Error message displayed when trying to export seats but no seats are owned yet.",
|
|
1424
|
+
"message": "No participants have claimed their seat yet. The export will be available once at least one participant has enrolled."
|
|
1425
|
+
},
|
|
1374
1426
|
"components.DownloadCertificateButton.download": {
|
|
1375
1427
|
"description": "Label for the download button of a certificate",
|
|
1376
1428
|
"message": "Download"
|
|
@@ -2137,7 +2189,7 @@
|
|
|
2137
2189
|
},
|
|
2138
2190
|
"components.SaleTunnelSuccess.successDetailMessage": {
|
|
2139
2191
|
"description": "Text to explain when the user will be able to start its training.",
|
|
2140
|
-
"message": "You
|
|
2192
|
+
"message": "You’ll be able to start your training once the first installment has been paid, or once access opens if no payment is required."
|
|
2141
2193
|
},
|
|
2142
2194
|
"components.SaleTunnelSuccess.successMessage": {
|
|
2143
2195
|
"description": "Message to confirm that order has been created",
|
|
@@ -2457,7 +2509,7 @@
|
|
|
2457
2509
|
},
|
|
2458
2510
|
"components.TeacherDashboard.TeacherDashboardRoutes.course.product.learnerList.label": {
|
|
2459
2511
|
"description": "Label to display the product's learner list view.",
|
|
2460
|
-
"message": "
|
|
2512
|
+
"message": "Buyers"
|
|
2461
2513
|
},
|
|
2462
2514
|
"components.TeacherDashboard.TeacherDashboardRoutes.generalInformation.label": {
|
|
2463
2515
|
"description": "Label of the course general information view.",
|
|
@@ -2489,7 +2541,7 @@
|
|
|
2489
2541
|
},
|
|
2490
2542
|
"components.TeacherDashboard.TeacherDashboardRoutes.organization.course.product.learnerList.label": {
|
|
2491
2543
|
"description": "Label to display the organization product's learner list view.",
|
|
2492
|
-
"message": "
|
|
2544
|
+
"message": "Buyers"
|
|
2493
2545
|
},
|
|
2494
2546
|
"components.TeacherDashboard.TeacherDashboardRoutes.organization.courses.label": {
|
|
2495
2547
|
"description": "Label of the organization courses view.",
|
package/js/api/joanie.ts
CHANGED
|
@@ -16,6 +16,7 @@ import { JOANIE_API_VERSION } from 'settings';
|
|
|
16
16
|
import { ResourcesQuery } from 'hooks/useResources';
|
|
17
17
|
import { ObjectHelper } from 'utils/ObjectHelper';
|
|
18
18
|
import { Maybe, Nullable } from 'types/utils';
|
|
19
|
+
import { HttpError, HttpStatusCode } from 'utils/errors/HttpError';
|
|
19
20
|
import { checkStatus, getFileFromResponse } from './utils';
|
|
20
21
|
|
|
21
22
|
/*
|
|
@@ -366,10 +367,15 @@ const API = (): Joanie.API => {
|
|
|
366
367
|
);
|
|
367
368
|
},
|
|
368
369
|
},
|
|
369
|
-
seats_export: async (id: string): Promise<File> =>
|
|
370
|
-
fetchWithJWT(
|
|
371
|
-
.
|
|
372
|
-
|
|
370
|
+
seats_export: async (id: string): Promise<File> => {
|
|
371
|
+
const response = await fetchWithJWT(
|
|
372
|
+
ROUTES.user.batchOrders.seats_export.replace(':id', id),
|
|
373
|
+
);
|
|
374
|
+
if (response.status === HttpStatusCode.UNPROCESSABLE_ENTITY) {
|
|
375
|
+
throw new HttpError(response.status, response.statusText);
|
|
376
|
+
}
|
|
377
|
+
return checkStatus(response).then(getFileFromResponse);
|
|
378
|
+
},
|
|
373
379
|
},
|
|
374
380
|
enrollments: {
|
|
375
381
|
create: async (payload) =>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { useId } from 'react';
|
|
2
|
-
import { Button } from '@openfun/cunningham-react';
|
|
2
|
+
import { Alert, Button, VariantType } from '@openfun/cunningham-react';
|
|
3
3
|
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
|
4
4
|
import { Spinner } from 'components/Spinner';
|
|
5
|
+
import { Icon, IconTypeEnum } from 'components/Icon';
|
|
6
|
+
import { HttpStatusCode } from 'utils/errors/HttpError';
|
|
5
7
|
import { useDownloadBatchOrderSeats } from 'hooks/useDownloadBatchOrderSeats';
|
|
6
8
|
|
|
7
9
|
const messages = defineMessages({
|
|
@@ -20,6 +22,12 @@ const messages = defineMessages({
|
|
|
20
22
|
description: 'Text displayed for seats value in batch order',
|
|
21
23
|
id: 'batchOrder.seats',
|
|
22
24
|
},
|
|
25
|
+
noSeatsOwned: {
|
|
26
|
+
defaultMessage:
|
|
27
|
+
'No participants have claimed their seat yet. The export will be available once at least one participant has enrolled.',
|
|
28
|
+
description: 'Error message displayed when trying to export seats but no seats are owned yet.',
|
|
29
|
+
id: 'components.DownloadBatchOrderSeatsButton.noSeatsOwned',
|
|
30
|
+
},
|
|
23
31
|
});
|
|
24
32
|
|
|
25
33
|
export const sanitizeForFilename = (str: string) =>
|
|
@@ -46,7 +54,7 @@ const DownloadBatchOrderSeatsButton = ({
|
|
|
46
54
|
batchOrderId,
|
|
47
55
|
productTitle,
|
|
48
56
|
}: DownloadBatchOrderSeatsButtonProps) => {
|
|
49
|
-
const { download, loading } = useDownloadBatchOrderSeats();
|
|
57
|
+
const { download, loading, error } = useDownloadBatchOrderSeats();
|
|
50
58
|
const labelId = useId();
|
|
51
59
|
const intl = useIntl();
|
|
52
60
|
|
|
@@ -56,24 +64,33 @@ const DownloadBatchOrderSeatsButton = ({
|
|
|
56
64
|
};
|
|
57
65
|
|
|
58
66
|
return (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
67
|
+
<>
|
|
68
|
+
<Button
|
|
69
|
+
size="small"
|
|
70
|
+
color="brand"
|
|
71
|
+
variant="primary"
|
|
72
|
+
className="dashboard-item__action-button"
|
|
73
|
+
icon={<Icon name={IconTypeEnum.DOWNLOAD} size="small" />}
|
|
74
|
+
iconPosition="left"
|
|
75
|
+
disabled={loading}
|
|
76
|
+
onClick={handleClick}
|
|
77
|
+
>
|
|
78
|
+
{loading ? (
|
|
79
|
+
<Spinner theme="primary" aria-labelledby={labelId}>
|
|
80
|
+
<span id={labelId}>
|
|
81
|
+
<FormattedMessage {...messages.generating} />
|
|
82
|
+
</span>
|
|
83
|
+
</Spinner>
|
|
84
|
+
) : (
|
|
85
|
+
<FormattedMessage {...messages.download} />
|
|
86
|
+
)}
|
|
87
|
+
</Button>
|
|
88
|
+
{error?.code === HttpStatusCode.UNPROCESSABLE_ENTITY && (
|
|
89
|
+
<Alert type={VariantType.ERROR} className="mt-s">
|
|
90
|
+
<FormattedMessage {...messages.noSeatsOwned} />
|
|
91
|
+
</Alert>
|
|
75
92
|
)}
|
|
76
|
-
|
|
93
|
+
</>
|
|
77
94
|
);
|
|
78
95
|
};
|
|
79
96
|
|
|
@@ -129,4 +129,32 @@ describe('useDownloadBatchOrderSeats', () => {
|
|
|
129
129
|
expect(result.current.loading).toBe(false);
|
|
130
130
|
});
|
|
131
131
|
});
|
|
132
|
+
|
|
133
|
+
it('exposes a 422 HttpError when seats export fails because no seats are owned', async () => {
|
|
134
|
+
const batchOrder = BatchOrderReadFactory().one();
|
|
135
|
+
const DOWNLOAD_URL = `https://joanie.test/api/v1.0/batch-orders/${batchOrder.id}/seats-export/`;
|
|
136
|
+
fetchMock.get(DOWNLOAD_URL, {
|
|
137
|
+
status: HttpStatusCode.UNPROCESSABLE_ENTITY,
|
|
138
|
+
body: { detail: 'Batch order has no seats owned, cannot export seats.' },
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
const { result } = renderHook(() => useDownloadBatchOrderSeats(), {
|
|
142
|
+
wrapper: Wrapper,
|
|
143
|
+
});
|
|
144
|
+
await waitFor(() => expect(result.current).not.toBeNull());
|
|
145
|
+
|
|
146
|
+
expect(result.current.error).toBeUndefined();
|
|
147
|
+
|
|
148
|
+
act(() => {
|
|
149
|
+
result.current.download(batchOrder.id);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
await waitFor(() => {
|
|
153
|
+
expect(fetchMock.called(DOWNLOAD_URL)).toBe(true);
|
|
154
|
+
expect(result.current.error?.code).toBe(HttpStatusCode.UNPROCESSABLE_ENTITY);
|
|
155
|
+
// eslint-disable-next-line compat/compat
|
|
156
|
+
expect(URL.createObjectURL).toHaveBeenCalledTimes(0);
|
|
157
|
+
expect(result.current.loading).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
132
160
|
});
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import { useJoanieApi } from 'contexts/JoanieApiContext';
|
|
3
3
|
import { browserDownloadFromBlob } from 'utils/download';
|
|
4
|
+
import { HttpError, HttpStatusCode } from 'utils/errors/HttpError';
|
|
4
5
|
|
|
5
6
|
export const useDownloadBatchOrderSeats = () => {
|
|
6
7
|
const [loading, setLoading] = useState(false);
|
|
8
|
+
const [error, setError] = useState<HttpError | undefined>();
|
|
7
9
|
const API = useJoanieApi();
|
|
8
10
|
|
|
9
11
|
return {
|
|
10
12
|
download: async (batchOrderId: string, filename?: string) => {
|
|
11
13
|
setLoading(true);
|
|
14
|
+
setError(undefined);
|
|
12
15
|
try {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const downloadFn = async () => {
|
|
17
|
+
try {
|
|
18
|
+
return await API.user.batchOrders.seats_export(batchOrderId);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
if (err instanceof HttpError && err.code === HttpStatusCode.UNPROCESSABLE_ENTITY) {
|
|
21
|
+
setError(err);
|
|
22
|
+
}
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
await browserDownloadFromBlob(downloadFn, false, filename);
|
|
18
27
|
} finally {
|
|
19
28
|
setLoading(false);
|
|
20
29
|
}
|
|
21
30
|
},
|
|
22
31
|
loading,
|
|
32
|
+
error,
|
|
23
33
|
};
|
|
24
34
|
};
|