diff --git a/.eslintrc b/.eslintrc index 7f627918..520ea965 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,4 +1,4 @@ { "root": true, - "extends": ["@kth/eslint-config-kth"], + "extends": ["plugin:react-hooks/recommended", "@kth/eslint-config-kth"], } diff --git a/.gitignore b/.gitignore index 6b4dcd7f..8947aa9e 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,7 @@ yarn.lock notes* # Files downloaded during unit test -course-information-statistics-* \ No newline at end of file +course-information-statistics-* + +# Jest coverage +coverage \ No newline at end of file diff --git a/i18n/messages.en.js b/i18n/messages.en.js index afddba4b..1f932e61 100644 --- a/i18n/messages.en.js +++ b/i18n/messages.en.js @@ -144,7 +144,6 @@ module.exports = { course_language: 'Language of instruction', course_required_equipment: 'Equipment', course_level_code: 'Education cycle', - course_establishment: 'Fastställande', course_decision_to_discontinue: 'Avvecklingsbeslut', course_transitional_reg: 'Transitional regulations', course_ethical: 'Ethical approach', diff --git a/i18n/messages.se.js b/i18n/messages.se.js index 5d7954d5..1583004c 100644 --- a/i18n/messages.se.js +++ b/i18n/messages.se.js @@ -146,7 +146,6 @@ module.exports = { course_language: 'Undervisningsspråk', course_required_equipment: 'Utrustning', course_level_code: 'Utbildningsnivå', - course_establishment: 'Fastställande', course_decision_to_discontinue: 'Avvecklingsbeslut', course_transitional_reg: 'Övergångsbestämmelser', course_ethical: 'Etiskt förhållningssätt', diff --git a/package.json b/package.json index 9186725e..64975ca8 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "test:file:watch": "jest ./server/apiCalls/transformers/offerings-over-several-semesters.test.js --watch", "test:notify": "jest --watch --notify", "docker": "npm install --development && npm run build && npm prune --production", - "lint": "eslint public server && prettier-eslint --list-different **/*.js", + "lint": "eslint \"{public,server}/**/*.{js,jsx}\"", "prepare": "husky", "start": "bash -c 'cat /KTH_NODEJS; NODE_ENV=production node app.js'", "start-dev": "bash -c 'NODE_ENV=development concurrently --kill-others -n build,app \"npm run build-dev\" \"nodemon app.js\"'" diff --git a/public/css/kursinfo-web.scss b/public/css/kursinfo-web.scss index c36442c9..a045befb 100644 --- a/public/css/kursinfo-web.scss +++ b/public/css/kursinfo-web.scss @@ -134,30 +134,6 @@ sup { } } -/************************************************/ - -/* Animation */ -#roundInformationOneCol, -#roundKeyInformation, -#coreContent { - @keyframes fadeOutIn { - 0% { - opacity: 1; - } - 50% { - opacity: 0; - } - 100% { - opacity: 1; - } - } - - .fadeOutIn { - animation-name: fadeOutIn; - animation-duration: 800ms; - } -} - ///******************** MODAL ****************************/// .modal { .modal-title { diff --git a/public/js/app/client-context/addClientFunctionsToWebContext.jsx b/public/js/app/client-context/addClientFunctionsToWebContext.jsx deleted file mode 100644 index 00a847f2..00000000 --- a/public/js/app/client-context/addClientFunctionsToWebContext.jsx +++ /dev/null @@ -1,31 +0,0 @@ -'use strict' - -import axios from 'axios' - -function getCourseEmployees() { - const ladokRound = this.courseData.roundList[this.activeSemester][this.activeRoundIndex] - const { round_application_code: applicationCode } = ladokRound - const data = { - courseCode: this.courseCode, - semester: this.activeSemester, - applicationCodes: [applicationCode], - } - return axios.post(this.paths.ug.rest.api.uri, data).then(response => { - const { examiners, responsibles, teachers } = response.data - const courseRoundEmployees = { - examiners, - responsibles, - teachers, - } - return courseRoundEmployees - }) -} - -function addClientFunctionsToWebContext() { - const functions = { - getCourseEmployees, - } - return functions -} - -export { addClientFunctionsToWebContext } diff --git a/public/js/app/client-context/addClientFunctionsToWebContext.test.js b/public/js/app/client-context/addClientFunctionsToWebContext.test.js deleted file mode 100644 index ac9aec98..00000000 --- a/public/js/app/client-context/addClientFunctionsToWebContext.test.js +++ /dev/null @@ -1,12 +0,0 @@ -import { addClientFunctionsToWebContext } from './addClientFunctionsToWebContext' - -describe('Client functions for webContext addClientFunctionsToWebContext', () => { - test('create a new RouterStore', () => { - const clientSideContext = addClientFunctionsToWebContext() - expect(clientSideContext).toMatchInlineSnapshot(` - { - "getCourseEmployees": [Function], - } - `) - }) -}) diff --git a/public/js/app/components/CourseSectionList.jsx b/public/js/app/components/CourseSectionList.jsx index 590ebc52..b1f012a6 100644 --- a/public/js/app/components/CourseSectionList.jsx +++ b/public/js/app/components/CourseSectionList.jsx @@ -7,14 +7,8 @@ import { useMissingInfo } from '../hooks/useMissingInfo' import CourseSection from './CourseSections' import SyllabusInformation from './SyllabusInformation' -function CourseSectionList({ - courseInfo = {}, - partToShow, - syllabusList: syllabus = {}, - syllabusName, - syllabusSemesterList, -}) { - const [context] = useWebContext() +function CourseSectionList({ courseInfo = {}, partToShow, syllabus = {}, syllabusName, hasSyllabus }) { + const context = useWebContext() const { translation } = useLanguage() const { isMissingInfoLabel, missingInfoLabel } = useMissingInfo() @@ -193,12 +187,7 @@ function CourseSectionList({ id={partToShow} aria-label={`${translation.courseLabels.label_course_information} ${syllabusName}`} > - + { - const [context, setWebContext] = useWebContext() - const { roundDisabled } = context - const [roundSelectedIndex, setRoundSelectIndex] = React.useState(0) +const DROPDOWN_ID = 'roundsDropdown' +const EMPTY_OPTION = -1 +const RoundOptions = ({ roundsForSelectedSemester }) => { const { createRoundLabel } = useRoundUtils() - const dropdownID = 'roundsDropdown' + return roundsForSelectedSemester.map((round, roundIndex) => { + const optionLabel = createRoundLabel(round) - async function handleDropdownSelect(e) { - e.preventDefault() + const uniqueKey = `${optionLabel}${round.round_application_code}${round.round_start_date}` - const eTarget = e.target - const selectedOption = eTarget[eTarget.selectedIndex] + return ( + + ) + }) +} - const selectInfo = selectedOption.id.split('_') +const DropdownRounds = ({ roundsForSelectedSemester, semesterRoundState }) => { + const { setSelectedRoundIndex, resetSelectedRoundIndex } = semesterRoundState - const newContext = { - activeRoundIndex: eTarget.selectedIndex === 0 ? 0 : selectInfo[1], - showRoundData: eTarget.selectedIndex !== 0, - roundSelectedIndex: eTarget.selectedIndex, - } - setWebContext({ ...context, ...newContext }) + const { translation } = useLanguage() + const label = translation.courseLabels.label_round_select - setRoundSelectIndex(eTarget.selectedIndex) - } + const [selectedOptionIndex, setSelectedOptionIndex] = React.useState(EMPTY_OPTION) + + useEffect(() => { + setSelectedOptionIndex(EMPTY_OPTION) + }, [roundsForSelectedSemester]) + + const handleDropdownSelect = React.useCallback( + ({ target }) => { + const { value } = target + + const selectedOption = parseInt(value) + + const isEmptyOption = selectedOption === EMPTY_OPTION - if (courseRoundList && courseRoundList.length < 2) { - return '' + const newActiveRoundIndex = isEmptyOption ? 0 : selectedOption + + if (isEmptyOption) { + resetSelectedRoundIndex() + } else { + setSelectedRoundIndex(newActiveRoundIndex) + } + + setSelectedOptionIndex(selectedOption) + }, + [setSelectedRoundIndex, resetSelectedRoundIndex, setSelectedOptionIndex] + ) + + if (!roundsForSelectedSemester || roundsForSelectedSemester.length < 2) { + return null } + return (
-