Skip to content

Commit

Permalink
Merge branch 'feature/OPHKIOS-108' into feature/OPHKIOS-114
Browse files Browse the repository at this point in the history
  • Loading branch information
jrkkp committed Oct 8, 2024
2 parents 46cf830 + d28dcc3 commit 140ef60
Show file tree
Hide file tree
Showing 54 changed files with 1,270 additions and 83 deletions.
10 changes: 10 additions & 0 deletions backend/vkt/src/main/java/fi/oph/vkt/api/PublicController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import fi.oph.vkt.api.dto.PublicEnrollmentDTO;
import fi.oph.vkt.api.dto.PublicEnrollmentInitialisationDTO;
import fi.oph.vkt.api.dto.PublicExamEventDTO;
import fi.oph.vkt.api.dto.PublicExaminerDTO;
import fi.oph.vkt.api.dto.PublicPersonDTO;
import fi.oph.vkt.api.dto.PublicReservationDTO;
import fi.oph.vkt.model.Enrollment;
Expand All @@ -24,6 +25,7 @@
import fi.oph.vkt.service.PublicEnrollmentAppointmentService;
import fi.oph.vkt.service.PublicEnrollmentService;
import fi.oph.vkt.service.PublicExamEventService;
import fi.oph.vkt.service.PublicExaminerService;
import fi.oph.vkt.service.PublicPersonService;
import fi.oph.vkt.service.PublicReservationService;
import fi.oph.vkt.service.koski.KoskiService;
Expand Down Expand Up @@ -95,11 +97,19 @@ public class PublicController {
@Resource
private FeatureFlagService featureFlagService;

@Resource
private PublicExaminerService publicExaminerService;

@GetMapping(path = "/examEvent")
public List<PublicExamEventDTO> list() {
return publicExamEventService.listExamEvents(ExamLevel.EXCELLENT);
}

@GetMapping(path = "/examiner")
public List<PublicExaminerDTO> listExaminers() {
return publicExaminerService.listExaminers();
}

@PostMapping(path = "/enrollment/reservation/{reservationId:\\d+}")
@ResponseStatus(HttpStatus.CREATED)
public PublicEnrollmentDTO createEnrollment(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package fi.oph.vkt.api.dto;

import fi.oph.vkt.model.type.ExamLanguage;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record PublicExaminerDTO(
@NonNull @NotNull Long id,
@NonNull @NotNull String lastName,
@NonNull @NotNull String firstName,
@NonNull @NotNull List<ExamLanguage> languages,
@NonNull @NotNull List<PublicMunicipalityDTO> municipalities,
@NonNull @NotNull List<LocalDate> examDates
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fi.oph.vkt.api.dto;

import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record PublicMunicipalityDTO(@NonNull @NotNull String fi, @NonNull @NotNull String sv) {}
3 changes: 2 additions & 1 deletion backend/vkt/src/main/java/fi/oph/vkt/model/FeatureFlag.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package fi.oph.vkt.model;

public enum FeatureFlag {
FREE_ENROLLMENT_FOR_HIGHEST_LEVEL_ALLOWED("freeEnrollmentAllowed");
FREE_ENROLLMENT_FOR_HIGHEST_LEVEL_ALLOWED("freeEnrollmentAllowed"),
GOOD_AND_SATISFACTORY_LEVEL("goodAndSatisfactoryLevel");

private final String propertyKey;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package fi.oph.vkt.service;

import fi.oph.vkt.api.dto.PublicExaminerDTO;
import fi.oph.vkt.api.dto.PublicMunicipalityDTO;
import fi.oph.vkt.model.type.ExamLanguage;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class PublicExaminerService {

public List<PublicExaminerDTO> listExaminers() {
final PublicMunicipalityDTO helsinki = PublicMunicipalityDTO.builder().fi("Helsinki").sv("Helsingfors").build();
final PublicMunicipalityDTO espoo = PublicMunicipalityDTO.builder().fi("Espoo").sv("Esbo").build();
final PublicMunicipalityDTO vantaa = PublicMunicipalityDTO.builder().fi("Vantaa").sv("Vanda").build();
final PublicMunicipalityDTO kauniainen = PublicMunicipalityDTO.builder().fi("Kauniainen").sv("Grankulla").build();
final List<PublicExaminerDTO> examiners = new ArrayList<>();
examiners.add(
PublicExaminerDTO
.builder()
.id(1L)
.lastName("Laine")
.firstName("Eemeli")
.languages(List.of(ExamLanguage.FI))
.municipalities(List.of(helsinki, espoo, vantaa, kauniainen))
.examDates(List.of())
.build()
);

return examiners;
}
}
1 change: 1 addition & 0 deletions backend/vkt/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,6 @@ app:
account: ${payment.paytrail.account:null}
featureFlags:
freeEnrollmentAllowed: ${feature-flags.free-enrollment-allowed:false}
goodAndSatisfactoryLevel: ${feature-flags.good-and-satisfactory-level:false}
aws:
s3-bucket: ${aws.s3-bucket:test}
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ koski.user={{vkt_koski_user}}
koski.password={{vkt_koski_password}}

feature-flags.free-enrollment-allowed={{vkt_feature_free_enrollment_allowed}}
feature-flags.good-and-satisfactory-level={{vkt_feature_good_and_satisfactory_level}}

aws.s3-bucket={{vkt_aws_s3_bucket}}
4 changes: 1 addition & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@fontsource/roboto": "^5.0.14",
"@mui/base": "5.0.0-beta.58",
"@mui/icons-material": "^5.16.7",
"@mui/material": "^5.16.7",
"@mui/system": "^5.16.7",
Expand Down Expand Up @@ -109,8 +110,5 @@
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
},
"@comments": {
"react-router-dom": "Do not update past 6.13.0 until useBlocker is fixed, see https://github.com/remix-run/react-router/issues/11155"
}
}
5 changes: 5 additions & 0 deletions frontend/packages/shared/CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Released]

## [1.11.5] - 2024-09-27

### Added
- MobileNavigationMenuWithPortal component

## [1.11.4] - 2024-10-07

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion frontend/packages/shared/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opetushallitus/kieli-ja-kaantajatutkinnot.shared",
"version": "1.11.4",
"version": "1.11.5",
"description": "Shared Frontend Package",
"exports": {
"./components": "./src/components/index.tsx",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@use '../../styles/abstracts/colors';

button.navigation-menu-toggle {
background-color: colors.$color-primary;
border: 0;
}

.navigation-menu-contents {
ul {
list-style-type: none;
display: flex;
flex-direction: column;
padding: 1rem;
}

li {
> a {
text-decoration: none;
}
padding: 1rem;
}

li.active {
p {
color: colors.$color-secondary;
font-weight: 700;
}
border-left: 2px solid colors.$color-secondary;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { FocusTrap } from '@mui/base/FocusTrap';
import CloseIcon from '@mui/icons-material/Close';
import MenuIcon from '@mui/icons-material/Menu';
import { ClickAwayListener, Divider, Paper } from '@mui/material';
import { Fragment, useState } from 'react';
import { createPortal } from 'react-dom';
import { Link } from 'react-router-dom';

import { Color } from '../../enums';
import { NavigationLinksProps } from '../NavigationLinks/NavigationLinks';
import { Text } from '../Text/Text';

import './MobileNavigationMenu.scss';

const MobileNavigationMenuToggle = ({
openStateLabel,
openStateAriaLabel,
closedStateLabel,
closedStateAriaLabel,
isOpen,
setIsOpen,
}: {
openStateLabel: string;
openStateAriaLabel: string;
closedStateLabel: string;
closedStateAriaLabel: string;
isOpen: boolean;
setIsOpen: (state: boolean) => void;
}) => {
const handleClick = () => {
setIsOpen(!isOpen);
};

return (
<button
tabIndex={0}
className="navigation-menu-toggle rows align-items-center"
onClick={handleClick}
>
{isOpen && (
<>
<CloseIcon
color={Color.Secondary}
fontSize="large"
aria-hidden={true}
/>
<Text aria-label={openStateAriaLabel} fontSize={12}>
{openStateLabel}
</Text>
</>
)}
{!isOpen && (
<>
<MenuIcon
color={Color.Secondary}
fontSize="large"
aria-hidden={true}
/>
<Text aria-label={closedStateAriaLabel} fontSize={12}>
{closedStateLabel}
</Text>
</>
)}
</button>
);
};

interface MobileNavigationMenuProps extends NavigationLinksProps {
closeMenu: () => void;
}

export const MobileNavigationMenuContents = ({
navigationAriaLabel,
links,
closeMenu,
}: MobileNavigationMenuProps) => {
const handleClickAway = (e: MouseEvent | TouchEvent) => {
// Prevent event default so that when user clicks on menu close button (outside actual menu contents),
// the menu isn't immediately opened again.
e.preventDefault();
closeMenu();
};

const handleEsc = (e: React.KeyboardEvent) => {
if (e.key === 'Escape') {
closeMenu();
}
};

return (
<FocusTrap open={true}>
<Paper
onKeyDown={handleEsc}
role="presentation"
tabIndex={-1}
elevation={3}
>
<nav
className="navigation-menu-contents"
aria-label={navigationAriaLabel}
>
<ClickAwayListener onClickAway={handleClickAway}>
<ul className="gapped-sm">
{links.map((l, i) => (
<Fragment key={i}>
{i > 0 && <Divider />}
<li key={i} className={l.active ? 'active' : undefined}>
<Link
to={l.href}
aria-current={l.active && 'page'}
onClick={closeMenu}
>
<Text>{l.label}</Text>
</Link>
</li>
</Fragment>
))}
</ul>
</ClickAwayListener>
</nav>
</Paper>
</FocusTrap>
);
};

export const MobileNavigationMenuWithPortal = ({
navigationAriaLabel,
openStateLabel,
openStateAriaLabel,
closedStateLabel,
closedStateAriaLabel,
links,
portalContainer,
}: {
openStateLabel: string;
openStateAriaLabel: string;
closedStateLabel: string;
closedStateAriaLabel: string;
portalContainer: HTMLElement;
} & NavigationLinksProps) => {
const [isMenuOpen, setIsMenuOpen] = useState(false);

return (
<>
<MobileNavigationMenuToggle
openStateAriaLabel={openStateAriaLabel}
openStateLabel={openStateLabel}
closedStateAriaLabel={closedStateAriaLabel}
closedStateLabel={closedStateLabel}
isOpen={isMenuOpen}
setIsOpen={() => setIsMenuOpen(true)}
/>
{isMenuOpen &&
createPortal(
<MobileNavigationMenuContents
navigationAriaLabel={navigationAriaLabel}
links={links}
closeMenu={() => setIsMenuOpen(false)}
/>,
portalContainer,
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

li {
padding-bottom: 2rem;

> a {
text-decoration: none;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link } from 'react-router-dom';
import { Text } from '../Text/Text';
import './NavigationLinks.scss';

interface NavigationLinksProps {
export interface NavigationLinksProps {
navigationAriaLabel: string;
links: Array<NavigationLink>;
}
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/shared/src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ export {
NativeSelectWithLabel,
} from './NativeSelect/NativeSelect';
export { NavigationLinks } from './NavigationLinks/NavigationLinks';
export { MobileNavigationMenuWithPortal } from './MobileNavigationMenu/MobileNavigationMenu';
2 changes: 1 addition & 1 deletion frontend/packages/vkt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@
},
"dependencies": {
"reduxjs-toolkit-persist": "^7.2.1",
"shared": "npm:@opetushallitus/[email protected].4"
"shared": "npm:@opetushallitus/[email protected].5"
}
}
Loading

0 comments on commit 140ef60

Please sign in to comment.