From 22200fa079fefe77cbf49a1fe76d7319542fae76 Mon Sep 17 00:00:00 2001 From: albinagu <47886428+albinagu@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:33:41 +0000 Subject: [PATCH 01/15] fix(inheritance-report): efs danarbu tweaks (#16944) * fix(inheritance-report): efs danarbu tweaks * file uploads * overview docs * f * cleanup --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../src/components/ShareInput/index.tsx | 7 +++ .../fields/Overview/OverviewAssets/index.tsx | 5 +- .../fields/Overview/OverviewAssets/rows.ts | 51 ------------------- .../fields/Overview/OverviewAssets/types.ts | 2 +- .../fields/OverviewOtherDocuments/index.tsx | 17 +++++++ .../src/fields/ReportFieldsRepeater/index.tsx | 4 +- .../inheritance-report/src/fields/index.ts | 1 + .../src/forms/sections/assets.ts | 2 +- .../src/forms/sections/heirs.ts | 19 +++---- .../sections/prepaidInheritance/heirs.ts | 1 + .../sections/prepaidInheritance/overview.ts | 16 +++--- 11 files changed, 45 insertions(+), 80 deletions(-) create mode 100644 libs/application/templates/inheritance-report/src/fields/OverviewOtherDocuments/index.tsx diff --git a/libs/application/templates/inheritance-report/src/components/ShareInput/index.tsx b/libs/application/templates/inheritance-report/src/components/ShareInput/index.tsx index 41c1a6c38e95..ec84cdf5994c 100644 --- a/libs/application/templates/inheritance-report/src/components/ShareInput/index.tsx +++ b/libs/application/templates/inheritance-report/src/components/ShareInput/index.tsx @@ -156,6 +156,13 @@ export const ShareInput = ({ const validInput = percentageRegex.test(val) const numberValue = valueToNumber(val, ',') + + // allow percentage with up to 4 digits after a decimal point + const regex4dec = /^(\d+(\.\d{0,4})?)?$/ + if (!regex4dec.test(val.replace(',', '.'))) { + return + } + const isRemoving = len < prevLen.current prevLen.current = len diff --git a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/index.tsx b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/index.tsx index 021c0afc6024..e00c9255592a 100644 --- a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/index.tsx +++ b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/index.tsx @@ -11,7 +11,6 @@ import { FC, Fragment } from 'react' import { m } from '../../../lib/messages' import { getBankAccountsDataRow, - getClaimsDataRow, getGunsDataRow, getInventoryDataRow, getMoneyDataRow, @@ -109,14 +108,12 @@ export const OverviewAssets: FC> = ({ }) // Claims - const claimsDataRow = getClaimsDataRow(answers) const claimsDataTotal = formatCurrency( String(getValueViaPath(answers, 'assets.claims.total')) ?? '', ) sections.push({ title: m.claimsTitle, - data: claimsDataRow, total: claimsDataTotal, totalTitle: m.totalValue, }) @@ -175,7 +172,7 @@ export const OverviewAssets: FC> = ({ {formatMessage(title)} {showTotalFirst && totalRow} - {data.map((row, index) => ( + {data?.map((row, index) => ( ))} {!showTotalFirst && totalRow} diff --git a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/rows.ts b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/rows.ts index 9e52fa24bc07..7be77ebc83c2 100644 --- a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/rows.ts +++ b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/rows.ts @@ -146,38 +146,6 @@ export const getInventoryDataRow = (answers: FormValue): RowType[] => { ] } -export const getClaimsDataRow = (answers: FormValue): RowType[] => { - const values = (answers.assets as unknown as EstateAssets)?.claims?.data - - const data = (values ?? []).map((item) => { - const propertyValuation = roundedValueToNumber(item.propertyValuation) - - const items: RowItemsType = [ - { - title: m.claimsAmount, - value: formatCurrency(String(valueToNumber(item.value))), - }, - ] - - const deceasedShare = valueToNumber(item.deceasedShare ?? '0') - - if (hasYes(item.deceasedShareEnabled)) { - items.push({ - title: m.deceasedShare, - value: `${String(deceasedShare)}%`, - }) - } - - return { - title: item.description, - value: formatCurrency(String(propertyValuation)), - items, - } - }) - - return data -} - export const getStocksDataRow = (answers: FormValue): RowType[] => { const values = (answers.assets as unknown as EstateAssets)?.stocks?.data @@ -289,26 +257,7 @@ export const getOtherAssetsDataRow = (answers: FormValue): RowType[] => { export const getMoneyDataRow = (answers: FormValue): RowType[] => { const values = (answers.assets as unknown as EstateAssets)?.money - const items: RowItemsType = [] - - const deceasedShare = valueToNumber(values?.deceasedShare ?? '0') - - if (values?.info) { - items.push({ - title: m.moneyText, - value: values?.info, - type: 'info', - }) - } - - if (hasYes(values?.deceasedShareEnabled)) { - items.push({ - title: m.deceasedShare, - value: `${String(deceasedShare)}%`, - }) - } - return [ { title: diff --git a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/types.ts b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/types.ts index 74c2beb377d2..2579df688f18 100644 --- a/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/types.ts +++ b/libs/application/templates/inheritance-report/src/fields/Overview/OverviewAssets/types.ts @@ -2,7 +2,7 @@ import { MessageDescriptor } from 'react-intl' export type SectionType = { title: MessageDescriptor | string - data: RowType[] + data?: RowType[] total?: string totalTitle?: MessageDescriptor | string showTotalFirst?: boolean diff --git a/libs/application/templates/inheritance-report/src/fields/OverviewOtherDocuments/index.tsx b/libs/application/templates/inheritance-report/src/fields/OverviewOtherDocuments/index.tsx new file mode 100644 index 000000000000..341e1a8dafcc --- /dev/null +++ b/libs/application/templates/inheritance-report/src/fields/OverviewOtherDocuments/index.tsx @@ -0,0 +1,17 @@ +import { getValueViaPath } from '@island.is/application/core' +import { FieldBaseProps } from '@island.is/application/types' +import { Text } from '@island.is/island-ui/core' +import { FC } from 'react' + +export const OverviewOtherDocuments: FC< + React.PropsWithChildren +> = ({ application }) => { + const { answers } = application + const files = getValueViaPath<{ key: string; name: string }[]>( + answers, + 'heirsAdditionalInfoFilesOtherDocuments', + ) + return files?.map((file) => {file.name}) +} + +export default OverviewOtherDocuments diff --git a/libs/application/templates/inheritance-report/src/fields/ReportFieldsRepeater/index.tsx b/libs/application/templates/inheritance-report/src/fields/ReportFieldsRepeater/index.tsx index 88ba53971318..7529b650832a 100644 --- a/libs/application/templates/inheritance-report/src/fields/ReportFieldsRepeater/index.tsx +++ b/libs/application/templates/inheritance-report/src/fields/ReportFieldsRepeater/index.tsx @@ -153,8 +153,8 @@ export const ReportFieldsRepeater: FC< const faceValue = stockValues?.amount const rateOfExchange = stockValues?.exchangeRateOrInterest - const a = faceValue?.replace(/[^\d.]/g, '') || explicitAVal - const b = rateOfExchange?.replace(/[^\d.]/g, '') || explicitBVal + const a = faceValue?.replace(',', '.') || explicitAVal + const b = rateOfExchange?.replace(',', '.') || explicitBVal const aVal = parseFloat(a) const bVal = parseFloat(b) diff --git a/libs/application/templates/inheritance-report/src/fields/index.ts b/libs/application/templates/inheritance-report/src/fields/index.ts index 61b6498cd211..a96297d0e039 100644 --- a/libs/application/templates/inheritance-report/src/fields/index.ts +++ b/libs/application/templates/inheritance-report/src/fields/index.ts @@ -15,3 +15,4 @@ export { CalculateShare } from './CalculateShare' export { OverviewAssets } from './Overview/OverviewAssets' export { OverviewDebts } from './Overview/OverviewDebts' export { ShareInput } from '../components/ShareInput' +export { OverviewOtherDocuments } from './OverviewOtherDocuments' diff --git a/libs/application/templates/inheritance-report/src/forms/sections/assets.ts b/libs/application/templates/inheritance-report/src/forms/sections/assets.ts index 7946cf6e67aa..0bebecb2ae92 100644 --- a/libs/application/templates/inheritance-report/src/forms/sections/assets.ts +++ b/libs/application/templates/inheritance-report/src/forms/sections/assets.ts @@ -502,7 +502,7 @@ export const assets = buildSection({ { title: m.stocksRateOfChange, id: 'exchangeRateOrInterest', - type: 'number', + type: 'currency', required: true, }, { diff --git a/libs/application/templates/inheritance-report/src/forms/sections/heirs.ts b/libs/application/templates/inheritance-report/src/forms/sections/heirs.ts index ae58219582d3..fe96962a63e4 100644 --- a/libs/application/templates/inheritance-report/src/forms/sections/heirs.ts +++ b/libs/application/templates/inheritance-report/src/forms/sections/heirs.ts @@ -174,9 +174,9 @@ export const heirs = buildSection({ id: 'heirsAdditionalInfoPrivateTransferFiles', uploadAccept: '.pdf, .doc, .docx, .jpg, .jpeg, .png, .xls, .xlsx', uploadDescription: m.uploadPrivateTransferDescription, - uploadMultiple: false, title: '', uploadHeader: '', + uploadMultiple: false, }), buildDescriptionField({ id: 'heirsAdditionalInfoFilesOtherDocumentsTitle', @@ -192,6 +192,7 @@ export const heirs = buildSection({ uploadDescription: m.uploadOtherDocumentsDescription, title: '', uploadHeader: '', + uploadMultiple: true, }), ], }), @@ -383,18 +384,14 @@ export const heirs = buildSection({ }), buildDescriptionField({ id: 'heirs_space6', - title: '', + title: m.fileUploadOtherDocuments, + titleVariant: 'h5', space: 'gutter', }), - buildKeyValueField({ - label: m.fileUploadOtherDocuments, - value: ({ answers }) => { - const files = getValueViaPath( - answers, - 'heirsAdditionalInfoFilesOtherDocuments', - ) - return files.map((file: any) => file.name).join(', ') - }, + buildCustomField({ + title: '', + id: 'otherDocs', + component: 'OverviewOtherDocuments', }), buildDescriptionField({ id: 'heirs_space7', diff --git a/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/heirs.ts b/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/heirs.ts index af810a90beb5..8403cdfb24e6 100644 --- a/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/heirs.ts +++ b/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/heirs.ts @@ -112,6 +112,7 @@ export const prePaidHeirs = buildSection({ uploadDescription: m.fileUploadOtherDocumentsPrePaidDescription, title: '', uploadHeader: '', + uploadMultiple: true, }), ], }), diff --git a/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/overview.ts b/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/overview.ts index 7ef3122938c0..e24ac9a5c7fc 100644 --- a/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/overview.ts +++ b/libs/application/templates/inheritance-report/src/forms/sections/prepaidInheritance/overview.ts @@ -153,18 +153,14 @@ export const prepaidOverview = buildSubSection({ }), buildDescriptionField({ id: 'heirs_space5', - title: '', + title: m.fileUploadOtherDocumentsPrePaid, + titleVariant: 'h3', space: 'gutter', }), - buildKeyValueField({ - label: m.fileUploadOtherDocumentsPrePaid, - value: ({ answers }) => { - const files = getValueViaPath( - answers, - 'heirsAdditionalInfoFilesOtherDocuments', - ) - return files.map((file: any) => file.name).join(', ') - }, + buildCustomField({ + title: '', + id: 'otherDocs', + component: 'OverviewOtherDocuments', }), buildCustomField({ title: '', From 869bce37d77f790d35ff5d707940ef2537944b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=BAnar=20Vestmann?= <43557895+RunarVestmann@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:47:28 +0000 Subject: [PATCH 02/15] feat(web): WHODAS calculator (#16947) * WIP * Use dynamic text * Add translation * Add progress meter * Only scroll when not initially rendering * Update id * Style links --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../MarkdownText/MarkdownText.css.ts | 11 + .../connected/WHODAS/Calculator.css.ts | 9 + .../connected/WHODAS/Calculator.strings.ts | 115 +++++++ .../connected/WHODAS/Calculator.tsx | 318 ++++++++++++++++++ apps/web/utils/richText.tsx | 4 + 5 files changed, 457 insertions(+) create mode 100644 apps/web/components/connected/WHODAS/Calculator.css.ts create mode 100644 apps/web/components/connected/WHODAS/Calculator.strings.ts create mode 100644 apps/web/components/connected/WHODAS/Calculator.tsx diff --git a/apps/web/components/Organization/MarkdownText/MarkdownText.css.ts b/apps/web/components/Organization/MarkdownText/MarkdownText.css.ts index e9ea7962a7cd..5f759495007a 100644 --- a/apps/web/components/Organization/MarkdownText/MarkdownText.css.ts +++ b/apps/web/components/Organization/MarkdownText/MarkdownText.css.ts @@ -1,7 +1,18 @@ import { globalStyle, style } from '@vanilla-extract/css' +import { theme } from '@island.is/island-ui/theme' + export const markdownText = style({}) globalStyle(`${markdownText} ul`, { paddingTop: 16, }) + +globalStyle(`${markdownText} a`, { + color: theme.color.blue400, + textDecoration: 'underline', +}) + +globalStyle(`${markdownText} a:hover`, { + color: theme.color.blueberry400, +}) diff --git a/apps/web/components/connected/WHODAS/Calculator.css.ts b/apps/web/components/connected/WHODAS/Calculator.css.ts new file mode 100644 index 000000000000..c98463701223 --- /dev/null +++ b/apps/web/components/connected/WHODAS/Calculator.css.ts @@ -0,0 +1,9 @@ +import { style } from '@vanilla-extract/css' + +import { theme } from '@island.is/island-ui/theme' + +export const breakdownRowContainer = style({ + display: 'grid', + gridTemplateColumns: '180px 1fr', + gap: theme.spacing[5], +}) diff --git a/apps/web/components/connected/WHODAS/Calculator.strings.ts b/apps/web/components/connected/WHODAS/Calculator.strings.ts new file mode 100644 index 000000000000..d1b82b8593f5 --- /dev/null +++ b/apps/web/components/connected/WHODAS/Calculator.strings.ts @@ -0,0 +1,115 @@ +import { defineMessages } from 'react-intl' + +export const m = { + form: defineMessages({ + previousStep: { + id: 'web.whodas.calculator:form.previousStep', + defaultMessage: 'Fyrra skref', + description: 'Fyrra skref', + }, + nextStep: { + id: 'web.whodas.calculator:form.nextStep', + defaultMessage: 'Næsta skref', + description: 'Næsta skref', + }, + seeResults: { + id: 'web.whodas.calculator:form.seeResults', + defaultMessage: 'Senda inn svör', + description: 'Senda inn svör', + }, + progress: { + id: 'web.whodas.calculator:form.progress', + defaultMessage: 'Skref {stepIndex} af {stepCount}', + description: 'Skref {stepIndex} af {stepCount}', + }, + }), + answerLabel: defineMessages({ + '0': { + id: 'web.whodas.calculator:form.answerLabel0', + defaultMessage: 'Ekkert erfitt', + description: 'Ekkert erfitt', + }, + '1': { + id: 'web.whodas.calculator:form.answerLabel1', + defaultMessage: 'Svolítið erfitt', + description: 'Svolítið erfitt', + }, + '2': { + id: 'web.whodas.calculator:form.answerLabel2', + defaultMessage: 'Nokkuð erfitt', + description: 'Nokkuð erfitt', + }, + '3': { + id: 'web.whodas.calculator:form.answerLabel3', + defaultMessage: 'Talsvert erfitt', + description: 'Talsvert erfitt', + }, + '4': { + id: 'web.whodas.calculator:form.answerLabel4', + defaultMessage: 'Mjög erfitt eða gekk ekki', + description: 'Mjög erfitt eða gekk ekki', + }, + }), + results: defineMessages({ + mainHeading: { + id: 'web.whodas.calculator:form.mainHeading', + defaultMessage: 'Niðurstaða mats á færni', + description: 'Niðurstaða mats á færni', + }, + print: { + id: 'web.whodas.calculator:form.print', + defaultMessage: 'Prenta', + description: 'Prenta', + }, + scoreHeading: { + id: 'web.whodas.calculator:form.scoreHeading', + defaultMessage: 'Heildarstig', + description: 'Heildarstig', + }, + firstBracketScoreText: { + id: 'web.whodas.calculator:form.firstBracketScoreText', + defaultMessage: '0 til 16,9 stig', + description: 'Lítil skerðing á færni - "Score" texti', + }, + secondBracketScoreText: { + id: 'web.whodas.calculator:form.secondBracketScoreText', + defaultMessage: '17 til 100 stig', + description: 'Talsverð skerðing á færni - "Score" texti', + }, + firstBracketInterpretationText: { + id: 'web.whodas.calculator:form.firstBracketInterpretationText', + defaultMessage: 'Lítil skerðing á færni', + description: 'Lítil skerðing á færni - Túlkun', + }, + secondBracketInterpretationText: { + id: 'web.whodas.calculator:form.secondBracketInterpretationText', + defaultMessage: 'Talsverð færniskerðing', + description: 'Talsverð færniskerðing - Túlkun', + }, + firstBracketAdviceText: { + id: 'web.whodas.calculator:form.firstBracketAdviceText#markdown', + defaultMessage: 'Mælum með að skoða hvað er í boði í þínu nærsamfélagi.', + description: 'Lítil skerðing á færni - Ráð', + }, + secondBracketAdviceText: { + id: 'web.whodas.calculator:form.secondBracketAdviceText#markdown', + defaultMessage: 'Vert er að sækja um heimaþjónustu í þínu sveitarfélagi.', + description: 'Talsverð færniskerðing - Ráð', + }, + interpretationHeading: { + id: 'web.whodas.calculator:form.interpretationHeading', + defaultMessage: 'Túlkun', + description: 'Túlkun', + }, + adviceHeading: { + id: 'web.whodas.calculator:form.adviceHeading', + defaultMessage: 'Ráðleggingar', + description: 'Ráðleggingar', + }, + breakdownHeading: { + id: 'web.whodas.calculator:form.breakdownHeading', + defaultMessage: 'Sundurliðun á niðurstöðum', + description: 'Sundurliðun á niðurstöðum', + }, + }), +} diff --git a/apps/web/components/connected/WHODAS/Calculator.tsx b/apps/web/components/connected/WHODAS/Calculator.tsx new file mode 100644 index 000000000000..ee3592b173c1 --- /dev/null +++ b/apps/web/components/connected/WHODAS/Calculator.tsx @@ -0,0 +1,318 @@ +import { + type Dispatch, + type SetStateAction, + useEffect, + useRef, + useState, +} from 'react' +import { useIntl } from 'react-intl' + +import { + Box, + Bullet, + BulletList, + Button, + Inline, + ProgressMeter, + RadioButton, + Stack, + Text, +} from '@island.is/island-ui/core' +import { ConnectedComponent } from '@island.is/web/graphql/schema' +import { useDateUtils } from '@island.is/web/i18n/useDateUtils' + +import { MarkdownText } from '../../Organization' +import { m } from './Calculator.strings' +import * as styles from './Calculator.css' + +interface Question { + question: string + answerOptions: { + score: number + }[] +} + +interface Step { + title: string + description: string + questions: Question[] +} + +interface CheckboxState { + steps: { + title: string + questions: { + selectedAnswerIndex: number + answerScore: number + }[] + }[] +} + +interface WHODASFormProps { + step: Step + stepIndex: number + state: CheckboxState + setState: Dispatch> +} + +const WHODASForm = ({ step, stepIndex, state, setState }: WHODASFormProps) => { + const formState = state.steps[stepIndex] + const { formatMessage } = useIntl() + return ( + + + + {step.title} + + {step.description} + + + {step.questions.map(({ question, answerOptions }, questionIndex) => { + const questionState = formState.questions[questionIndex] + return ( + + + {question} + + + {answerOptions.map((option, answerIndex) => { + const id = `${step.title}-${questionIndex}-${answerIndex}` + + if (answerIndex > 3) { + return null + } + + const label = formatMessage( + m.answerLabel[ + String(answerIndex) as keyof typeof m.answerLabel + ], + ) + return ( + { + questionState.selectedAnswerIndex = answerIndex + questionState.answerScore = option.score + setState((prevState) => ({ ...prevState })) + }} + /> + ) + })} + + + ) + })} + + + ) +} + +interface WHODASResultsProps { + results: { + steps: (Pick & { scoreForStep: number })[] + } + bracket: 1 | 2 +} + +const WHODASResults = ({ results, bracket }: WHODASResultsProps) => { + const { format } = useDateUtils() + const date = format(new Date(), 'do MMMM yyyy') + + const { formatMessage } = useIntl() + + return ( + + + + {formatMessage(m.results.mainHeading)} + + + + {date} + + + {formatMessage(m.results.scoreHeading)} + + + + {formatMessage( + bracket === 1 + ? m.results.firstBracketScoreText + : m.results.secondBracketScoreText, + )} + + + + + + {formatMessage(m.results.interpretationHeading)} + + + {formatMessage( + bracket === 1 + ? m.results.firstBracketInterpretationText + : m.results.secondBracketInterpretationText, + )} + + + + + + {formatMessage(m.results.adviceHeading)} + + + {formatMessage( + bracket === 1 + ? m.results.firstBracketAdviceText + : m.results.secondBracketAdviceText, + )} + + + + {bracket !== 1 && ( + + + {formatMessage(m.results.breakdownHeading)} + + + {results.steps.map((step) => ( + + + {step.title} + {step.scoreForStep} + + + ))} + + + )} + + ) +} + +interface WHODASCalculatorProps { + slice: ConnectedComponent +} + +export const WHODASCalculator = ({ slice }: WHODASCalculatorProps) => { + const [stepIndex, setStepIndex] = useState(0) + const formRef = useRef(null) + const steps = (slice.json?.steps ?? []) as Step[] + const initialRender = useRef(true) + + const step = steps[stepIndex] + const showResults = stepIndex >= steps.length + + const { formatMessage } = useIntl() + + const [state, setState] = useState({ + steps: steps.map(({ title, description, questions }) => ({ + title, + description, + questions: questions.map(() => ({ + selectedAnswerIndex: 0, + answerScore: 0, + })), + })), + }) + + useEffect(() => { + if (initialRender.current) { + initialRender.current = false + return + } + window.scrollTo({ + behavior: 'smooth', + top: formRef.current?.offsetTop ?? 0, + }) + }, [stepIndex]) + + if (showResults) { + let totalScore = 0 + const results: WHODASResultsProps['results'] = { + steps: [], + } + for (const stateStep of state.steps) { + let score = 0 + for (const question of stateStep.questions) { + score += question.answerScore + } + results.steps.push({ ...stateStep, scoreForStep: score }) + totalScore += score + } + return ( + + ) + } + + return ( + + + + + + {formatMessage(m.form.progress, { + stepIndex: stepIndex + 1, + stepCount: steps.length, + })} + + + + + + + + {stepIndex > 0 && ( + + )} + + + + ) +} diff --git a/apps/web/utils/richText.tsx b/apps/web/utils/richText.tsx index 41c1b857d440..e0456a2f12ab 100644 --- a/apps/web/utils/richText.tsx +++ b/apps/web/utils/richText.tsx @@ -88,6 +88,7 @@ import HousingBenefitCalculator from '../components/connected/HousingBenefitCalc import JourneymanList from '../components/connected/syslumenn/TableLists/JourneymanList/JourneymanList' import ProfessionRights from '../components/connected/syslumenn/TableLists/ProfessionRights/ProfessionRights' import { UmsCostOfLivingCalculator } from '../components/connected/UmbodsmadurSkuldara' +import { WHODASCalculator } from '../components/connected/WHODAS/Calculator' import FeaturedEvents from '../components/FeaturedEvents/FeaturedEvents' import FeaturedSupportQNAs from '../components/FeaturedSupportQNAs/FeaturedSupportQNAs' import { EmbedSlice } from '../components/Organization/Slice/EmbedSlice/EmbedSlice' @@ -199,6 +200,9 @@ export const webRenderConnectedComponent = ( ) break + case 'WHODAS/Calculator': + connectedComponent = + break default: connectedComponent = renderConnectedComponent(slice) } From 29bb191aa44ee50b3ea4b8da79a28fedf77d0623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Thu, 21 Nov 2024 11:32:02 +0000 Subject: [PATCH 03/15] fix(web-grants): change to only fund url (#16969) Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- libs/cms/src/lib/generated/contentfulTypes.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/cms/src/lib/generated/contentfulTypes.d.ts b/libs/cms/src/lib/generated/contentfulTypes.d.ts index 1391d3119346..5107c1cfa6ef 100644 --- a/libs/cms/src/lib/generated/contentfulTypes.d.ts +++ b/libs/cms/src/lib/generated/contentfulTypes.d.ts @@ -1555,7 +1555,7 @@ export interface IFundFields { fundTitle: string /** Link */ - fundLink?: IArticle | IOrganizationSubpage | ILinkUrl | undefined + fundLink?: ILinkUrl | undefined /** Featured Image */ fundFeaturedImage: Asset From be1824e1bb9c09b5cf61988f996c2acd7eeac2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9tur=20Neisti=20Erlingsson?= Date: Thu, 21 Nov 2024 12:30:39 +0000 Subject: [PATCH 04/15] chore: Update helm dependencies (#16975) --- infra/helm/Chart.lock | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/infra/helm/Chart.lock b/infra/helm/Chart.lock index 477c293f5ef4..18eb45050564 100644 --- a/infra/helm/Chart.lock +++ b/infra/helm/Chart.lock @@ -56,9 +56,6 @@ dependencies: - name: api-template repository: file://libs/api-template version: 0.0.1 -- name: api-template - repository: file://libs/api-template - version: 0.0.1 - name: cronjob-template repository: file://libs/cronjob-template version: 0.0.1 @@ -110,11 +107,17 @@ dependencies: - name: api-template repository: file://libs/api-template version: 0.0.1 -- name: cronjob-template - repository: file://libs/cronjob-template +- name: api-template + repository: file://libs/api-template + version: 0.0.1 +- name: api-template + repository: file://libs/api-template + version: 0.0.1 +- name: api-template + repository: file://libs/api-template version: 0.0.1 - name: api-template repository: file://libs/api-template version: 0.0.1 -digest: sha256:d282af5c4270985ea9ca1ecb9f8bfb5c96f72ac30aade68f34b7e7f898da180b -generated: "2023-09-18T13:08:28.226991116Z" +digest: sha256:4a1d366fb8ddc48a860688bd2137eacb9693056372824c634eb3d40d32797247 +generated: "2024-11-21T11:44:06.23465238Z" From a9f7f9100c6c8710e9655ca4d3352a9cbb3f028a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9tur=20Neisti=20Erlingsson?= Date: Thu, 21 Nov 2024 13:43:07 +0000 Subject: [PATCH 05/15] chore: Sync helm templates (#16983) --- .../libs/api-template/templates/_helpers.tpl | 20 +-- .../api-template/templates/deployment.yaml | 15 +- .../helm/libs/api-template/templates/pdb.yaml | 22 +++ .../cronjob-template/templates/_helpers.tpl | 32 +++-- .../cronjob-template/templates/cronjob.yaml | 13 ++ infra/helm/libs/cronjob-template/values.yaml | 1 + infra/helm/libs/job-template/.helmignore | 23 +++ infra/helm/libs/job-template/Chart.yaml | 6 + .../libs/job-template/templates/_helpers.tpl | 67 +++++++++ .../helm/libs/job-template/templates/job.yaml | 133 ++++++++++++++++++ .../helm/libs/job-template/templates/pvc.yaml | 22 +++ .../libs/job-template/templates/secrets.yaml | 18 +++ .../templates/serviceaccount.yaml | 17 +++ infra/helm/libs/job-template/values.yaml | 33 +++++ 14 files changed, 399 insertions(+), 23 deletions(-) create mode 100644 infra/helm/libs/api-template/templates/pdb.yaml create mode 100644 infra/helm/libs/job-template/.helmignore create mode 100644 infra/helm/libs/job-template/Chart.yaml create mode 100644 infra/helm/libs/job-template/templates/_helpers.tpl create mode 100644 infra/helm/libs/job-template/templates/job.yaml create mode 100644 infra/helm/libs/job-template/templates/pvc.yaml create mode 100644 infra/helm/libs/job-template/templates/secrets.yaml create mode 100644 infra/helm/libs/job-template/templates/serviceaccount.yaml create mode 100644 infra/helm/libs/job-template/values.yaml diff --git a/infra/helm/libs/api-template/templates/_helpers.tpl b/infra/helm/libs/api-template/templates/_helpers.tpl index de39c681ba35..7e2591422b25 100644 --- a/infra/helm/libs/api-template/templates/_helpers.tpl +++ b/infra/helm/libs/api-template/templates/_helpers.tpl @@ -3,7 +3,11 @@ Expand the name of the chart. */}} {{- define "api-template.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- if .Values.name -}} + {{- .Values.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} {{- end -}} {{/* @@ -13,14 +17,14 @@ If release name contains chart name it will be used as a full name. */}} {{- define "api-template.fullname" -}} {{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} {{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} + {{- $name := .Values.name | default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} + {{- end -}} {{- end -}} {{- end -}} diff --git a/infra/helm/libs/api-template/templates/deployment.yaml b/infra/helm/libs/api-template/templates/deployment.yaml index 81812e13abdd..e1ff2f6676a3 100644 --- a/infra/helm/libs/api-template/templates/deployment.yaml +++ b/infra/helm/libs/api-template/templates/deployment.yaml @@ -55,6 +55,15 @@ spec: {{- toYaml .Values.annotations | nindent 8 }} {{- end }} spec: + {{- if .Values.armBetaEnrolled }} + tolerations: + - key: "arm" + operator: "Equal" + value: "true" + effect: "NoSchedule" + nodeSelector: + nodetype: "arm" + {{- end }} {{- with .Values.imagePullSecrets }} imagePullSecrets: {{- toYaml . | nindent 8 }} @@ -175,6 +184,8 @@ spec: fieldPath: metadata.labels['tags.datadoghq.com/version'] - name: DD_LOGS_INJECTION value: "true" + - name: DD_DBM_PROPAGATION_MODE + value: "full" - name: DD_AGENT_HOST valueFrom: fieldRef: @@ -183,6 +194,8 @@ spec: value: "true" - name: DD_DOGSTATSD_NON_LOCAL_TRAFFIC value: "true" + - name: DD_PROFILING_ENABLED + value: "false" - name: DD_APM_REPLACE_TAGS value: '[ { @@ -232,4 +245,4 @@ spec: claimName: {{.name}} {{- end }} {{- end }} - {{- end }} \ No newline at end of file + {{- end }} diff --git a/infra/helm/libs/api-template/templates/pdb.yaml b/infra/helm/libs/api-template/templates/pdb.yaml new file mode 100644 index 000000000000..3b3534fd8eb4 --- /dev/null +++ b/infra/helm/libs/api-template/templates/pdb.yaml @@ -0,0 +1,22 @@ +{{- $labels := include "api-template.labels" . -}} +{{- $namespace := $.Values.namespace -}} +{{- $serviceName := include "api-template.name" . -}} +{{- if .Values.enabled }} +{{- if .Values.podDisruptionBudget }} +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: {{ $serviceName }}-pdb + namespace: {{ $namespace }} +spec: +{{- if hasKey .Values.podDisruptionBudget "minAvailable" }} + minAvailable: {{ .Values.podDisruptionBudget.minAvailable }} +{{- end }} +{{- if hasKey .Values.podDisruptionBudget "maxUnavailable" }} + maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }} +{{- end }} + selector: + matchLabels: + app.kubernetes.io/name: {{ $serviceName }} +{{- end }} +{{- end }} diff --git a/infra/helm/libs/cronjob-template/templates/_helpers.tpl b/infra/helm/libs/cronjob-template/templates/_helpers.tpl index 924d9da8880e..00e92e0d4f65 100644 --- a/infra/helm/libs/cronjob-template/templates/_helpers.tpl +++ b/infra/helm/libs/cronjob-template/templates/_helpers.tpl @@ -3,8 +3,12 @@ Expand the name of the chart. */}} {{- define "cronjob-template.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} +{{- if .Values.name -}} + {{- .Values.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} {{/* Create a default fully qualified app name. @@ -12,23 +16,23 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this If release name contains chart name it will be used as a full name. */}} {{- define "cronjob-template.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} +{{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- $name := .Values.name | default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} + {{- end -}} +{{- end -}} +{{- end -}} {{/* Create chart name and version as used by the chart label. */}} {{- define "cronjob-template.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- end }} {{/* diff --git a/infra/helm/libs/cronjob-template/templates/cronjob.yaml b/infra/helm/libs/cronjob-template/templates/cronjob.yaml index ef17498097e4..a3892dce80ce 100644 --- a/infra/helm/libs/cronjob-template/templates/cronjob.yaml +++ b/infra/helm/libs/cronjob-template/templates/cronjob.yaml @@ -18,8 +18,21 @@ spec: failedJobsHistoryLimit: {{ .Values.failedJobsHistoryLimit | default 1 }} successfulJobsHistoryLimit: {{ .Values.successfulJobsHistoryLimit | default 3}} schedule: {{ .Values.schedule | quote }} + {{- if .Values.startingDeadlineSeconds }} + startingDeadlineSeconds: {{ .Values.startingDeadlineSeconds }} + {{- end }} jobTemplate: spec: + {{- if .Values.armBetaEnrolled }} + tolerations: + - key: "arm" + operator: "Equal" + value: "true" + effect: "NoSchedule" + nodeSelector: + nodetype: "arm" + {{- end }} + ttlSecondsAfterFinished: {{ .Values.ttlSecondsAfterFinished | default 600 }} template: metadata: annotations: diff --git a/infra/helm/libs/cronjob-template/values.yaml b/infra/helm/libs/cronjob-template/values.yaml index 4727071401ae..19c15349ef2f 100644 --- a/infra/helm/libs/cronjob-template/values.yaml +++ b/infra/helm/libs/cronjob-template/values.yaml @@ -9,6 +9,7 @@ serviceAccount: image: repository: defaultmissing schedule: '0 8 * * 1' +startingDeadlineSeconds: null resources: # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little diff --git a/infra/helm/libs/job-template/.helmignore b/infra/helm/libs/job-template/.helmignore new file mode 100644 index 000000000000..0e8a0eb36f4c --- /dev/null +++ b/infra/helm/libs/job-template/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/infra/helm/libs/job-template/Chart.yaml b/infra/helm/libs/job-template/Chart.yaml new file mode 100644 index 000000000000..bcd9e96aec26 --- /dev/null +++ b/infra/helm/libs/job-template/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: job-template +description: A Helm chart template for Kubernetes jobs +type: application +version: 0.0.1 +appVersion: 1.16.0 diff --git a/infra/helm/libs/job-template/templates/_helpers.tpl b/infra/helm/libs/job-template/templates/_helpers.tpl new file mode 100644 index 000000000000..d9b22069a578 --- /dev/null +++ b/infra/helm/libs/job-template/templates/_helpers.tpl @@ -0,0 +1,67 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "job-template.name" -}} +{{- if .Values.name -}} + {{- .Values.name | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "job-template.fullname" -}} +{{- if .Values.fullnameOverride -}} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} + {{- $name := .Values.name | default .Chart.Name .Values.nameOverride -}} + {{- if contains $name .Release.Name -}} + {{- .Release.Name | trunc 63 | trimSuffix "-" -}} + {{- else -}} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} + {{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "job-template.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "job-template.labels" -}} +helm.sh/chart: {{ include "job-template.chart" . }} +{{ include "job-template.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "job-template.selectorLabels" -}} +app.kubernetes.io/name: {{ include "job-template.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "job-template.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "job-template.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/infra/helm/libs/job-template/templates/job.yaml b/infra/helm/libs/job-template/templates/job.yaml new file mode 100644 index 000000000000..303f3e362798 --- /dev/null +++ b/infra/helm/libs/job-template/templates/job.yaml @@ -0,0 +1,133 @@ +{{- if .Values.enabled }} +{{- $fullName := include "job-template.fullname" . -}} +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ .Chart.Name }}-{{ now | unixEpoch }}" + {{- if $.Values.namespace }} + namespace: {{ $.Values.namespace }} + {{- end }} + labels: + {{- include "job-template.labels" . | nindent 4 }} + chart: "{{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}" + tags.datadoghq.com/env: {{ .Values.global.env.name }} + tags.datadoghq.com/service: {{ include "job-template.name" . }} + tags.datadoghq.com/version: {{ .Values.image.tag | default .Values.global.image.tag }} +spec: + ttlSecondsAfterFinished: {{ .Values.ttlSecondsAfterFinished | default 600 }} + template: + metadata: + annotations: + linkerd.io/inject: disabled + ad.datadoghq.com/{{ .Chart.Name }}.logs: >- + [{ + "log_processing_rules": [{ + "type": "mask_sequences", + "name": "mask_national_ids", + "replace_placeholder": "--MASKED--", + "pattern" : "\\b(?:[89]\\d{3}|(?:[012]\\d|3[01])(?:0\\d|1[012]))\\d\\d-?\\d{4}\\b" + }] + }] + labels: + {{- include "job-template.labels" . | nindent 8 }} + chart: "{{ $.Chart.Name }}-{{ $.Chart.Version | replace "+" "_" }}" + tags.datadoghq.com/env: {{ .Values.global.env.name }} + tags.datadoghq.com/service: {{ include "job-template.name" . }} + tags.datadoghq.com/version: {{ .Values.image.tag | default .Values.global.image.tag }} + spec: + {{- if .Values.armBetaEnrolled }} + tolerations: + - key: "arm" + operator: "Equal" + value: "true" + effect: "NoSchedule" + nodeSelector: + nodetype: "arm" + {{- end }} + serviceAccountName: {{ include "job-template.serviceAccountName" $ }} + securityContext: + {{- toYaml $.Values.podSecurityContext | nindent 12 }} + containers: + - image: "{{ $.Values.image.repository }}:{{ $.Values.image.tag | default .Values.global.image.tag }}" + name: {{ .Chart.Name }} + securityContext: + {{- toYaml $.Values.securityContext | nindent 14 }} + volumeMounts: + {{- if not (empty .Values.pvcs) }} + {{- range .Values.pvcs}} + - mountPath: {{ .mountPath }} + name: {{ .name }} + {{- end}} + {{- end }} + {{- if not (empty .Values.files) }} + - name: config-volume + mountPath: /etc/config + {{- end }} + env: + {{- range $key, $value := .Values.global.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- range $key, $value := .Values.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- range $key, $value := .Values.secrets }} + - name: {{ $key }} + valueFrom: + secretKeyRef: + name: {{ $fullName }} + key: {{ $key }} + {{- end }} + - name: APP_VERSION + value: {{ .Values.image.tag | default .Values.global.image.tag }} + - name: DD_ENV + valueFrom: + fieldRef: + fieldPath: metadata.labels['tags.datadoghq.com/env'] + - name: DD_SERVICE + valueFrom: + fieldRef: + fieldPath: metadata.labels['tags.datadoghq.com/service'] + - name: DD_VERSION + valueFrom: + fieldRef: + fieldPath: metadata.labels['tags.datadoghq.com/version'] + - name: DD_LOGS_INJECTION + value: "true" + - name: DD_AGENT_HOST + valueFrom: + fieldRef: + fieldPath: status.hostIP + - name: DD_APM_REPLACE_TAGS + value: '[ + { + "name": "*", + "pattern": "\\b(?:[89]\\d{3}|(?:[012]\\d|3[01])(?:0\\d|1[012]))\\d\\d-?\\d{4}\\b", + "repl": "--MASKED--" + }]' + {{- with .Values.command }} + command: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.args }} + args: {{ toYaml . | nindent 12 }} + {{- end }} + resources: + {{ toYaml $.Values.resources | nindent 14 }} + {{- if or (not (empty .Values.files)) (not (empty .Values.pvcs)) }} + volumes: + {{- end }} + {{- if not (empty .Values.files) }} + - name: config-volume + configMap: + name: {{ include "job-template.name" . }} + {{- end }} + {{- if not (empty .Values.pvcs) }} + {{- range .Values.pvcs }} + - name: {{ .name }} + persistentVolumeClaim: + claimName: {{ .name }} + {{- end }} + {{- end }} + restartPolicy: {{ .Values.restartPolicy | default "Never" }} +{{- end }} diff --git a/infra/helm/libs/job-template/templates/pvc.yaml b/infra/helm/libs/job-template/templates/pvc.yaml new file mode 100644 index 000000000000..93e9a6d60f89 --- /dev/null +++ b/infra/helm/libs/job-template/templates/pvc.yaml @@ -0,0 +1,22 @@ +{{- $labels := include "cronjob-template.labels" . -}} +{{- $namespace := $.Values.namespace -}} +{{- if .Values.enabled }} +{{- range .Values.pvcs }} +{{- if not .useExisting }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + {{- $labels | nindent 4 }} + name: {{ .name }} + namespace: {{ $namespace }} +spec: + accessModes: + - {{ .accessModes }} + resources: + requests: + storage: {{ .size }} + storageClassName: {{ .storageClass }} +{{- end }} +{{- end }} +{{- end }} diff --git a/infra/helm/libs/job-template/templates/secrets.yaml b/infra/helm/libs/job-template/templates/secrets.yaml new file mode 100644 index 000000000000..7436eaa53a19 --- /dev/null +++ b/infra/helm/libs/job-template/templates/secrets.yaml @@ -0,0 +1,18 @@ +{{- if .Values.enabled }} +{{- if not (empty .Values.secrets) }} +apiVersion: kubernetes-client.io/v1 +kind: ExternalSecret +metadata: + {{- if .Values.namespace }} + namespace: {{ .Values.namespace }} + {{- end }} + name: {{ include "cronjob-template.fullname" . }} +spec: + backendType: systemManager + data: + {{- range $key, $value := .Values.secrets }} + - name: {{ $key }} + key: {{ $value | quote }} + {{- end }} +{{- end }} +{{- end }} diff --git a/infra/helm/libs/job-template/templates/serviceaccount.yaml b/infra/helm/libs/job-template/templates/serviceaccount.yaml new file mode 100644 index 000000000000..81bee6cbaacf --- /dev/null +++ b/infra/helm/libs/job-template/templates/serviceaccount.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "cronjob-template.serviceAccountName" . }} + {{- if .Values.namespace }} + namespace: {{ .Values.namespace }} + {{- end }} + labels: + {{- include "cronjob-template.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end -}} +{{- end }} diff --git a/infra/helm/libs/job-template/values.yaml b/infra/helm/libs/job-template/values.yaml new file mode 100644 index 000000000000..4fbfb611fb19 --- /dev/null +++ b/infra/helm/libs/job-template/values.yaml @@ -0,0 +1,33 @@ +global: + env: + name: dev + image: + tag: latest +enabled: false +serviceAccount: + create: true +image: + repository: defaultmissing +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 400m ## Research + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi +podSecurityContext: + {} + # fsGroup: 2000 + +securityContext: + {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: runner From 6054c6695687f1f01b238394ec827ff2d28493c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Thu, 21 Nov 2024 14:02:02 +0000 Subject: [PATCH 06/15] fix(web-grants): Tag descriptions (#16941) * feat: init * fix: layout --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- apps/web/screens/Grants/Grant/Grant.tsx | 2 +- apps/web/screens/Grants/Home/GrantsHome.tsx | 13 ++++++- .../screens/Grants/Home/mapTagToMessageId.ts | 38 +++++++++++++++++++ apps/web/screens/Grants/messages.ts | 36 ++++++++++++++++++ 4 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 apps/web/screens/Grants/Home/mapTagToMessageId.ts diff --git a/apps/web/screens/Grants/Grant/Grant.tsx b/apps/web/screens/Grants/Grant/Grant.tsx index d3f4caf7aa06..fbbc9f66dae2 100644 --- a/apps/web/screens/Grants/Grant/Grant.tsx +++ b/apps/web/screens/Grants/Grant/Grant.tsx @@ -22,6 +22,7 @@ import { } from '@island.is/web/graphql/schema' import { useLinkResolver } from '@island.is/web/hooks' import { withMainLayout } from '@island.is/web/layouts/main' +import { CustomNextError } from '@island.is/web/units/errors' import { webRichText } from '@island.is/web/utils/richText' import { @@ -32,7 +33,6 @@ import SidebarLayout from '../../Layouts/SidebarLayout' import { GET_GRANT_QUERY } from '../../queries' import { m } from '../messages' import { GrantSidebar } from './GrantSidebar' -import { CustomNextError } from '@island.is/web/units/errors' const GrantSinglePage: CustomScreen = ({ grant, locale }) => { const { formatMessage } = useIntl() diff --git a/apps/web/screens/Grants/Home/GrantsHome.tsx b/apps/web/screens/Grants/Home/GrantsHome.tsx index d106bee459fe..8addc3728a94 100644 --- a/apps/web/screens/Grants/Home/GrantsHome.tsx +++ b/apps/web/screens/Grants/Home/GrantsHome.tsx @@ -31,6 +31,11 @@ import { } from '../../CustomPage/CustomPageWrapper' import { GET_GENERIC_TAGS_IN_TAG_GROUPS_QUERY } from '../../queries/GenericTag' import { m } from '../messages' +import { + CATEGORY_TAG_SLUGS, + CategorySlug, + mapTagToMessageId, +} from './mapTagToMessageId' const GrantsHomePage: CustomScreen = ({ categories, @@ -138,7 +143,13 @@ const GrantsHomePage: CustomScreen = ({ ))} diff --git a/apps/web/screens/Grants/Home/mapTagToMessageId.ts b/apps/web/screens/Grants/Home/mapTagToMessageId.ts new file mode 100644 index 000000000000..69b8873a5a76 --- /dev/null +++ b/apps/web/screens/Grants/Home/mapTagToMessageId.ts @@ -0,0 +1,38 @@ +import { m } from '../messages' + +export const CATEGORY_TAG_SLUGS = [ + 'grant-category-business', + 'grant-category-culture-and-arts', + 'grant-category-native', + 'grant-category-research', + 'grant-category-innovation', + 'grant-category-global', + 'grant-category-professional-education', + 'grant-category-education-and-teaching', + 'grant-category-youth-and-sports', +] as const + +export type CategorySlug = typeof CATEGORY_TAG_SLUGS[number] + +export const mapTagToMessageId = (tagSlug: CategorySlug) => { + switch (tagSlug) { + case 'grant-category-business': + return m.home.grantCategoryBusinessDescription + case 'grant-category-culture-and-arts': + return m.home.grantCategoryCultureAndArtsDescription + case 'grant-category-native': + return m.home.grantCategoryNativeDescription + case 'grant-category-research': + return m.home.grantCategoryResearchDescription + case 'grant-category-innovation': + return m.home.grantCategoryInnovationDescription + case 'grant-category-global': + return m.home.grantCategoryGlobalDescription + case 'grant-category-professional-education': + return m.home.grantCategoryProfessionalEducationDescription + case 'grant-category-education-and-teaching': + return m.home.grantCategoryEducationAndTeachingDescription + case 'grant-category-youth-and-sports': + return m.home.grantCategoryYouthAndSportsDescription + } +} diff --git a/apps/web/screens/Grants/messages.ts b/apps/web/screens/Grants/messages.ts index 15a1cf7d595a..08128f8d28ba 100644 --- a/apps/web/screens/Grants/messages.ts +++ b/apps/web/screens/Grants/messages.ts @@ -161,5 +161,41 @@ export const m = { id: 'web.grants:home.allGrants', defaultMessage: 'Allir styrkir', }, + grantCategoryYouthAndSportsDescription: { + id: 'web.grants:home.grantCategoryYouthAndSportsDescription', + defaultMessage: 'Lýsing á æskulýðsstarfi og íþróttum', + }, + grantCategoryEducationAndTeachingDescription: { + id: 'web.grants:home.grantCategoryEducationAndTeachingDescription', + defaultMessage: 'Lýsing á námi og kennslu', + }, + grantCategoryProfessionalEducationDescription: { + id: 'web.grants:home.grantCategoryProfessionalEducationDescription', + defaultMessage: 'Lýsing á starfs- og símenntun', + }, + grantCategoryGlobalDescription: { + id: 'web.grants:home.grantCategoryGlobalDescription', + defaultMessage: 'Lýsing á alþjóðlegum', + }, + grantCategoryInnovationDescription: { + id: 'web.grants:home.grantCategoryInnovationDescription', + defaultMessage: 'Lýsing á nýsköpun', + }, + grantCategoryResearchDescription: { + id: 'web.grants:home.grantCategoryResearchDescription', + defaultMessage: 'Lýsing á rannsóknum', + }, + grantCategoryNativeDescription: { + id: 'web.grants:home.grantCategoryNativeDescription', + defaultMessage: 'Lýsing á innlendu', + }, + grantCategoryCultureAndArtsDescription: { + id: 'web.grants:home.grantCategoryCultureAndArtsDescription', + defaultMessage: 'Lýsing á menningu og list', + }, + grantCategoryBusinessDescription: { + id: 'web.grants:home.grantCategoryBusinessDescription', + defaultMessage: 'Lýsing á atvinnulífi', + }, }), } From ae1a547791b4be49b06b1d262ebd1594d5314d73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9E=C3=B3r=C3=B0ur=20H?= Date: Thu, 21 Nov 2024 14:44:26 +0000 Subject: [PATCH 07/15] fix(services-bff): JSON body limit bff service (#16970) * JSON body limit bff service * Add problem module * Update expected error in spec --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- apps/services/bff/src/app/app.module.ts | 2 ++ .../services/bff/src/app/modules/auth/auth.controller.spec.ts | 4 ++-- apps/services/bff/src/main.ts | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/services/bff/src/app/app.module.ts b/apps/services/bff/src/app/app.module.ts index 923f19224d97..561a14a094a3 100644 --- a/apps/services/bff/src/app/app.module.ts +++ b/apps/services/bff/src/app/app.module.ts @@ -1,5 +1,6 @@ import { ConfigModule } from '@island.is/nest/config' import { Module } from '@nestjs/common' +import { ProblemModule } from '@island.is/nest/problem' import { BffConfig } from './bff.config' import { AuthModule as AppAuthModule } from './modules/auth/auth.module' import { CacheModule } from './modules/cache/cache.module' @@ -18,6 +19,7 @@ import { EnhancedFetchModule } from './modules/enhancedFetch/enhanced-fetch.modu AppAuthModule, ProxyModule, EnhancedFetchModule, + ProblemModule, ], }) export class AppModule {} diff --git a/apps/services/bff/src/app/modules/auth/auth.controller.spec.ts b/apps/services/bff/src/app/modules/auth/auth.controller.spec.ts index ac2b1d951a9d..7d0d4cb14899 100644 --- a/apps/services/bff/src/app/modules/auth/auth.controller.spec.ts +++ b/apps/services/bff/src/app/modules/auth/auth.controller.spec.ts @@ -456,8 +456,8 @@ describe('AuthController', () => { expect(res.status).toEqual(HttpStatus.BAD_REQUEST) // Expect error to be expect(res.body).toMatchObject({ - statusCode: 400, - message: 'No param "logout_token" provided!', + status: 400, + detail: 'No param "logout_token" provided!', }) }) diff --git a/apps/services/bff/src/main.ts b/apps/services/bff/src/main.ts index 2e68f2bcbc6e..4a6cf20067ed 100644 --- a/apps/services/bff/src/main.ts +++ b/apps/services/bff/src/main.ts @@ -9,4 +9,5 @@ bootstrap({ port: environment.port, globalPrefix: `${environment.keyPath}/bff`, healthCheck: true, + jsonBodyLimit: '350kb', }) From 75764d959dc632591572e17fdf165558cfa2d0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Svanhildur=20Einarsd=C3=B3ttir?= <54863023+svanaeinars@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:13:23 +0000 Subject: [PATCH 08/15] chore(tests): Make Jest ignore E2E test files (#16979) Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- jest.preset.js | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.preset.js b/jest.preset.js index 1651c8322bda..91dff7b208d1 100644 --- a/jest.preset.js +++ b/jest.preset.js @@ -6,6 +6,7 @@ const customResolver = path.join(__dirname, 'jest.resolver.js') module.exports = { ...nxPresetRest, testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'], + testPathIgnorePatterns: ['/apps/.*/e2e'], resolver: customResolver, moduleFileExtensions: ['ts', 'js', 'html'], coverageReporters: ['json'], From 05f9988cdc3389fc20ab926f31fac45e9b645cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gunnlaugur=20Gu=C3=B0mundsson?= <34029342+GunnlaugurG@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:53:33 +0000 Subject: [PATCH 09/15] feat(auth-admin): Add automaticDelegationGrant to ids admin (#16864) * automatic declegation grant to ids (all layers) * chore: nx format:write update dirty files --------- Co-authored-by: andes-it Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- apps/services/auth/admin-api/project.json | 6 +++++ .../src/lib/scope/dto/patch-scope.input.ts | 3 +++ .../admin/dto/admin-patch-scope.dto.ts | 7 ++++++ .../admin/ids-admin/src/lib/messages.ts | 9 ++++++++ .../Permission/EditPermission.schema.ts | 1 + .../src/screens/Permission/Permission.graphql | 1 + .../components/PermissionAccessControl.tsx | 22 ++++++++++++++++++- 7 files changed, 48 insertions(+), 1 deletion(-) diff --git a/apps/services/auth/admin-api/project.json b/apps/services/auth/admin-api/project.json index ed4e11cf7369..2866faa0019a 100644 --- a/apps/services/auth/admin-api/project.json +++ b/apps/services/auth/admin-api/project.json @@ -42,6 +42,12 @@ }, "outputs": ["{workspaceRoot}/coverage/apps/services/auth/admin-api"] }, + "dev": { + "executor": "nx:run-commands", + "options": { + "command": "yarn start --project services-auth-admin-api" + } + }, "codegen/backend-schema": { "executor": "nx:run-commands", "options": { diff --git a/libs/api/domains/auth-admin/src/lib/scope/dto/patch-scope.input.ts b/libs/api/domains/auth-admin/src/lib/scope/dto/patch-scope.input.ts index 37ae1eea341c..281a9cbd886e 100644 --- a/libs/api/domains/auth-admin/src/lib/scope/dto/patch-scope.input.ts +++ b/libs/api/domains/auth-admin/src/lib/scope/dto/patch-scope.input.ts @@ -47,6 +47,9 @@ export class AdminPatchScopeInput { @Field(() => Boolean, { nullable: true }) isAccessControlled?: boolean + @Field(() => Boolean, { nullable: true }) + automaticDelegationGrant?: boolean + @Field(() => Boolean, { nullable: true, deprecationReason: diff --git a/libs/auth-api-lib/src/lib/resources/admin/dto/admin-patch-scope.dto.ts b/libs/auth-api-lib/src/lib/resources/admin/dto/admin-patch-scope.dto.ts index 11d4df948a9d..f3cc7a556b05 100644 --- a/libs/auth-api-lib/src/lib/resources/admin/dto/admin-patch-scope.dto.ts +++ b/libs/auth-api-lib/src/lib/resources/admin/dto/admin-patch-scope.dto.ts @@ -82,6 +82,13 @@ export class AdminPatchScopeDto { }) isAccessControlled?: boolean + @IsBoolean() + @IsOptional() + @ApiPropertyOptional({ + example: false, + }) + automaticDelegationGrant?: boolean + @IsBoolean() @IsOptional() @ApiPropertyOptional({ diff --git a/libs/portals/admin/ids-admin/src/lib/messages.ts b/libs/portals/admin/ids-admin/src/lib/messages.ts index 4fa97ac192d2..d0e35018cd9f 100644 --- a/libs/portals/admin/ids-admin/src/lib/messages.ts +++ b/libs/portals/admin/ids-admin/src/lib/messages.ts @@ -794,6 +794,15 @@ export const m = defineMessages({ defaultMessage: 'Should the authenticated individual get this scope (uncheck if only delegated users should be allowed).', }, + automaticDelegationGrant: { + id: 'ap.ids-admin:automatic-delegation-grant', + defaultMessage: 'Automatic delegation grant', + }, + automaticDelegationGrantDescription: { + id: 'ap.ids-admin:automatic-delegation-grant-description', + defaultMessage: + 'Should users automatically get this permission when they authenticate with this application', + }, grantToProcuringHolders: { id: 'ap.ids-admin:grant-to-procuring-holders', defaultMessage: 'Companies', diff --git a/libs/portals/admin/ids-admin/src/screens/Permission/EditPermission.schema.ts b/libs/portals/admin/ids-admin/src/screens/Permission/EditPermission.schema.ts index 7ec1bf5f1d77..4986c1769456 100644 --- a/libs/portals/admin/ids-admin/src/screens/Permission/EditPermission.schema.ts +++ b/libs/portals/admin/ids-admin/src/screens/Permission/EditPermission.schema.ts @@ -55,6 +55,7 @@ const accessControlSchema = z .object({ isAccessControlled: booleanCheckbox, grantToAuthenticatedUser: booleanCheckbox, + automaticDelegationGrant: booleanCheckbox, }) .merge(defaultEnvironmentSchema) diff --git a/libs/portals/admin/ids-admin/src/screens/Permission/Permission.graphql b/libs/portals/admin/ids-admin/src/screens/Permission/Permission.graphql index 850249c1358c..7294da4f1c24 100644 --- a/libs/portals/admin/ids-admin/src/screens/Permission/Permission.graphql +++ b/libs/portals/admin/ids-admin/src/screens/Permission/Permission.graphql @@ -23,6 +23,7 @@ fragment AuthAdminScopeEnvironmentFragment on AuthAdminScopeEnvironment { grantToPersonalRepresentatives supportedDelegationTypes + automaticDelegationGrant } query AuthAdminScope($input: ScopeInput!) { diff --git a/libs/portals/admin/ids-admin/src/screens/Permission/components/PermissionAccessControl.tsx b/libs/portals/admin/ids-admin/src/screens/Permission/components/PermissionAccessControl.tsx index c169b659a8dd..53a09599f7f6 100644 --- a/libs/portals/admin/ids-admin/src/screens/Permission/components/PermissionAccessControl.tsx +++ b/libs/portals/admin/ids-admin/src/screens/Permission/components/PermissionAccessControl.tsx @@ -22,14 +22,20 @@ export const PermissionAccessControl = () => { const { formatMessage } = useLocale() const { selectedPermission, permission } = usePermission() const { isSuperAdmin } = useSuperAdmin() - const { isAccessControlled, grantToAuthenticatedUser } = selectedPermission + const { + isAccessControlled, + grantToAuthenticatedUser, + automaticDelegationGrant, + } = selectedPermission const [inputValues, setInputValues] = useEnvironmentState<{ isAccessControlled: boolean grantToAuthenticatedUser: boolean + automaticDelegationGrant: boolean }>({ isAccessControlled, grantToAuthenticatedUser, + automaticDelegationGrant, }) return ( @@ -39,6 +45,7 @@ export const PermissionAccessControl = () => { inSync={checkEnvironmentsSync(permission.environments, [ 'isAccessControlled', 'grantToAuthenticatedUser', + 'automaticDelegationGrant', ])} > @@ -70,6 +77,19 @@ export const PermissionAccessControl = () => { }} {...commonProps} /> + { + setInputValues({ + ...inputValues, + automaticDelegationGrant: e.target.checked, + }) + }} + {...commonProps} + > ) From 6b0e7792cf1e35111ee993292416b213366918d1 Mon Sep 17 00:00:00 2001 From: unakb Date: Thu, 21 Nov 2024 16:36:23 +0000 Subject: [PATCH 10/15] fix(j-s): Whitelist config (#16974) * fix(j-s): Whitelist config * Update baseNotification.service.ts --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../src/app/modules/notification/baseNotification.service.ts | 2 +- .../backend/src/app/modules/notification/notification.config.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/judicial-system/backend/src/app/modules/notification/baseNotification.service.ts b/apps/judicial-system/backend/src/app/modules/notification/baseNotification.service.ts index be1034a1dcb1..82c66351821c 100644 --- a/apps/judicial-system/backend/src/app/modules/notification/baseNotification.service.ts +++ b/apps/judicial-system/backend/src/app/modules/notification/baseNotification.service.ts @@ -89,7 +89,7 @@ export abstract class BaseNotificationService { // We use the first one as the main recipient and the rest as CC let recipients = recipientEmail ? recipientEmail.split(',') : undefined - if (!this.config.production && recipients) { + if (this.config.shouldUseWhitelist && recipients) { recipients = await this.handleWhitelist(recipients) } diff --git a/apps/judicial-system/backend/src/app/modules/notification/notification.config.ts b/apps/judicial-system/backend/src/app/modules/notification/notification.config.ts index f863a518fad2..ba742a4742a6 100644 --- a/apps/judicial-system/backend/src/app/modules/notification/notification.config.ts +++ b/apps/judicial-system/backend/src/app/modules/notification/notification.config.ts @@ -5,6 +5,8 @@ export const notificationModuleConfig = defineConfig({ load: (env) => ({ production: env.optional('NODE_ENV') === 'production', courtOfAppealsId: '4676f08b-aab4-4b4f-a366-697540788088', + shouldUseWhitelist: + env.required('CONTENTFUL_ENVIRONMENT', 'test') !== 'master', email: { fromEmail: env.required('EMAIL_FROM', 'ben10@omnitrix.is'), fromName: env.required('EMAIL_FROM_NAME', 'Réttarvörslugátt'), From 57e6c90f10356e89393e47b81b38d52dcc2e3749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Svanhildur=20Einarsd=C3=B3ttir?= <54863023+svanaeinars@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:06:41 +0000 Subject: [PATCH 11/15] chore(tests): Support more options E2E Playwright config (#16982) * chore(tests): Support more options E2E Playwright config * Fix nested if statement * Small correction --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- libs/testing/e2e/README.md | 16 ++++----- .../e2e/src/lib/config/playwright-config.ts | 36 ++++++++++++++----- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/libs/testing/e2e/README.md b/libs/testing/e2e/README.md index 40fedb39f715..2b25fca2891f 100644 --- a/libs/testing/e2e/README.md +++ b/libs/testing/e2e/README.md @@ -41,7 +41,7 @@ export default playwrightConfig Use the following command structure to run tests for any app: ```bash -yarn e2e +yarn nx e2e ``` ### Useful Playwright Commands and Flags @@ -49,26 +49,26 @@ yarn e2e - **Run with UI Mode**: Launch the tests with a UI to select and debug tests interactively. ```bash - yarn e2e --ui + yarn nx e2e --ui ``` - **Run Tests Without Caching**: Ensure a fresh run of tests without using cached results. ```bash - yarn e2e --skip-nx-cache + yarn nx e2e --skip-nx-cache ``` - **Run Tests with Tags**: Use tags to include or exclude specific tests. ```bash # Run only tests tagged with @fast - yarn e2e --grep @fast + yarn nx e2e --grep @fast # Exclude tests tagged with @fast - yarn e2e --grep-invert @fast + yarn nx e2e --grep-invert @fast # Run tests tagged with either @fast or @slow - yarn e2e --grep "@fast|@slow" + yarn nx e2e --grep "@fast|@slow" ``` - **View the Test Report**: After running tests, use this command to view the generated report: @@ -80,13 +80,13 @@ yarn e2e - **Run Specific Tests**: Use `--grep` to run tests matching a specific pattern: ```bash - yarn e2e --grep "Home Page Test" + yarn nx e2e --grep "Home Page Test" ``` - **Debug Mode**: Run tests in debug mode for better visibility: ```bash - yarn e2e --debug + yarn nx e2e --debug ``` For more details on Playwright commands and flags, refer to the [official documentation](https://playwright.dev/docs/test-cli) diff --git a/libs/testing/e2e/src/lib/config/playwright-config.ts b/libs/testing/e2e/src/lib/config/playwright-config.ts index d888387b0874..f70cff4535eb 100644 --- a/libs/testing/e2e/src/lib/config/playwright-config.ts +++ b/libs/testing/e2e/src/lib/config/playwright-config.ts @@ -3,7 +3,10 @@ import { defineConfig, ReporterDescription } from '@playwright/test' interface PlaywrightConfigParams { webServerUrl: string port?: number - command: string + command?: string + app?: string + dependencies?: string[] + proxies?: boolean cwd?: string timeoutMs?: number } @@ -18,6 +21,9 @@ interface PlaywrightConfigParams { * @param {string} config.command - Command to start the web server. * @param {string} config.cwd - Working directory for the web server command. * @param {number} config.timeoutMs - Timeout in milliseconds for server startup. + * @param {string} config.app - Application to run. + * @param {string[]} config.dependencies - List of dependencies. + * @param {boolean} config.proxies - Whether to use proxies. * * @returns A configuration object for Playwright E2E tests. */ @@ -27,8 +33,25 @@ export const createPlaywrightConfig = ({ command, cwd, timeoutMs = 5 * 60 * 1000, -}: PlaywrightConfigParams) => - defineConfig({ + app, + dependencies = [], + proxies = false, +}: PlaywrightConfigParams) => { + if (!command && !app) { + throw new Error('Either command or app must be specified.') + } + + if (!command) { + command = `yarn infra run-local-env ${app} --print --no-secrets` + if (dependencies.length > 0) { + command += ` --dependencies ${dependencies.join(' ')}` + } + if (proxies) { + command += ' --proxies' + } + } + + return defineConfig({ testDir: 'e2e', fullyParallel: true, forbidOnly: !!process.env.CI, @@ -40,16 +63,10 @@ export const createPlaywrightConfig = ({ : [['dot']]) as ReporterDescription[]), ['html', { open: 'never' }], ], - use: { baseURL: webServerUrl, trace: 'on-first-retry', }, - projects: [ - { name: 'everything', testMatch: 'e2e/**/*.spec.[tj]s' }, - { name: 'smoke', testMatch: 'e2e/smoke/**/*.spec.[tj]s' }, - { name: 'acceptance', testMatch: 'e2e/acceptance/**/*.spec.[tj]s' }, - ], webServer: { stdout: 'pipe', port: port ? port : undefined, @@ -60,3 +77,4 @@ export const createPlaywrightConfig = ({ cwd, }, }) +} From 306e2767332f562d04a87e32839db5c774854c90 Mon Sep 17 00:00:00 2001 From: Kristofer Date: Thu, 21 Nov 2024 17:16:17 +0000 Subject: [PATCH 12/15] chore(ci): Fewer test timouts/cancellations (#16988) * Moderate test timeout increase * Increase e2e timeout --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .github/workflows/pullrequest.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 51e54f62e853..66a7a84c814a 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -178,7 +178,7 @@ jobs: runs-on: ec2-runners container: image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest - timeout-minutes: 35 + timeout-minutes: 45 env: AFFECTED_PROJECTS: ${{ matrix.projects }} MAX_JOBS: 1 @@ -220,7 +220,7 @@ jobs: runs-on: ec2-runners container: image: public.ecr.aws/m3u4c4h9/island-is/actions-runner-public:latest - timeout-minutes: 35 + timeout-minutes: 45 env: AFFECTED_PROJECT: ${{ matrix.projects }} CYPRESS_PROJECT_ID: 4q7jz8 From 57ca74a127e722ddf68a7bdfbd18132f29529201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9E=C3=B3r=C3=B0ur=20H?= Date: Thu, 21 Nov 2024 18:04:56 +0000 Subject: [PATCH 13/15] fix(my-pages): Sanitize sheet name (#16986) * Sanitize sheet name * Update replace and fallback --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../my-pages/assets/src/utils/downloadVehicleOwnedFile.ts | 3 ++- libs/portals/my-pages/core/src/utils/downloadDataFile.ts | 7 +++++-- libs/portals/my-pages/core/src/utils/utils.ts | 7 +++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libs/portals/my-pages/assets/src/utils/downloadVehicleOwnedFile.ts b/libs/portals/my-pages/assets/src/utils/downloadVehicleOwnedFile.ts index 60d0f6da36a2..7e463439780a 100644 --- a/libs/portals/my-pages/assets/src/utils/downloadVehicleOwnedFile.ts +++ b/libs/portals/my-pages/assets/src/utils/downloadVehicleOwnedFile.ts @@ -1,3 +1,4 @@ +import { sanitizeSheetName } from '@island.is/portals/my-pages/core' import XLSX from 'xlsx' const locale = 'is-IS' @@ -45,7 +46,7 @@ export const downloadVehicleOwnedFile = async ( showOperatorVehicles ? header[1] : null, ...(showOperatorVehicles ? data[1] : [['Ekkert fannst']]), ] - const sheetName = name.substring(0, 31) // Max length for a sheet name. + const sheetName = sanitizeSheetName(name) const worksheet: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(sheetData) const workbook: XLSX.WorkBook = { diff --git a/libs/portals/my-pages/core/src/utils/downloadDataFile.ts b/libs/portals/my-pages/core/src/utils/downloadDataFile.ts index c3fecfdad97b..a958254c0f05 100644 --- a/libs/portals/my-pages/core/src/utils/downloadDataFile.ts +++ b/libs/portals/my-pages/core/src/utils/downloadDataFile.ts @@ -1,5 +1,6 @@ import CSVStringify from 'csv-stringify' import XLSX from 'xlsx' +import { sanitizeSheetName } from './utils' export const downloadFile = async ( name: string, @@ -30,8 +31,10 @@ export const downloadFile = async ( } else { const sheetData = [header, ...data] const dateString = new Date().toISOString().split('T')[0] - const fileName = `${name.replace(/\./g, '')} - ${dateString}` - const sheetName = name.substring(0, 31) // Max length for a sheet name. + const fileName = sanitizeSheetName( + `${name.replace(/\./g, '')} - ${dateString}`, + ) + const sheetName = sanitizeSheetName(name) const worksheet: XLSX.WorkSheet = XLSX.utils.aoa_to_sheet(sheetData) const workbook: XLSX.WorkBook = { diff --git a/libs/portals/my-pages/core/src/utils/utils.ts b/libs/portals/my-pages/core/src/utils/utils.ts index 826628f8e405..69855f71d055 100644 --- a/libs/portals/my-pages/core/src/utils/utils.ts +++ b/libs/portals/my-pages/core/src/utils/utils.ts @@ -13,6 +13,13 @@ export const getNameAbbreviation = (name: string) => { return initials } +export const sanitizeSheetName = (sheetName: string) => { + return sheetName + .replace(/[:\\/?*[\]]/g, '_') + .trim() + .substring(0, 31) // Max length for a sheet name. +} + export const tableStyles = { padding: '16px', } From 421f147c38d52e4164b5a9723c273e0a1741803b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Eorkell=20M=C3=A1ni=20=C3=9Eorkelsson?= Date: Fri, 22 Nov 2024 09:29:30 +0000 Subject: [PATCH 14/15] feat(vehicle-mileage): bulk mileage list search'n'filter (#16906) * feat: add search * fix: search works * feat: add filter * feat: add mileage last * fix: add keys * fix: add key again --- .../src/lib/dto/vehiclesListInputV3.ts | 3 + .../src/lib/models/v3/mileageDetails.model.ts | 4 + .../models/v3/mileageRegistration.model.ts | 3 + .../v3/mileageRegistrationHistory.model.ts | 3 - .../src/lib/services/vehicles.service.ts | 40 ++- libs/clients/vehicles/src/clientConfig.json | 303 +++++++++++++++++- .../VehicleBulkMileage.graphql | 7 +- .../VehicleBulkMileage/VehicleBulkMileage.tsx | 183 ++++++++--- .../VehicleBulkMileageRow.tsx | 30 +- .../VehicleBulkMileageTable.tsx | 2 +- .../src/screens/VehicleBulkMileage/types.ts | 7 +- .../VehicleBulkMileageJobDetail.tsx | 31 +- .../VehicleBulkMileageUpload.tsx | 8 +- .../components/IntroWrapper/IntroWrapper.tsx | 7 +- .../OccupationalLicensesDetail.tsx | 93 +++--- 15 files changed, 560 insertions(+), 164 deletions(-) diff --git a/libs/api/domains/vehicles/src/lib/dto/vehiclesListInputV3.ts b/libs/api/domains/vehicles/src/lib/dto/vehiclesListInputV3.ts index f61910fa95b5..a2825d09b61c 100644 --- a/libs/api/domains/vehicles/src/lib/dto/vehiclesListInputV3.ts +++ b/libs/api/domains/vehicles/src/lib/dto/vehiclesListInputV3.ts @@ -8,6 +8,9 @@ export class VehiclesListInputV3 { @Field() page!: number + @Field({ nullable: true }) + filterOnlyRequiredMileageRegistration?: boolean + @Field({ nullable: true }) query?: string } diff --git a/libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts b/libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts index 09053d9e25a0..3375f50c5613 100644 --- a/libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts +++ b/libs/api/domains/vehicles/src/lib/models/v3/mileageDetails.model.ts @@ -1,5 +1,6 @@ import { Field, ObjectType } from '@nestjs/graphql' import { MileageRegistrationHistory } from './mileageRegistrationHistory.model' +import { MileageRegistration } from './mileageRegistration.model' @ObjectType('VehiclesMileageDetails') export class MileageDetails { @@ -9,6 +10,9 @@ export class MileageDetails { @Field({ nullable: true }) requiresMileageRegistration?: boolean + @Field(() => MileageRegistration, { nullable: true }) + lastMileageRegistration?: MileageRegistration + @Field(() => MileageRegistrationHistory, { nullable: true }) mileageRegistrations?: MileageRegistrationHistory } diff --git a/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistration.model.ts b/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistration.model.ts index 1585acb1d381..64ffdb798251 100644 --- a/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistration.model.ts +++ b/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistration.model.ts @@ -10,4 +10,7 @@ export class MileageRegistration { @Field(() => GraphQLISODateTime) date!: Date + + @Field(() => Int, { nullable: true }) + internalId?: number } diff --git a/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistrationHistory.model.ts b/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistrationHistory.model.ts index dde6de0404c5..c7509a7a0750 100644 --- a/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistrationHistory.model.ts +++ b/libs/api/domains/vehicles/src/lib/models/v3/mileageRegistrationHistory.model.ts @@ -6,9 +6,6 @@ export class MileageRegistrationHistory { @Field() vehicleId!: string - @Field(() => MileageRegistration, { nullable: true }) - lastMileageRegistration?: MileageRegistration - @Field(() => [MileageRegistration], { nullable: true }) mileageRegistrationHistory?: Array } diff --git a/libs/api/domains/vehicles/src/lib/services/vehicles.service.ts b/libs/api/domains/vehicles/src/lib/services/vehicles.service.ts index 018749f96b3c..8580eeee81ae 100644 --- a/libs/api/domains/vehicles/src/lib/services/vehicles.service.ts +++ b/libs/api/domains/vehicles/src/lib/services/vehicles.service.ts @@ -46,6 +46,7 @@ import { GetVehicleMileageInput } from '../dto/getVehicleMileageInput' import { MileageRegistrationHistory } from '../models/v3/mileageRegistrationHistory.model' import { VehiclesMileageUpdateError } from '../models/v3/vehicleMileageResponseError.model' import { UpdateResponseError } from '../dto/updateResponseError.dto' +import { MileageRegistration } from '../models/v3/mileageRegistration.model' const ORIGIN_CODE = 'ISLAND.IS' const LOG_CATEGORY = 'vehicle-service' @@ -111,6 +112,7 @@ export class VehiclesService { showCoowned: true, showOperated: true, showOwned: true, + onlyMileageRequiredVehicles: input.filterOnlyRequiredMileageRegistration, page: input.page, pageSize: input.pageSize, permno: input.query @@ -140,6 +142,21 @@ export class VehiclesService { if (!d.permno || !d.regno) { return null } + + let lastMileageRegistration: MileageRegistration | undefined + + if ( + d.latestOriginCode && + d.latestMileage && + d.latestMileageReadDate + ) { + lastMileageRegistration = { + originCode: d.latestOriginCode, + mileage: d.latestMileage, + date: d.latestMileageReadDate, + internalId: d.latestMileageInternalId ?? undefined, + } + } return { vehicleId: d.permno, registrationNumber: d.regno, @@ -147,6 +164,7 @@ export class VehiclesService { type: d.make ?? undefined, color: d.colorName ?? undefined, mileageDetails: { + lastMileageRegistration, canRegisterMileage: d.canRegisterMilage ?? undefined, requiresMileageRegistration: d.requiresMileageRegistration ?? undefined, @@ -377,28 +395,18 @@ export class VehiclesService { permno: input.permno, }) - const [lastRegistration, ...history] = res + const samplePermno = res[0].permno - if (!lastRegistration.permno) { + if (!samplePermno) { return null } return { - vehicleId: lastRegistration.permno, - lastMileageRegistration: - lastRegistration.originCode && - lastRegistration.readDate && - lastRegistration.mileage - ? { - originCode: lastRegistration.originCode, - mileage: lastRegistration.mileage, - date: lastRegistration.readDate, - } - : undefined, - mileageRegistrationHistory: history?.length - ? history + vehicleId: samplePermno, + mileageRegistrationHistory: res?.length + ? res .map((h) => { - if (h.permno !== lastRegistration.permno) { + if (h.permno !== samplePermno) { return null } if (!h.originCode || !h.mileage || !h.readDate) { diff --git a/libs/clients/vehicles/src/clientConfig.json b/libs/clients/vehicles/src/clientConfig.json index 79e3505893e6..fa0d8a9edfcf 100644 --- a/libs/clients/vehicles/src/clientConfig.json +++ b/libs/clients/vehicles/src/clientConfig.json @@ -2,7 +2,7 @@ "openapi": "3.0.1", "info": { "title": "Samgöngustofa", - "description": "Leitar eftir ökutækjum út frá fastanúmeri, skr�ningarnúmeri eða verksmiðjunúmeri - Release-41 : 20240708.1", + "description": "Leitar eftir ökutækjum út frá fastanúmeri, skr�ningarnúmeri eða verksmiðjunúmeri - Release-46 : 20241106.1", "contact": { "name": "Samgongustofa", "url": "https://www.samgongustofa.is/", @@ -503,6 +503,96 @@ ] } }, + "/VehicleHistoryV2": { + "get": { + "tags": ["VehicleSearch"], + "parameters": [ + { + "name": "requestedPersidno", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "showDeregistered", + "in": "query", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "showHistory", + "in": "query", + "schema": { + "type": "boolean", + "default": false + } + }, + { + "name": "dtFrom", + "in": "query", + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "cursor", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "schema": { + "type": "integer", + "format": "int32", + "default": 50 + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AllVehiclesForPersidnoV2" + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + }, + "401": { + "description": "Unauthorized" + }, + "403": { + "description": "Forbidden" + } + }, + "security": [ + { + "OAuth2": ["OAuth2"] + } + ] + } + }, "/CurrentVehicles": { "get": { "tags": ["VehicleSearch"], @@ -1104,6 +1194,190 @@ }, "additionalProperties": false }, + "AllVehiclesForPersidnoV2": { + "type": "object", + "properties": { + "guid": { + "type": "string", + "nullable": true + }, + "persidno": { + "type": "string", + "nullable": true + }, + "fullName": { + "type": "string", + "nullable": true + }, + "address": { + "type": "string", + "nullable": true + }, + "zipCode": { + "type": "string", + "nullable": true + }, + "permno": { + "type": "string", + "nullable": true + }, + "regno": { + "type": "string", + "nullable": true + }, + "startDate": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "endDate": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "operserno": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "mainOper": { + "type": "boolean", + "nullable": true + }, + "ownchserno": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "latestOwnchserno": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "roleCode": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "vehicleRole": { + "type": "string", + "nullable": true + }, + "vin": { + "type": "string", + "nullable": true + }, + "firstRegDate": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "productYear": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "vehicleStatus": { + "type": "string", + "nullable": true + }, + "plateStatus": { + "type": "string", + "nullable": true + }, + "modelYear": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "vehGroupCode": { + "type": "string", + "nullable": true + }, + "otherOwners": { + "type": "boolean", + "nullable": true + }, + "vehGroup": { + "type": "string", + "nullable": true + }, + "buyerPersidno": { + "type": "string", + "nullable": true + }, + "ownerPersidno": { + "type": "string", + "nullable": true + }, + "useGroupCode": { + "type": "string", + "nullable": true + }, + "useGroup": { + "type": "string", + "nullable": true + }, + "importCode": { + "type": "string", + "nullable": true + }, + "fuelCode": { + "type": "string", + "nullable": true + }, + "fuel": { + "type": "string", + "nullable": true + }, + "colorCode": { + "type": "string", + "nullable": true + }, + "color": { + "type": "string", + "nullable": true + }, + "make": { + "type": "string", + "nullable": true + }, + "outOfUse": { + "type": "boolean", + "nullable": true + }, + "termination": { + "type": "string", + "nullable": true + }, + "registrationCode": { + "type": "string", + "nullable": true + }, + "registrationTypeSubCode": { + "type": "string", + "nullable": true + }, + "registrationType": { + "type": "string", + "nullable": true + }, + "deregistered": { + "type": "boolean", + "nullable": true + }, + "isCurrent": { + "type": "boolean", + "nullable": true + }, + "newRegDate": { + "type": "string", + "format": "date-time", + "nullable": true + } + }, + "additionalProperties": false + }, "BasicVehicleInformationAddonsChangeDto": { "type": "object", "properties": { @@ -2768,6 +3042,25 @@ "type": "string", "format": "date-time", "nullable": true + }, + "latestMileageInternalId": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "latestOriginCode": { + "type": "string", + "nullable": true + }, + "latestMileage": { + "type": "integer", + "format": "int32", + "nullable": true + }, + "latestMileageReadDate": { + "type": "string", + "format": "date-time", + "nullable": true } }, "additionalProperties": false @@ -3371,6 +3664,10 @@ "format": "double", "nullable": true }, + "engine": { + "type": "string", + "nullable": true + }, "nextAvailableMileageReadDate": { "type": "string", "format": "date", @@ -3389,10 +3686,6 @@ }, "nullable": true }, - "engine": { - "type": "string", - "nullable": true - }, "allOperatorsAreAnonymous": { "type": "boolean" }, diff --git a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql index 75414f355492..fd57a53a42c6 100644 --- a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql +++ b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.graphql @@ -11,6 +11,9 @@ query vehiclesList($input: VehiclesListInputV3!) { type color mileageDetails { + lastMileageRegistration { + ...mileageRegistration + } canRegisterMileage requiresMileageRegistration } @@ -68,14 +71,12 @@ fragment mileageRegistration on VehiclesMileageRegistration { originCode mileage date + internalId } query vehicleMileageRegistrationHistory($input: GetVehicleMileageInput) { vehiclesMileageRegistrationHistory(input: $input) { vehicleId - lastMileageRegistration { - ...mileageRegistration - } mileageRegistrationHistory { ...mileageRegistration } diff --git a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx index 85fb5453b46f..c2964c3ee81a 100644 --- a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx +++ b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileage.tsx @@ -1,18 +1,30 @@ -import { Stack, Pagination, Text, Inline } from '@island.is/island-ui/core' +import { + Stack, + Box, + Filter, + FilterInput, + Inline, + Checkbox, + Pagination, + Text, +} from '@island.is/island-ui/core' +import debounce from 'lodash/debounce' +import { debounceTime } from '@island.is/shared/constants' import { useLocale, useNamespaces } from '@island.is/localization' import { m, SAMGONGUSTOFA_SLUG, LinkButton, IntroWrapper, + formatDate, } from '@island.is/portals/my-pages/core' import { vehicleMessage as messages, vehicleMessage } from '../../lib/messages' import * as styles from './VehicleBulkMileage.css' -import { useEffect, useState } from 'react' +import { useEffect, useState, useMemo } from 'react' import VehicleBulkMileageTable from './VehicleBulkMileageTable' import { VehicleType } from './types' import { FormProvider, useForm } from 'react-hook-form' -import { useVehiclesListQuery } from './VehicleBulkMileage.generated' +import { useVehiclesListLazyQuery } from './VehicleBulkMileage.generated' import { isDefined } from '@island.is/shared/utils' import { AssetsPaths } from '../../lib/paths' import { Problem } from '@island.is/react-spa/shared' @@ -27,36 +39,84 @@ const VehicleBulkMileage = () => { const [vehicles, setVehicles] = useState>([]) const [page, setPage] = useState(1) const [totalPages, setTotalPages] = useState(1) + const [search, setSearch] = useState() + const [filterValue, setFilterValue] = useState(false) + + const [vehicleListQuery, { data, loading, error, called }] = + useVehiclesListLazyQuery() - const { data, loading, error } = useVehiclesListQuery({ - variables: { - input: { - page, - pageSize: 10, + useEffect(() => { + vehicleListQuery({ + variables: { + input: { + page, + pageSize: 10, + query: undefined, + }, }, - }, - }) + }) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) - const methods = useForm() + const debouncedQuery = useMemo(() => { + return debounce(() => { + vehicleListQuery({ + variables: { + input: { + page, + pageSize: 10, + query: search ?? undefined, + filterOnlyRequiredMileageRegistration: filterValue, + }, + }, + }).then((res) => { + const vehicles: Array = + res.data?.vehiclesListV3?.data + ?.map((v) => { + if (!v.type) { + return null + } + + const lastMileageRegistration = + v.mileageDetails?.lastMileageRegistration && + v.mileageDetails.lastMileageRegistration.date && + v.mileageDetails.lastMileageRegistration.mileage && + v.mileageDetails.lastMileageRegistration.originCode + ? { + date: new Date( + v.mileageDetails.lastMileageRegistration.date, + ), + mileage: v.mileageDetails.lastMileageRegistration.mileage, + origin: + v.mileageDetails.lastMileageRegistration.originCode, + internalId: + v.mileageDetails.lastMileageRegistration.internalId ?? + undefined, + } + : undefined + + return { + vehicleId: v.vehicleId, + vehicleType: v.type, + lastMileageRegistration, + } + }) + .filter(isDefined) ?? [] + setVehicles(vehicles) + setTotalPages(res?.data?.vehiclesListV3?.totalPages || 1) + }) + }, debounceTime.search) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [search, filterValue, page]) useEffect(() => { - if (data?.vehiclesListV3?.data) { - const vehicles: Array = data.vehiclesListV3?.data - .map((v) => { - if (!v.type) { - return null - } - return { - vehicleId: v.vehicleId, - vehicleType: v.type, - lastMileageRegistration: undefined, - } - }) - .filter(isDefined) - setVehicles(vehicles) - setTotalPages(data?.vehiclesListV3?.totalPages || 1) + debouncedQuery() + return () => { + debouncedQuery.cancel() } - }, [data?.vehiclesListV3]) + }, [debouncedQuery]) + + const methods = useForm() return ( @@ -83,22 +143,63 @@ const VehicleBulkMileage = () => { } serviceProviderSlug={SAMGONGUSTOFA_SLUG} serviceProviderTooltip={formatMessage(m.vehiclesTooltip)} + buttonGroup={[ + , + , + ]} > + + { + console.log('clear') + }} + align="left" + reverse + filterInput={ + { + setSearch(search) + }} + name={formatMessage(m.searchLabel)} + placeholder={formatMessage(vehicleMessage.searchForPlate)} + /> + } + > + + + {formatMessage(m.filterBy)} + + setFilterValue(!filterValue)} + /> + + + - - - - {error && !loading && } {!error && ( diff --git a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx index de057a5a71c4..b4661d31d6a4 100644 --- a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx +++ b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageRow.tsx @@ -22,7 +22,6 @@ import { InputController } from '@island.is/shared/form-fields' import * as styles from './VehicleBulkMileage.css' import { displayWithUnit } from '../../utils/displayWithUnit' import { isReadDateToday } from '../../utils/readDate' -import { isDefined } from '@island.is/shared/utils' const ORIGIN_CODE = 'ISLAND.IS' @@ -216,22 +215,6 @@ export const VehicleBulkMileageRow = ({ vehicle }: Props) => { return [[]] } const tableData: Array> = [[]] - if (data?.vehiclesMileageRegistrationHistory?.lastMileageRegistration) { - tableData.push([ - formatDate( - data.vehiclesMileageRegistrationHistory.lastMileageRegistration.date, - ), - data.vehiclesMileageRegistrationHistory.lastMileageRegistration - .originCode, - //'-', - displayWithUnit( - data.vehiclesMileageRegistrationHistory.lastMileageRegistration - .mileage, - 'km', - true, - ), - ]) - } for (const mileageRegistration of data?.vehiclesMileageRegistrationHistory ?.mileageRegistrationHistory ?? []) { if (mileageRegistration) { @@ -258,10 +241,15 @@ export const VehicleBulkMileageRow = ({ vehicle }: Props) => { { value: vehicle.vehicleId, }, - // Until we get the data from the service - /*{ - value: formatDate(vehicle.lastMileageRegistration), - },*/ + { + value: vehicle.lastMileageRegistration?.mileage + ? displayWithUnit( + vehicle.lastMileageRegistration.mileage, + 'km', + true, + ) + : '-', + }, { value: ( diff --git a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx index 5206f451f31a..0cc14273bbe8 100644 --- a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx +++ b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/VehicleBulkMileageTable.tsx @@ -33,7 +33,7 @@ const VehicleBulkMileageTable = ({ vehicles, loading }: Props) => { { value: '', printHidden: true }, { value: formatMessage(vehicleMessage.type) }, { value: formatMessage(vehicleMessage.permno) }, - //{ value: formatMessage(vehicleMessage.lastRegistration) }, + { value: formatMessage(vehicleMessage.lastRegistration) }, { value: formatMessage(vehicleMessage.odometer) }, { value: '', printHidden: true }, ]} diff --git a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/types.ts b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/types.ts index 41da1aa9497c..c2a1195c5370 100644 --- a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/types.ts +++ b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileage/types.ts @@ -1,7 +1,6 @@ export interface VehicleProps { vehicleId: string vehicleType: string - lastMileageRegistration?: Date } export type SubmissionStatus = 'success' | 'error' | 'loading' | 'idle' @@ -13,6 +12,12 @@ export interface Props { export interface VehicleType extends VehicleProps { mileageUploadedFromFile?: number isCurrentlyEditing?: boolean + lastMileageRegistration?: { + date: Date + origin: string + mileage: number + internalId?: number + } registrationHistory?: Array<{ date: Date origin: string diff --git a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx index 1fc24db58a4b..6f885965e58e 100644 --- a/libs/portals/my-pages/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx +++ b/libs/portals/my-pages/assets/src/screens/VehicleBulkMileageJobDetail/VehicleBulkMileageJobDetail.tsx @@ -115,22 +115,21 @@ const VehicleBulkMileageJobDetail = () => { } serviceProviderSlug={SAMGONGUSTOFA_SLUG} serviceProviderTooltip={formatMessage(m.vehiclesTooltip)} - buttonGroup={ - - - - } + buttonGroup={[ + , + ]} > {!error && !loading && !jobsStatus && ( { intro={m.vehiclesBulkMileageUploadDescription} serviceProviderSlug={SAMGONGUSTOFA_SLUG} serviceProviderTooltip={formatMessage(m.vehiclesTooltip)} - buttonGroup={ - - - - } + buttonGroup={[ + , + ]} > {error && } diff --git a/libs/portals/my-pages/core/src/components/IntroWrapper/IntroWrapper.tsx b/libs/portals/my-pages/core/src/components/IntroWrapper/IntroWrapper.tsx index ada8014b94df..04588d34cc1e 100644 --- a/libs/portals/my-pages/core/src/components/IntroWrapper/IntroWrapper.tsx +++ b/libs/portals/my-pages/core/src/components/IntroWrapper/IntroWrapper.tsx @@ -7,6 +7,7 @@ import { GridRow, SkeletonLoader, Stack, + Inline, } from '@island.is/island-ui/core' import FootNote from '../FootNote/FootNote' import { MessageDescriptor } from 'react-intl' @@ -24,7 +25,7 @@ type BaseProps = { img?: string isSubheading?: boolean children?: React.ReactNode - buttonGroup?: React.ReactNode + buttonGroup?: Array serviceProviderSlug?: OrganizationSlugType serviceProviderTooltip?: string span?: GridColumnProps['span'] @@ -80,7 +81,9 @@ export const IntroWrapper = (props: IntroWrapperProps) => { {props.introComponent && ( {props.introComponent} )} - {props.buttonGroup} + + {props.buttonGroup} + )} diff --git a/libs/portals/my-pages/occupational-licenses/src/screens/v2/OccupationalLicensesDetail/OccupationalLicensesDetail.tsx b/libs/portals/my-pages/occupational-licenses/src/screens/v2/OccupationalLicensesDetail/OccupationalLicensesDetail.tsx index 9bdc975b543a..b79f3f364a62 100644 --- a/libs/portals/my-pages/occupational-licenses/src/screens/v2/OccupationalLicensesDetail/OccupationalLicensesDetail.tsx +++ b/libs/portals/my-pages/occupational-licenses/src/screens/v2/OccupationalLicensesDetail/OccupationalLicensesDetail.tsx @@ -62,58 +62,51 @@ const OccupationalLicenseDetail = () => { intro={res?.headerText ?? ''} serviceProviderSlug={license?.issuer as OrganizationSlugType} buttonGroup={ - !isOldEducationLicense && - res?.actions && ( - - { - - {res.actions.map((a, index) => { - if (!a) { - return null + !isOldEducationLicense && res?.actions + ? res.actions.map((a, index) => { + if (!a) { + return null + } + if (a.type === OccupationalLicensesV2LinkType.FILE) { + return ( + + ) + } + + return ( + { - if (a.url) { - formSubmit(a.url) - } - }} - icon={'download'} - > - {a.text} - - ) + text={a.text} + icon={ + a.type === OccupationalLicensesV2LinkType.DOCUMENT + ? 'mailOpen' + : 'open' } - - return ( - - ) - })} - - } - - ) + /> + ) + }) + : undefined } > {error && !loading && } From bd7872355b3e32439bd0f72330439c7eec453062 Mon Sep 17 00:00:00 2001 From: norda-gunni <161026627+norda-gunni@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:56:51 +0000 Subject: [PATCH 15/15] fix(application-system): Stop sending doctor visit dates when none are entered (#16957) * fix(application-system): Stop sending doctor visit dates when none are entered * chore: nx format:write update dirty files --------- Co-authored-by: andes-it Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../accident-notification-v2.utils.ts | 25 +++++- .../rights-portal/src/clientConfig.json | 85 ++++++++++++------- .../rights-portal/src/index.ts | 1 - 3 files changed, 79 insertions(+), 32 deletions(-) diff --git a/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification-v2.utils.ts b/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification-v2.utils.ts index 2b8228aa9375..9a06be962945 100644 --- a/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification-v2.utils.ts +++ b/libs/application/template-api-modules/src/lib/modules/templates/accident-notification/accident-notification-v2.utils.ts @@ -263,6 +263,29 @@ const createDateTime = (date?: string | null, time?: string | null): Date => { return new Date(year, month - 1, day, hours, minutes) } +const createNullableDateTime = ( + date?: string | null, + time?: string | null, +): Date | null => { + if (!date) { + return null + } + + const [year, month, day] = date.split('-').map(Number) + let hours = time ? parseInt(time.slice(0, 2), 10) : 0 + let minutes = time ? parseInt(time.slice(2, 4), 10) : 0 + + if (hours > 23 || hours < 0) { + hours = 0 + } + + if (minutes > 59 || minutes < 0) { + minutes = 0 + } + + return new Date(year, month - 1, day, hours, minutes) +} + const getAccident = ( answers: AccidentNotificationAnswers, ): MinarsidurAPIModelsAccidentReportsAccidentDTO => { @@ -294,7 +317,7 @@ const getAccident = ( location: accidentLocation, locationDescription: locationDescription ?? '', symptoms: accidentDetails?.accidentSymptoms ?? '', - dateTimeOfDoctorVisit: createDateTime( + dateTimeOfDoctorVisit: createNullableDateTime( accidentDetails?.dateOfDoctorVisit, accidentDetails?.timeOfDoctorVisit, ), diff --git a/libs/clients/icelandic-health-insurance/rights-portal/src/clientConfig.json b/libs/clients/icelandic-health-insurance/rights-portal/src/clientConfig.json index fac35c13470d..7b4732c0da23 100644 --- a/libs/clients/icelandic-health-insurance/rights-portal/src/clientConfig.json +++ b/libs/clients/icelandic-health-insurance/rights-portal/src/clientConfig.json @@ -310,6 +310,46 @@ } } }, + "/v1/aidsandnutrition/{iso}/renew": { + "get": { + "tags": ["aidsandnutrition"], + "operationId": "RenewAidOrNutrition", + "parameters": [ + { + "name": "iso", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + }, + "400": { + "description": "Bad Request", + "content": { + "application/json": { + "schema": { + "type": "string" + } + } + } + }, + "404": { + "description": "Not Found" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Internal Server Error" + } + } + } + }, "/v1/application": { "post": { "tags": ["application"], @@ -2416,13 +2456,7 @@ "components": { "schemas": { "Minarsidur.API.Models.AccidentReports.AccidentDTO": { - "required": [ - "datetime", - "dateTimeOfDoctorVisit", - "description", - "symptoms", - "type" - ], + "required": ["datetime", "description", "type"], "type": "object", "properties": { "type": { @@ -2448,7 +2482,8 @@ }, "dateTimeOfDoctorVisit": { "type": "string", - "format": "date-time" + "format": "date-time", + "nullable": true }, "fatal": { "type": "boolean", @@ -2611,9 +2646,6 @@ "employer": { "$ref": "#/components/schemas/Minarsidur.API.Models.AccidentReports.EmployerDTO" }, - "club": { - "$ref": "#/components/schemas/Minarsidur.API.Models.AccidentReports.ClubDTO" - }, "attachments": { "type": "array", "items": { @@ -2624,25 +2656,6 @@ }, "additionalProperties": false }, - "Minarsidur.API.Models.AccidentReports.ClubDTO": { - "required": ["accidentType", "name", "nationalId"], - "type": "object", - "properties": { - "nationalId": { - "type": "string", - "nullable": true - }, - "name": { - "type": "string", - "nullable": true - }, - "accidentType": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": false - }, "Minarsidur.API.Models.AccidentReports.EmployerDTO": { "required": [ "companyName", @@ -2912,10 +2925,18 @@ "expiring": { "type": "boolean", "nullable": true + }, + "renewalStatus": { + "$ref": "#/components/schemas/Minarsidur.API.Models.AidsAndNutrition.AidOrNutritionDTO_RenewalStatusEnum" } }, "additionalProperties": false }, + "Minarsidur.API.Models.AidsAndNutrition.AidOrNutritionDTO_RenewalStatusEnum": { + "enum": [0, 1, 2, 3], + "type": "integer", + "format": "int32" + }, "Minarsidur.API.Models.AidsAndNutrition.AidOrNutritionRefundDTO": { "type": "object", "properties": { @@ -4134,6 +4155,10 @@ "type": "string", "nullable": true }, + "canRegister": { + "type": "boolean", + "nullable": true + }, "waitlistRegistration": { "type": "boolean", "nullable": true diff --git a/libs/clients/icelandic-health-insurance/rights-portal/src/index.ts b/libs/clients/icelandic-health-insurance/rights-portal/src/index.ts index 59b3bb43a902..68be01f7dcd2 100644 --- a/libs/clients/icelandic-health-insurance/rights-portal/src/index.ts +++ b/libs/clients/icelandic-health-insurance/rights-portal/src/index.ts @@ -28,7 +28,6 @@ export { MinarsidurAPIModelsAccidentReportsInjuredDTO, MinarsidurAPIModelsAccidentReportsAccidentDTO, MinarsidurAPIModelsAccidentReportsEmployerDTO, - MinarsidurAPIModelsAccidentReportsClubDTO, MinarsidurAPIModelsAccidentReportsAccidentReportAttachmentDTO, MinarsidurAPIModelsAccidentReportsAccidentDTOAccidentLocationEnum, MinarsidurAPIModelsAccidentReportsAccidentDTOAccidentAtSailorWorkDTOAccidentAtSailorWorkShipLocationEnum,