From dc264b86053785f28a3a2f96c00449df260113ca Mon Sep 17 00:00:00 2001 From: Florent Chehab Date: Sun, 14 Jul 2019 19:05:53 +0200 Subject: [PATCH] hotFix(front crash on missing course code) & refacto(moduleHeader as component) & Tweaks Hot fix: * Front was crashing on course sort when a course didn't have a code. Refacto: * Changed module header subfunctions to concrete components, Tweaks: * tabs on the university page are now centered on smaller devices, * Removed react swipeable from search for performance, * Changed search pagination to progress for better long list support, * Smaller univ name on the edit feedback page, * Fixed wording unlinked partners for singular vs plural, * Allow disabled items in SimpleFormMenu, Other: * Removed univ logo from edit form, not supported yet, --- backend/backend_app/serializers.py | 5 + .../src/components/app/UnlinkedPartners.js | 11 +- .../src/components/common/SimplePopupMenu.js | 5 +- frontend/src/components/form/Form.js | 2 + frontend/src/components/form/fields/Field.js | 2 +- .../src/components/form/fields/NumberField.js | 7 +- .../pages/PageEditExchangeFeedbacks.js | 2 +- .../recommendation/SelectListSubPage.js | 1 + .../components/recommendation/view/View.js | 5 +- frontend/src/components/search/UnivList.js | 38 ++-- .../university/UniversityTemplate.js | 2 +- .../editors/UniversityGeneralEditor.js | 14 +- .../modules/common/ModuleGroupWrapper.js | 3 - .../modules/common/ModuleWrapper.js | 87 +++----- .../getModerationTooltipAndClass.js | 2 +- .../moduleWrapperFunctions/renderFirstRow.js | 79 -------- .../moduleWrapperFunctions/renderTitle.js | 39 ---- .../common/subComponents/ModuleFirstRow.js | 187 ++++++++++++++++++ .../common/subComponents/ModuleTitle.js | 80 ++++++++ .../UpdateInfo.js} | 10 +- .../UsefulLinks.js} | 46 ++++- .../CourseFeedback.js | 18 +- .../edit/EditModuleCoursesFeedback.js | 19 +- .../university/tabs/TipsAndTricksTab.js | 2 +- 24 files changed, 424 insertions(+), 242 deletions(-) delete mode 100644 frontend/src/components/university/modules/common/moduleWrapperFunctions/renderFirstRow.js delete mode 100644 frontend/src/components/university/modules/common/moduleWrapperFunctions/renderTitle.js create mode 100644 frontend/src/components/university/modules/common/subComponents/ModuleFirstRow.js create mode 100644 frontend/src/components/university/modules/common/subComponents/ModuleTitle.js rename frontend/src/components/university/modules/common/{moduleWrapperFunctions/renderUpdateInfo.js => subComponents/UpdateInfo.js} (82%) rename frontend/src/components/university/modules/common/{moduleWrapperFunctions/renderUsefulLinks.js => subComponents/UsefulLinks.js} (54%) diff --git a/backend/backend_app/serializers.py b/backend/backend_app/serializers.py index 90940ef6..aa8ac9ac 100644 --- a/backend/backend_app/serializers.py +++ b/backend/backend_app/serializers.py @@ -9,10 +9,14 @@ from backend_app.models.exchange import Exchange class CourseFeedbackSerializer(EssentialModuleSerializer): course_code = serializers.SerializerMethodField() # needed for the front + course_title = serializers.SerializerMethodField() # needed for the front def get_course_code(self, obj): return obj.course.code + def get_course_title(self, obj): + return obj.course.title + def update(self, instance, validated_data): instance.untouched = False return super().update(instance, validated_data) @@ -21,6 +25,7 @@ class CourseFeedbackSerializer(EssentialModuleSerializer): model = CourseFeedback fields = EssentialModuleSerializer.Meta.fields + ( "course_code", + "course_title", "language", "comment", "adequation", diff --git a/frontend/src/components/app/UnlinkedPartners.js b/frontend/src/components/app/UnlinkedPartners.js index 3b432537..bbaf959b 100644 --- a/frontend/src/components/app/UnlinkedPartners.js +++ b/frontend/src/components/app/UnlinkedPartners.js @@ -60,9 +60,14 @@ class UnlinkedPartners extends CustomComponentForAPI { nUnlinked > 0 ? <> - ⚠ {unlinkedPartners.length} universités partenaires de l'UTC - ne sont pas encore pleinement disponible(s) sur la plateforme. - Plus d'informations  + ⚠  + { + nUnlinked === 1 ? + "1 université partenaire de l'UTC n'est pas encore pleinement disponible" + : + `${nUnlinked} universités partenaires de l'UTC ne sont pas encore pleinement disponibles` + } + sur la plateforme. Plus d'informations  ici diff --git a/frontend/src/components/common/SimplePopupMenu.js b/frontend/src/components/common/SimplePopupMenu.js index ab963ee8..4358a57e 100644 --- a/frontend/src/components/common/SimplePopupMenu.js +++ b/frontend/src/components/common/SimplePopupMenu.js @@ -32,8 +32,8 @@ function SimplePopupMenu(props) { onClose={handleClose} > { - props.items.map(({label, onClick}, key) => ( - { + props.items.map(({label, onClick, disabled}, key) => ( + { onClick(); handleClose(); }}> @@ -51,6 +51,7 @@ SimplePopupMenu.propTypes = { items: PropTypes.arrayOf(PropTypes.shape({ label: PropTypes.string.isRequired, onClick: PropTypes.func.isRequired, + disabled: PropTypes.bool.isRequired, })).isRequired, renderHolder: PropTypes.func.isRequired, }; diff --git a/frontend/src/components/form/Form.js b/frontend/src/components/form/Form.js index 3eea5f08..1dcae0fb 100644 --- a/frontend/src/components/form/Form.js +++ b/frontend/src/components/form/Form.js @@ -152,6 +152,8 @@ class Form extends Component { // we need to compare objects (ie JSON objects) differently if (typeof cmp1 === "object") { return !isEqual(cmp1, cmp2); + } else if ((typeof cmp1 === "number") || (typeof cmp2 === "number")) { + return cmp1 != cmp2; // allow 93 == "93.00" } else { return cmp1 !== cmp2; } diff --git a/frontend/src/components/form/fields/Field.js b/frontend/src/components/form/fields/Field.js index c373cab9..c129c039 100644 --- a/frontend/src/components/form/fields/Field.js +++ b/frontend/src/components/form/fields/Field.js @@ -134,7 +134,7 @@ Field.propTypes = { required: PropTypes.bool.isRequired, // is the field required ? label: PropTypes.string, // text to go along the field comment: PropTypes.string, // text to give more information on what is expected - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, // value of the field + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // value of the field form: PropTypes.object, // required in constructor (reference of to the) form containing the field fieldMapping: PropTypes.string.isRequired, // name of the field in the data }; diff --git a/frontend/src/components/form/fields/NumberField.js b/frontend/src/components/form/fields/NumberField.js index 94b4a80b..212bc122 100644 --- a/frontend/src/components/form/fields/NumberField.js +++ b/frontend/src/components/form/fields/NumberField.js @@ -39,8 +39,11 @@ class NumberField extends Field { } serializeFromField() { - const value = super.serializeFromField(); - return parseFloat(value); + const value = super.serializeFromField(), + parsed = parseFloat(value); + + if (isNaN(parsed)) return null; + else return parsed; } handleChangeValue(val) { diff --git a/frontend/src/components/pages/PageEditExchangeFeedbacks.js b/frontend/src/components/pages/PageEditExchangeFeedbacks.js index 5298caf7..c38c7d9f 100644 --- a/frontend/src/components/pages/PageEditExchangeFeedbacks.js +++ b/frontend/src/components/pages/PageEditExchangeFeedbacks.js @@ -45,7 +45,7 @@ class PageEditExchangeFeedbacks extends CustomComponentForAPI { if (id) { return ( <> - + { univId ? {univName} : diff --git a/frontend/src/components/recommendation/SelectListSubPage.js b/frontend/src/components/recommendation/SelectListSubPage.js index 48171cd6..bf7a7474 100644 --- a/frontend/src/components/recommendation/SelectListSubPage.js +++ b/frontend/src/components/recommendation/SelectListSubPage.js @@ -103,6 +103,7 @@ class SelectListSubPage extends CustomComponentForAPI { this.props.deleteList(list.id, () => this.props.invalidateReadAll()) }, diff --git a/frontend/src/components/recommendation/view/View.js b/frontend/src/components/recommendation/view/View.js index b9996c00..37972d9a 100644 --- a/frontend/src/components/recommendation/view/View.js +++ b/frontend/src/components/recommendation/view/View.js @@ -452,6 +452,7 @@ class View extends React.Component { this.deleteBlock() }, @@ -466,8 +467,8 @@ class View extends React.Component { this.addBlock("text-block")}, - {label: "Université", onClick: () => this.addBlock("univ-block")}, + {label: "Markdown", onClick: () => this.addBlock("text-block"), disabled: false,}, + {label: "Université", onClick: () => this.addBlock("univ-block"), disabled: false,}, ]} renderHolder={({onClick}) => (