diff --git a/backend/README.md b/backend/README.md index 7b925382..304ecb1f 100644 --- a/backend/README.md +++ b/backend/README.md @@ -28,7 +28,8 @@ MAIN_BOARD_ID = 9 ELECTION_COMMITTEE_ID = 10 ## Optional ntnui-tools development variable -API_URI = "https://dev.api.ntnui.no" +NTNUI_TOOLS_API_URL = "https://dev.api.ntnui.no" + ``` ### ☁ Set up MongoDB Atlas diff --git a/backend/controllers/applicationController.ts b/backend/controllers/applicationController.ts index d594732b..d14d7dcc 100644 --- a/backend/controllers/applicationController.ts +++ b/backend/controllers/applicationController.ts @@ -296,6 +296,7 @@ const getApplications = async ( applications: { _id: 1, name: 1, + email: 1, submitted_date: 1, committees: { _id: 1, @@ -303,7 +304,9 @@ const getApplications = async ( slug: 1, }, statuses: { + _id: 1, committee: 1, + value: 1, }, }, pagination: { diff --git a/backend/fixtures/development/admissionperiod.json b/backend/fixtures/development/admissionperiod.json index b85be066..a307f9e0 100644 --- a/backend/fixtures/development/admissionperiod.json +++ b/backend/fixtures/development/admissionperiod.json @@ -1,4 +1,6 @@ -{ - "start_date": "2022-02-25", - "end_date": "2022-03-31" -} +[ + { + "start_date": "2022-02-25", + "end_date": "2022-03-31" + } +] diff --git a/backend/fixtures/development/applications.json b/backend/fixtures/development/applications.json index a4b5b46d..db82e1f6 100644 --- a/backend/fixtures/development/applications.json +++ b/backend/fixtures/development/applications.json @@ -7,6 +7,7 @@ "phone_number": "+6969696969", "email": "bolle@bolle.no", "text": "Jeg forsøker å søke til Triatlon og Turn", + "main_board_text": "", "committees": [2, 3], "statuses": [ { @@ -28,6 +29,7 @@ "phone_number": "+420420420", "email": "Navn@Navnesen.no", "text": "Jeg forsøker å søke til Ski og Fjellsport", + "main_board_text": "", "committees": [4], "statuses": [ { @@ -45,7 +47,8 @@ "name": "Cris P Bacon", "phone_number": "+123456789", "email": "Bacon@IsGoodForMe.no", - "text": "Jeg forsøker å søke til Hovedstyret", + "text": "", + "main_board_text": "Søknad til Introstyret", "committees": [9], "statuses": [ { @@ -63,7 +66,8 @@ "name": "Olle Bolle", "phone_number": "+987654321", "email": "Olle@Bolle.no", - "text": "Jeg forsøker å søke til Hovedstyret og Sprint", + "text": "Søknadstekst til Sprint", + "main_board_text": "Søknadstekst til Introstyret", "committees": [1, 9], "statuses": [ { diff --git a/backend/fixtures/development/committees.json b/backend/fixtures/development/committees.json index 57dc5c3a..43efb64d 100644 --- a/backend/fixtures/development/committees.json +++ b/backend/fixtures/development/committees.json @@ -57,7 +57,7 @@ }, { "_id": 9, - "name": "Hovedstyret", + "name": "Introstyret", "slug": "hovedstyret", "access_roles": [ "deputy_leader", diff --git a/frontend/README.md b/frontend/README.md index a9c6f586..b19a9ef3 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -15,8 +15,9 @@ Add environment variables to an `.env` file in the frontend folder to connect to ## Optional environment variables to use in development REACT_APP_BACKEND_URI = 'http://localhost:8082' -# Set main board ID to 9 while using development environment dev.api.ntnui.no +# Set main board ID to 9 and election committee ID to 10 while using development environment dev.api.ntnui.no REACT_APP_MAIN_BOARD_ID = 9 +REACT_APP_ELECTION_COMMITTEE_ID = 10 ``` ## Scripts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 397b01ff..6174e9e7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,11 +10,11 @@ "license": "MIT", "dependencies": { "@emotion/react": "^11.10.4", - "@mantine/core": "^5.4.1", - "@mantine/dates": "^5.4.1", - "@mantine/form": "^5.4.1", - "@mantine/hooks": "^5.4.1", - "@mantine/notifications": "^5.4.1", + "@mantine/core": "^5.10.0", + "@mantine/dates": "^5.10.0", + "@mantine/form": "^5.10.0", + "@mantine/hooks": "^5.10.0", + "@mantine/notifications": "^5.10.0", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", @@ -2926,40 +2926,40 @@ } }, "node_modules/@mantine/core": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-5.4.1.tgz", - "integrity": "sha512-lzDlUrUxz535XroXA8QnPXyIjfoqGqq9lJzQ9hhSYStrsvhAvQOUAcLLi1JLOYrqqJlFE+nSprDgDR/ysetkPg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-5.10.0.tgz", + "integrity": "sha512-if272RiYPK0nQQdGNwcCSY7bCPJW9455qXlRhnYOr021xh89T8WFVPeDw4uwcxoXsXdKRV5GAi9irSnsUqsjJQ==", "dependencies": { "@floating-ui/react-dom-interactions": "^0.10.1", - "@mantine/styles": "5.4.1", - "@mantine/utils": "5.4.1", - "@radix-ui/react-scroll-area": "1.0.0", + "@mantine/styles": "5.10.0", + "@mantine/utils": "5.10.0", + "@radix-ui/react-scroll-area": "1.0.2", "react-textarea-autosize": "8.3.4" }, "peerDependencies": { - "@mantine/hooks": "5.4.1", + "@mantine/hooks": "5.10.0", "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "node_modules/@mantine/dates": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-5.4.1.tgz", - "integrity": "sha512-S1GRUPV5phEuU6rhRzfFFI4rkvIZLTC+Oo13PSBBCg/Ku/SfyyAxrsQM5N1aO5F6C0OBQOwrYQGE99yMQ+VPGA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-5.10.0.tgz", + "integrity": "sha512-gK+BiXaTY9X1ESjRPNI7CASYx/QseDolNUJBqvXw6YB19QQ/PFCnyoj3xGiJUqiYfzKbFDKfTVSkP5cR6SHljA==", "dependencies": { - "@mantine/utils": "5.4.1" + "@mantine/utils": "5.10.0" }, "peerDependencies": { - "@mantine/core": "5.4.1", - "@mantine/hooks": "5.4.1", + "@mantine/core": "5.10.0", + "@mantine/hooks": "5.10.0", "dayjs": ">=1.0.0", "react": ">=16.8.0" } }, "node_modules/@mantine/form": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/form/-/form-5.4.1.tgz", - "integrity": "sha512-n7Iujyy7S93TG+A3ol7RuNCAP3O/AEgfryxJlsGIF0YK14zX3aUqeJYAG5XF5IcT5gz8JmDCzzwC3xf6uItp1g==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/form/-/form-5.10.0.tgz", + "integrity": "sha512-4X9RR75Aaq0fxu+kJ/mL/CAOPlgHNhbUY657hGJlfwqWJFwibnhyCe1s5lpZ7Sm8F3hNsSMpWzdA687gvhw4Lw==", "dependencies": { "fast-deep-equal": "^3.1.3", "klona": "^2.0.5" @@ -2969,32 +2969,32 @@ } }, "node_modules/@mantine/hooks": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-5.4.1.tgz", - "integrity": "sha512-qLYWLhFTciyHZCHiSUXoGei3DBwo+2gjCP1zdko9YzKer9xgfKoVDBoxBGTdsAVpac4ZzmeMk/Jm74fWn8PU+A==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-5.10.0.tgz", + "integrity": "sha512-dAefxpvqjFtXNeKse+awkIa4U1XGnMMOqWg1+07Y2Ino2G6EiT8AEnYqQyTXgcPoNaWwG9533Q/DDadmyweqaQ==", "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@mantine/notifications": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-5.4.1.tgz", - "integrity": "sha512-HiibhEhS7irz+fz1NYhHUPymeys9E+BttjR6HVrl6d6oKraTJLSdFs7q4aPcCmLRpd1PCHT2AFO5pU+krT2Zjw==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-5.10.0.tgz", + "integrity": "sha512-ipqH8ia0ibjHj1+4hIgFmYK5RbmGX2oEyZWoIYVie5rwf8OgdIQOjF4LaZw+KVw0QPvNajj9Fj4AQay5egJSDQ==", "dependencies": { - "@mantine/utils": "5.4.1", + "@mantine/utils": "5.10.0", "react-transition-group": "4.4.2" }, "peerDependencies": { - "@mantine/core": "5.4.1", - "@mantine/hooks": "5.4.1", + "@mantine/core": "5.10.0", + "@mantine/hooks": "5.10.0", "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "node_modules/@mantine/styles": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-5.4.1.tgz", - "integrity": "sha512-rhLivlSHHJqGlxwaFhAs34TPMcLpvYczhIxBxApj/ngP8LZD8+DPSk+yGN1pAL2Q2JBGKMnhqz5H9ow8zzOYcA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-5.10.0.tgz", + "integrity": "sha512-3JBM5LWJHb4Yk7jymPiSuaBJRoe2CgA7KoyYWgabwBP115GlHPb1rQCcavJsobHV4U+wFfZEEUnVBpaAaXqgmw==", "dependencies": { "clsx": "1.1.1", "csstype": "3.0.9" @@ -3011,9 +3011,9 @@ "integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==" }, "node_modules/@mantine/utils": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-5.4.1.tgz", - "integrity": "sha512-yaZ7gv9dkr98L65EjaAniZmJpVEPzHbe5aDDljIePLgcU5hVCdUls2v31YXslTf1/CJ5yZp/L7LPYLN86EXlEA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-5.10.0.tgz", + "integrity": "sha512-mHnNm0ajIa8qLAIEwv82N6+7YKecynOA3I8vzgBHXS2x4HwGsHITFYGmMh2LNpx5dRL034tObfEFYZXqncyEDw==", "peerDependencies": { "react": ">=16.8.0" } @@ -3171,12 +3171,12 @@ } }, "node_modules/@radix-ui/react-primitive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.0.tgz", - "integrity": "sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz", + "integrity": "sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.0" + "@radix-ui/react-slot": "1.0.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3184,9 +3184,9 @@ } }, "node_modules/@radix-ui/react-scroll-area": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.0.tgz", - "integrity": "sha512-3SNFukAjS5remgtpAVR9m3Zgo23ZojBZ8V3TCyR3A+56x2mtVqKlPV4+e8rScZUFMuvtbjIdQCmsJBFBazKZig==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.2.tgz", + "integrity": "sha512-k8VseTxI26kcKJaX0HPwkvlNBPTs56JRdYzcZ/vzrNUkDlvXBy8sMc7WvCpYzZkHgb+hd72VW9MqkqecGtuNgg==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/number": "1.0.0", @@ -3195,7 +3195,7 @@ "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0" }, @@ -3205,9 +3205,9 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.0.tgz", - "integrity": "sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz", + "integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0" @@ -5329,9 +5329,9 @@ } }, "node_modules/babel-loader/node_modules/loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -11589,9 +11589,9 @@ } }, "node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -13998,9 +13998,9 @@ } }, "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "engines": { "node": ">= 12.13.0" } @@ -14218,25 +14218,14 @@ } }, "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dependencies": { - "minimatch": "3.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/recursive-readdir/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dependencies": { - "brace-expansion": "^1.1.7" + "minimatch": "^3.0.5" }, "engines": { - "node": "*" + "node": ">=6.0.0" } }, "node_modules/redent": { @@ -15413,9 +15402,9 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "node_modules/tabler-icons-react": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/tabler-icons-react/-/tabler-icons-react-1.55.0.tgz", - "integrity": "sha512-+5zz2mQ2wl5658tMtK4mxUCFdF7TyPiPqLAvCUHHOeltZWukExE3aftY04HDMcap8skob/UFbzSzVhifCCMeUQ==", + "version": "1.56.0", + "resolved": "https://registry.npmjs.org/tabler-icons-react/-/tabler-icons-react-1.56.0.tgz", + "integrity": "sha512-FOme3w6PJIWDpeXqQ4xjArQqdxzrr9xNy7PSSgWpRzOUQ71RyZ7jt6WThsfyLBz5os78TPJRA8f/0NLjnKcx9A==", "peerDependencies": { "react": ">= 16.8.0" } @@ -19048,53 +19037,53 @@ } }, "@mantine/core": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-5.4.1.tgz", - "integrity": "sha512-lzDlUrUxz535XroXA8QnPXyIjfoqGqq9lJzQ9hhSYStrsvhAvQOUAcLLi1JLOYrqqJlFE+nSprDgDR/ysetkPg==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-5.10.0.tgz", + "integrity": "sha512-if272RiYPK0nQQdGNwcCSY7bCPJW9455qXlRhnYOr021xh89T8WFVPeDw4uwcxoXsXdKRV5GAi9irSnsUqsjJQ==", "requires": { "@floating-ui/react-dom-interactions": "^0.10.1", - "@mantine/styles": "5.4.1", - "@mantine/utils": "5.4.1", - "@radix-ui/react-scroll-area": "1.0.0", + "@mantine/styles": "5.10.0", + "@mantine/utils": "5.10.0", + "@radix-ui/react-scroll-area": "1.0.2", "react-textarea-autosize": "8.3.4" } }, "@mantine/dates": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-5.4.1.tgz", - "integrity": "sha512-S1GRUPV5phEuU6rhRzfFFI4rkvIZLTC+Oo13PSBBCg/Ku/SfyyAxrsQM5N1aO5F6C0OBQOwrYQGE99yMQ+VPGA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/dates/-/dates-5.10.0.tgz", + "integrity": "sha512-gK+BiXaTY9X1ESjRPNI7CASYx/QseDolNUJBqvXw6YB19QQ/PFCnyoj3xGiJUqiYfzKbFDKfTVSkP5cR6SHljA==", "requires": { - "@mantine/utils": "5.4.1" + "@mantine/utils": "5.10.0" } }, "@mantine/form": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/form/-/form-5.4.1.tgz", - "integrity": "sha512-n7Iujyy7S93TG+A3ol7RuNCAP3O/AEgfryxJlsGIF0YK14zX3aUqeJYAG5XF5IcT5gz8JmDCzzwC3xf6uItp1g==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/form/-/form-5.10.0.tgz", + "integrity": "sha512-4X9RR75Aaq0fxu+kJ/mL/CAOPlgHNhbUY657hGJlfwqWJFwibnhyCe1s5lpZ7Sm8F3hNsSMpWzdA687gvhw4Lw==", "requires": { "fast-deep-equal": "^3.1.3", "klona": "^2.0.5" } }, "@mantine/hooks": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-5.4.1.tgz", - "integrity": "sha512-qLYWLhFTciyHZCHiSUXoGei3DBwo+2gjCP1zdko9YzKer9xgfKoVDBoxBGTdsAVpac4ZzmeMk/Jm74fWn8PU+A==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-5.10.0.tgz", + "integrity": "sha512-dAefxpvqjFtXNeKse+awkIa4U1XGnMMOqWg1+07Y2Ino2G6EiT8AEnYqQyTXgcPoNaWwG9533Q/DDadmyweqaQ==", "requires": {} }, "@mantine/notifications": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-5.4.1.tgz", - "integrity": "sha512-HiibhEhS7irz+fz1NYhHUPymeys9E+BttjR6HVrl6d6oKraTJLSdFs7q4aPcCmLRpd1PCHT2AFO5pU+krT2Zjw==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-5.10.0.tgz", + "integrity": "sha512-ipqH8ia0ibjHj1+4hIgFmYK5RbmGX2oEyZWoIYVie5rwf8OgdIQOjF4LaZw+KVw0QPvNajj9Fj4AQay5egJSDQ==", "requires": { - "@mantine/utils": "5.4.1", + "@mantine/utils": "5.10.0", "react-transition-group": "4.4.2" } }, "@mantine/styles": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-5.4.1.tgz", - "integrity": "sha512-rhLivlSHHJqGlxwaFhAs34TPMcLpvYczhIxBxApj/ngP8LZD8+DPSk+yGN1pAL2Q2JBGKMnhqz5H9ow8zzOYcA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/styles/-/styles-5.10.0.tgz", + "integrity": "sha512-3JBM5LWJHb4Yk7jymPiSuaBJRoe2CgA7KoyYWgabwBP115GlHPb1rQCcavJsobHV4U+wFfZEEUnVBpaAaXqgmw==", "requires": { "clsx": "1.1.1", "csstype": "3.0.9" @@ -19108,9 +19097,9 @@ } }, "@mantine/utils": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-5.4.1.tgz", - "integrity": "sha512-yaZ7gv9dkr98L65EjaAniZmJpVEPzHbe5aDDljIePLgcU5hVCdUls2v31YXslTf1/CJ5yZp/L7LPYLN86EXlEA==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/@mantine/utils/-/utils-5.10.0.tgz", + "integrity": "sha512-mHnNm0ajIa8qLAIEwv82N6+7YKecynOA3I8vzgBHXS2x4HwGsHITFYGmMh2LNpx5dRL034tObfEFYZXqncyEDw==", "requires": {} }, "@nodelib/fs.scandir": { @@ -19210,18 +19199,18 @@ } }, "@radix-ui/react-primitive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.0.tgz", - "integrity": "sha512-EyXe6mnRlHZ8b6f4ilTDrXmkLShICIuOTTj0GX4w1rp+wSxf3+TD05u1UOITC8VsJ2a9nwHvdXtOXEOl0Cw/zQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz", + "integrity": "sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-slot": "1.0.0" + "@radix-ui/react-slot": "1.0.1" } }, "@radix-ui/react-scroll-area": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.0.tgz", - "integrity": "sha512-3SNFukAjS5remgtpAVR9m3Zgo23ZojBZ8V3TCyR3A+56x2mtVqKlPV4+e8rScZUFMuvtbjIdQCmsJBFBazKZig==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.0.2.tgz", + "integrity": "sha512-k8VseTxI26kcKJaX0HPwkvlNBPTs56JRdYzcZ/vzrNUkDlvXBy8sMc7WvCpYzZkHgb+hd72VW9MqkqecGtuNgg==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/number": "1.0.0", @@ -19230,15 +19219,15 @@ "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.0", + "@radix-ui/react-primitive": "1.0.1", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0" } }, "@radix-ui/react-slot": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.0.tgz", - "integrity": "sha512-3mrKauI/tWXo1Ll+gN5dHcxDPdm/Df1ufcDLCecn+pnCIVcdWE7CujXo8QaXOWRJyZyQWWbpB8eFwHzWXlv5mQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.0.1.tgz", + "integrity": "sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0" @@ -20809,9 +20798,9 @@ } }, "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -25343,9 +25332,9 @@ "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==" }, "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "requires": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", @@ -26966,9 +26955,9 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==" }, "supports-color": { "version": "7.2.0", @@ -27126,21 +27115,11 @@ } }, "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "requires": { - "minimatch": "3.0.4" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + "minimatch": "^3.0.5" } }, "redent": { @@ -28023,9 +28002,9 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, "tabler-icons-react": { - "version": "1.55.0", - "resolved": "https://registry.npmjs.org/tabler-icons-react/-/tabler-icons-react-1.55.0.tgz", - "integrity": "sha512-+5zz2mQ2wl5658tMtK4mxUCFdF7TyPiPqLAvCUHHOeltZWukExE3aftY04HDMcap8skob/UFbzSzVhifCCMeUQ==", + "version": "1.56.0", + "resolved": "https://registry.npmjs.org/tabler-icons-react/-/tabler-icons-react-1.56.0.tgz", + "integrity": "sha512-FOme3w6PJIWDpeXqQ4xjArQqdxzrr9xNy7PSSgWpRzOUQ71RyZ7jt6WThsfyLBz5os78TPJRA8f/0NLjnKcx9A==", "requires": {} }, "tailwindcss": { diff --git a/frontend/src/components/ApplicationList.tsx b/frontend/src/components/ApplicationList.tsx index c1a082ed..915c363a 100644 --- a/frontend/src/components/ApplicationList.tsx +++ b/frontend/src/components/ApplicationList.tsx @@ -25,7 +25,7 @@ type ApplicationListProps = { applications: IApplication[] } -function ApplicationList(applications: ApplicationListProps) { +function ApplicationList({ applications }: ApplicationListProps) { let navigate = useNavigate() function itemClickHandler(id: string) { @@ -35,7 +35,7 @@ function ApplicationList(applications: ApplicationListProps) { const { classes } = useStyles() return ( - {applications.applications.map((item: IApplication, idx: number) => ( + {applications.map((item: IApplication, idx: number) => ( void + setSort: (sort: string) => void + setChosenCommittees: (committees: string[]) => void + setNameSearch: (nameSearch: string) => void + setStatus: (status: string) => void + sort: string + nameSearch: string + status: string + chosenCommittees: string[] } -function FilterSearch({ setFilter }: FilterSearchProps) { +function FilterSearch({ + setFilter, + setSort, + setChosenCommittees, + setNameSearch, + setStatus, + sort, + nameSearch, + status, + chosenCommittees, +}: FilterSearchProps) { const { classes } = useStyles() const [committees, setCommittees] = useState([]) - const [chosenCommittees, setChosenCommittees] = useState([]) - const [filterCommittees, setFilterCommittees] = useState([]) - const [status, setStatus] = useState('') - const [sort, setSort] = useState('date_desc') - const [nameSearch, setNameSearch] = useState('') useEffect(() => { // Retrieve committees for multiselect @@ -161,7 +174,7 @@ function FilterSearch({ setFilter }: FilterSearchProps) { // Update filter with nameSearch using debouncer useEffect(() => { let query = constructSearchFilterQuery( - filterCommittees, + chosenCommittees, sort, status, nameSearch @@ -172,13 +185,13 @@ function FilterSearch({ setFilter }: FilterSearchProps) { // Update filter with other fields on input-change useEffect(() => { let query = constructSearchFilterQuery( - filterCommittees, + chosenCommittees, sort, status, nameSearch ) setFilter(query.toString()) - }, [status, filterCommittees, sort, setFilter]) + }, [status, chosenCommittees, sort, setFilter]) function mapCommitteesToMultiselectData() { let dataList: { value: string; label: string }[] = [] @@ -279,7 +292,7 @@ function FilterSearch({ setFilter }: FilterSearchProps) { searchable clearable nothingFound='Nothing found' - onDropdownClose={() => setFilterCommittees(chosenCommittees)} + defaultValue={chosenCommittees} value={chosenCommittees} onChange={setChosenCommittees} rightSectionWidth={40} diff --git a/frontend/src/components/NTNUICopyButton.tsx b/frontend/src/components/NTNUICopyButton.tsx new file mode 100644 index 00000000..982bea47 --- /dev/null +++ b/frontend/src/components/NTNUICopyButton.tsx @@ -0,0 +1,39 @@ +import { + ActionIcon, + CopyButton as MantineCopyButton, + createStyles, + Tooltip, +} from '@mantine/core' +import { Check, Copy } from 'tabler-icons-react' + +const useStyles = createStyles((theme) => ({ + button: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + '&:hover': { + backgroundColor: theme.colors.ntnui_yellow[9] + '0F', + }, + }, +})) + +function NTNUICopyButton({ value }: { value: string }) { + const { classes } = useStyles() + return ( + + {({ copied, copy }) => ( + + + {copied ? : } + + + )} + + ) +} + +export default NTNUICopyButton diff --git a/frontend/src/pages/ApplicationDetails.tsx b/frontend/src/pages/ApplicationDetails.tsx index 4c617be0..19a53291 100644 --- a/frontend/src/pages/ApplicationDetails.tsx +++ b/frontend/src/pages/ApplicationDetails.tsx @@ -13,10 +13,11 @@ import { Gavel, } from 'tabler-icons-react' import CommitteBanner from '../components/CommitteeBanner' +import NTNUICopyButton from '../components/NTNUICopyButton' import StatusInput from '../components/StatusInput' import { getApplication } from '../services/Applications' import { getUserCommittees, IRoleInCommittee } from '../services/Committees' -import { IApplication, IStatus } from '../types/types' +import { IApplication, IPopulatedStatus } from '../types/types' import { REACT_APP_MAIN_BOARD_ID } from '../utils/constants' interface IStatusesStyleProps { @@ -135,7 +136,12 @@ const useStyles = createStyles( p: { overflow: 'hidden', textOverflow: 'ellipsis', + display: 'flex', color: theme.colors.ntnui_blue[9], + button: { + display: 'flex', + flexDirection: 'column', + }, a: { color: theme.colors.ntnui_blue[9], textDecoration: 'none', @@ -270,11 +276,13 @@ function ApplicationDetailPage() { } interface IStatusWithRelevancy { - status: IStatus + status: IPopulatedStatus isRelevant: boolean } - function statusByRelevancy(statuses: IStatus[]): IStatusWithRelevancy[] { + function statusByRelevancy( + statuses: IPopulatedStatus[] + ): IStatusWithRelevancy[] { const isUserInElectionCommittee = userCommittees.some( (roleInCommittee: IRoleInCommittee) => { return roleInCommittee.committee.slug === 'valgkomiteen' @@ -360,7 +368,10 @@ function ApplicationDetailPage() { {isLoading || !application ? ( ) : ( - {application.email} + <> + {application.email} + + )}

@@ -383,7 +394,9 @@ function ApplicationDetailPage() { {isLoading || !application ? ( ) : ( - statusByRelevancy(application.statuses).map((statusRel, index) => ( + statusByRelevancy( + application.statuses as unknown as IPopulatedStatus[] + ).map((statusRel, index) => (

- Søknadstekst til Hovedstyret + Søknadstekst til Introstyret

{!application.main_board_text.length ? ( Ingen søknadstekst diff --git a/frontend/src/pages/ApplicationOverview.tsx b/frontend/src/pages/ApplicationOverview.tsx index 15cbb653..d5e101ca 100644 --- a/frontend/src/pages/ApplicationOverview.tsx +++ b/frontend/src/pages/ApplicationOverview.tsx @@ -1,10 +1,13 @@ import { createStyles, Loader, Pagination } from '@mantine/core' -import { useEffect, useState } from 'react' +import { createContext, useEffect, useState } from 'react' import ApplicationList from '../components/ApplicationList' import Filter from '../components/FilterSearch' import { IApplication } from '../types/types' import { getApplications } from '../services/Applications' import { useNavigate } from 'react-router-dom' +import useStickyState from '../utils/sessionstorage' +import { getUserCommittees, IRoleInCommittee } from '../services/User' +import { REACT_APP_ELECTION_COMMITTEE_ID } from '../utils/constants' const useStyles = createStyles((theme) => ({ overview: { @@ -18,9 +21,6 @@ const useStyles = createStyles((theme) => ({ fontSize: 'small', width: '100%', }, - '@media (min-width: 500px)': { - width: '80%', - }, }, pagination: { margin: '1rem auto 1rem auto', @@ -41,18 +41,60 @@ const useStyles = createStyles((theme) => ({ }, }, })) +export const UserContext = createContext({ + userRoleInCommittees: [], + isInElectionCommittee: false, +}) + +export const FilterContext = createContext({ + chosenCommittees: [], +}) + +interface IFilterContext { + chosenCommittees: number[] +} +interface IUserContext { + userRoleInCommittees: IRoleInCommittee[] + isInElectionCommittee: boolean +} function ApplicationOverview() { - const [currentPage, setCurrentPage] = useState(1) + const [currentPage, setCurrentPage] = useStickyState(1, 'page') const [numberOfPages, setNumberOfPages] = useState(1) const [isLoading, setIsLoading] = useState(false) const [applications, setApplications] = useState([]) - const [filters, setFilters] = useState('sort=date_desc') + const [filters, setFilters] = useStickyState('sort=date_desc', 'filters') + const [chosenCommittees, setChosenCommittees] = useStickyState( + [], + 'chosenCommittees' + ) + const [sort, setSort] = useStickyState('date_desc', 'sort') + const [status, setStatus] = useStickyState('', 'status') + const [nameSearch, setNameSearch] = useStickyState('', 'nameSearch') + + const [userRoleInCommittees, setUserRoleInCommittees] = useState< + IRoleInCommittee[] + >([]) let navigate = useNavigate() const { classes } = useStyles() + useEffect(() => { + const userCommitteesRes = async () => { + try { + const userCommitteesRes = await getUserCommittees() + setUserRoleInCommittees(userCommitteesRes) + } catch (error: any) { + setIsLoading(false) + if (error.response.status !== 200) { + navigate('/login') + } + } + } + userCommitteesRes() + }, []) + useEffect(() => { setIsLoading(true) const getApplicationsAsync = async () => { @@ -75,11 +117,33 @@ function ApplicationOverview() { return (

Søknadsoversikt

- - {applications.length ? ( - - ) : isLoading ? ( + + {isLoading ? ( + ) : applications.length ? ( + + roleInCommittee.committee._id === REACT_APP_ELECTION_COMMITTEE_ID + ), + }} + > + + + + ) : ( No applications found )} diff --git a/frontend/src/types/types.tsx b/frontend/src/types/types.tsx index a90bdbfb..7ede4b6c 100644 --- a/frontend/src/types/types.tsx +++ b/frontend/src/types/types.tsx @@ -1,6 +1,14 @@ import { StatusTypes } from '../utils/enums' export interface IStatus { + _id: string + value: StatusTypes + set_by: string | null + committee: number + updated_date: Date +} + +export interface IPopulatedStatus { _id: string value: StatusTypes set_by: string | null diff --git a/frontend/src/utils/constants.ts b/frontend/src/utils/constants.ts index ee56c7a3..91fb2fac 100644 --- a/frontend/src/utils/constants.ts +++ b/frontend/src/utils/constants.ts @@ -1,2 +1,5 @@ export const REACT_APP_MAIN_BOARD_ID = Number(process.env.REACT_APP_MAIN_BOARD_ID) || 52 + +export const REACT_APP_ELECTION_COMMITTEE_ID = + Number(process.env.REACT_APP_ELECTION_COMMITTEE_ID) || 53 diff --git a/frontend/src/utils/sessionstorage.ts b/frontend/src/utils/sessionstorage.ts new file mode 100644 index 00000000..b8d67231 --- /dev/null +++ b/frontend/src/utils/sessionstorage.ts @@ -0,0 +1,17 @@ +import { useEffect, useState } from 'react' + +function useStickyState(defaultValue: any, key: string) { + const [value, setValue] = useState(() => { + const stickyValue = window.sessionStorage.getItem(key) + if (stickyValue !== null) { + return JSON.parse(stickyValue) + } + return defaultValue + }) + useEffect(() => { + window.sessionStorage.setItem(key, JSON.stringify(value)) + }, [key, value]) + return [value, setValue] +} + +export default useStickyState