Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issues/1425 get data from ladok #399

Merged
merged 5 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .env.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
KURS_PM_DATA_API_KEY=[Available in Azure KeyVault]
KURSPLAN_API_KEY=[Available in Azure KeyVault]

REDIS_URI=[Available in Azure KeyVault]
REDIS_URI=[Available in Azure KeyVault]

# Ladok Mellanlager connection
LADOK_AUTH_CLIENT_SECRET=[Available in Azure KeyVault]
LADOK_OCP_APIM_SUBSCRIPTION_KEY=[Available in Azure KeyVault]
13 changes: 13 additions & 0 deletions config/serverSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,19 @@ module.exports = {
kursplanApi: unpackNodeApiConfig('KURSPLAN_API_URI', devKursplanApi),
},

// TODO(Ladok-POC): Replace devDefaults and add values to ref/prod.parameters.json when final mellanlager is deployed
ladokMellanlagerApi: {
clientId: getEnv('LADOK_AUTH_CLIENT_ID', devDefaults('fc1c0e6e-c17b-4b1c-9e34-003ca528740f')),
clientSecret: getEnv('LADOK_AUTH_CLIENT_SECRET', null),
tokenUrl: getEnv(
'LADOK_AUTH_TOKEN_URL',
devDefaults('https://login.microsoftonline.com/acd7f330-d613-48d9-85f2-258b1ac4a015/oauth2/v2.0/token')
),
scope: getEnv('LADOK_AUTH_SCOPE', devDefaults('api://97fe6696-a7b2-4f7f-adce-726426e35c1c/.default')),
baseUrl: getEnv('LADOK_BASE_URL', devDefaults('https://apim-mellanlagring2.azure-api.net')),
ocpApimSupscriptionKey: getEnv('LADOK_OCP_APIM_SUBSCRIPTION_KEY', null),
},

// koppsApi: unpackKOPPSConfig('KOPPS_URI', devKoppsApi),
koppsApi: unpackNodeApiConfig('KOPPS_URI', devKoppsApi),

Expand Down
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"kth-node-i18n": "^1.0.18",
"kth-node-redis": "^3.3.0",
"kth-style": "^10.3.0",
"om-kursen-ladok-client": "file:../studadm-om-kursen-packages/packages/om-kursen-ladok-client",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.12.0",
Expand Down
11 changes: 2 additions & 9 deletions public/js/app/pages/AboutCourseMemo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -217,18 +217,11 @@ function AboutCourseMemo({ mockKursPmDataApi = false, mockMixKoppsApi = false })

const [webContext] = useWebContext()

const {
allTypeMemos,
memoDatas,
courseCode,
language: userLangAbbr,
userLanguageIndex,
allRoundsFromKopps,
} = webContext
const { allTypeMemos, memoDatas, courseCode, language: userLangAbbr, userLanguageIndex, allRoundInfos } = webContext

const isThisTest = !!mockKursPmDataApi

const [allRounds, setAllRounds] = useState(allRoundsFromKopps)
const [allRounds, setAllRounds] = useState(allRoundInfos)

const webAndPdfMiniMemos = isThisTest ? mockKursPmDataApi : allTypeMemos
const allRoundsMockOrReal = isThisTest ? mockMixKoppsApi : allRounds
Expand Down
23 changes: 23 additions & 0 deletions server/controllers/helperFunctions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const createRoundInfos = ladokRounds => {
return ladokRounds.map(ladokRound => {
const { forstaUndervisningsdatum, sistaUndervisningsdatum, utbildningstillfalleskod, kortnamn, startperiod } =
ladokRound
return {
round: {
firstTuitionDate: forstaUndervisningsdatum.date,
lastTuitionDate: sistaUndervisningsdatum.date,
startWeek: forstaUndervisningsdatum,
endWeek: sistaUndervisningsdatum,
applicationCode: utbildningstillfalleskod,
shortName: kortnamn,
startTerm: {
term: startperiod.inDigits,
},
},
}
})
}

module.exports = {
createRoundInfos,
}
45 changes: 22 additions & 23 deletions server/controllers/memoCtrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const serverPaths = require('../server').getPaths()
const { browser, server: serverConfig } = require('../configuration')
const { getMemoDataById, getMemoVersion, getMiniMemosPdfAndWeb } = require('../kursPmDataApi')
const { getDetailedInformation, getCourseRoundTerms } = require('../koppsApi')
const { getLadokCourseData, getActiveCourseRoundsByCourseCodeAndFromTerm } = require('../ladokApi')
const { createBreadcrumbs } = require('../utils/breadcrumbUtil')
const { getServerSideFunctions } = require('../utils/serverSideRendering')
const { createServerSideContext } = require('../ssr-context/createServerSideContext')
Expand All @@ -21,6 +22,7 @@ const {
} = require('./memoCtrlHelpers')
const { getLastYearsTerm, extractTerm } = require('../utils/term')
const { redirectToAboutCourseConfig } = require('../utils/helpers')
const { createRoundInfos } = require('./helperFunctions')

const locales = { sv, en }

Expand Down Expand Up @@ -200,19 +202,17 @@ async function getContent(req, res, next) {

let fromTerm = semester ?? extractTerm(courseCode, finalMemoEndPoint)

const {
courseMainSubjects,
recruitmentText,
title,
credits,
creditUnitAbbr,
infoContactName,
examiners,
roundInfos,
} = await getDetailedInformation(courseCode, languagesContext.memoLanguage, fromTerm)
const { title, credits, creditUnitAbbr } = await getLadokCourseData(courseCode, responseLanguage)
const ladokRounds = await getActiveCourseRoundsByCourseCodeAndFromTerm(courseCode, fromTerm, responseLanguage)
const { infoContactName, examiners } = await getDetailedInformation(
courseCode,
languagesContext.memoLanguage,
fromTerm
)

const roundInfos = createRoundInfos(ladokRounds)

const courseContext = {
courseMainSubjects,
title,
credits,
creditUnitAbbr,
Expand Down Expand Up @@ -330,11 +330,10 @@ async function getOldContent(req, res, next) {
memoDatas: [],
}

const { courseMainSubjects, recruitmentText, title, credits, creditUnitAbbr, infoContactName, examiners } =
await getDetailedInformation(courseCode, languagesContext.memoLanguage)
const { title, credits, creditUnitAbbr } = await getLadokCourseData(courseCode)
const { infoContactName, examiners } = await getDetailedInformation(courseCode, languagesContext.memoLanguage)

const courseContext = {
courseMainSubjects,
title,
credits,
creditUnitAbbr,
Expand Down Expand Up @@ -416,11 +415,12 @@ async function getAboutContent(req, res, next) {

const fromTerm = getLastYearsTerm()

const { title, credits, creditUnitAbbr, infoContactName, examiners, roundInfos } = await getDetailedInformation(
courseCode,
responseLanguage,
fromTerm
)
const { title, credits, creditUnitAbbr } = await getLadokCourseData(courseCode, responseLanguage)
const ladokRounds = await getActiveCourseRoundsByCourseCodeAndFromTerm(courseCode, fromTerm, responseLanguage)
const { infoContactName, examiners } = await getDetailedInformation(courseCode, responseLanguage, fromTerm)

const roundInfos = createRoundInfos(ladokRounds)

webContext.title = title
webContext.credits = credits
webContext.creditUnitAbbr = creditUnitAbbr
Expand All @@ -429,7 +429,7 @@ async function getAboutContent(req, res, next) {

webContext.memoDatas = enrichMemoDatasWithOutdatedFlag(rawMemos, roundInfos)
webContext.allTypeMemos = await getMiniMemosPdfAndWeb(courseCode)
webContext.allRoundsFromKopps = await _getAllRoundsWithApplicationCodes(roundInfos)
webContext.allRoundInfos = await _getAllRoundsWithApplicationCodes(roundInfos)

// TODO: Proper language constant
const shortDescription = (responseLanguage === 'sv' ? 'Om kursen ' : 'About course ') + courseCode
Expand Down Expand Up @@ -532,12 +532,11 @@ async function _getAllRoundsWithApplicationCodes(roundInfos) {
const allRounds = []
roundInfos.map(roundInfo => {
const { round } = roundInfo
const { firstTuitionDate, lastTuitionDate, startTerm, applicationCodes } = round
const { firstTuitionDate, lastTuitionDate, startTerm, applicationCode } = round
const { term } = startTerm
if (isDateWithInCurrentOrFutureSemester(firstTuitionDate, lastTuitionDate)) {
round.term = term
const { applicationCode = '' } = applicationCodes[0]
round.applicationCode = applicationCode
round.applicationCode = applicationCode || ''
delete round.applicationCodes
allRounds.push(round)
}
Expand Down
1 change: 1 addition & 0 deletions server/controllers/memoCtrlHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ async function findMatchingRound(memo, roundInfos) {

function lookForMatchingRoundInRoundInfos(semester, memoApplicationCodes, roundInfos) {
const matchingRoundInfo = roundInfos.find(({ round: { applicationCodes } }) => {
if (!applicationCodes) return false
const hasMatchingTermAndApplicationCode = applicationCodes.some(({ applicationCode, term }) => {
return term === semester && memoApplicationCodes.includes(applicationCode)
})
Expand Down
19 changes: 2 additions & 17 deletions server/koppsApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,10 @@ async function getDetailedInformation(courseCode, language, fromTerm) {
try {
const res = await client.getAsync({ uri, useCache: true })
if (res.body) {
const { mainSubjects, course, examiners, roundInfos } = res.body
const isCreditNotStandard =
course &&
course.credits &&
course.credits.toString().indexOf('.') < 0 &&
course.credits.toString().indexOf(',') < 0
const { examiners } = res.body
return {
courseMainSubjects: mainSubjects && mainSubjects.length > 0 ? mainSubjects.join(', ') : '',
recruitmentText: course && course.recruitmentText ? course.recruitmentText : '',
title: course && course.title ? course.title : '',
credits: isCreditNotStandard ? course.credits + '.0' : course.credits || '',
creditUnitAbbr: course && course.creditUnitAbbr ? course.creditUnitAbbr : '',
infoContactName: course && course.infoContactName ? course.infoContactName : '',
infoContactName: '',
examiners: createPersonHtml(examiners),
roundInfos: roundInfos || [],
}
}

Expand All @@ -83,8 +72,6 @@ async function getDetailedInformation(courseCode, language, fromTerm) {
language
)
return {
courseMainSubjects: '',
recruitmentText: '',
title: '',
credits: '',
creditUnitAbbr: '',
Expand All @@ -94,8 +81,6 @@ async function getDetailedInformation(courseCode, language, fromTerm) {
} catch (err) {
log.error('Kopps is not available', err)
return {
courseMainSubjects: '',
recruitmentText: '',
title: '',
credits: '',
creditUnitAbbr: '',
Expand Down
36 changes: 36 additions & 0 deletions server/ladokApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use strict'

const { createApiClient } = require('om-kursen-ladok-client')
const serverConfig = require('./configuration').server

async function getLadokCourseData(courseCode, lang) {
const client = createApiClient(serverConfig.ladokMellanlagerApi)
const course = await client.getLatestCourseVersion(courseCode, lang)
const {
benamning: ladokCourseTitle,
omfattning: ladokCourseCredits,
utbildningstyp: { creditsUnitCode: ladokCreditUnitAbbr },
} = course

const isCreditNotStandard =
ladokCourseCredits &&
ladokCourseCredits.toString().indexOf('.') < 0 &&
ladokCourseCredits.toString().indexOf(',') < 0

return {
title: ladokCourseTitle ?? '',
credits: isCreditNotStandard ? ladokCourseCredits + '.0' : ladokCourseCredits || '',
creditUnitAbbr: ladokCreditUnitAbbr ?? '',
}
}

async function getActiveCourseRoundsByCourseCodeAndFromTerm(courseCode, fromTerm, lang) {
const client = createApiClient(serverConfig.ladokMellanlagerApi)
const rounds = await client.getActiveCourseRoundsFromTerm(courseCode, fromTerm, lang)
return rounds
}

module.exports = {
getLadokCourseData,
getActiveCourseRoundsByCourseCodeAndFromTerm,
}
1 change: 0 additions & 1 deletion server/ssr-context/createServerSideContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ function createServerSideContext() {
const context = {
browserConfig: {},
courseCode: '',
courseMainSubjects: '',
language: 'sv',
memoData: {},
memoDatas: [],
Expand Down
3 changes: 0 additions & 3 deletions test/mock-api/responses.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ module.exports = {
titleOther: 'Algebra and Geometry',
cancelled: false,
deactivated: false,
recruitmentText:
'<p>Algebra och geometri &#228;r en grundl&#228;ggande kurs i linj&#228;r algebra med vektorgeometri. Ett centralt begrepp i kursen &#228;r linj&#228;ritet som ligger till grund f&#246;r stora delar av anv&#228;ndningen av matematik inom s&#229;v&#228;l naturvetenskap som inom ingenj&#246;rstill&#228;mpningar.</p>',
credits: 7.5,
creditUnitLabel: 'Högskolepoäng',
creditUnitAbbr: 'hp',
Expand Down Expand Up @@ -1118,7 +1116,6 @@ module.exports = {
},
},
],
mainSubjects: ['Matematik', 'Teknik'],
examinationSets: {
20072: {
startingTerm: {
Expand Down