Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Staging->main #587

Merged
merged 7 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion backend/src/main/kotlin/no/bekk/routes/ContextRouting.kt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fun Route.contextRouting() {
call.respondText("Context and its answers and comments were successfully deleted.")
}

patch {
patch("/team"){
try {
logger.info("Received PATCH /contexts with id: ${call.parameters["contextId"]}")
val contextId = call.parameters["contextId"] ?: throw BadRequestException("Missing contextId")
Expand Down Expand Up @@ -136,9 +136,35 @@ fun Route.contextRouting() {
}

}
patch("/answers") {
try {
logger.info("Received PATCH /{contextId}/answers")
val contextId = call.parameters["contextId"] ?: throw BadRequestException("Missing contextId")

val payload = call.receive<CopyContextRequest>()
val copyContextId = payload.copyContextId ?: throw BadRequestException("Missing copy contextId in request body")

if (!hasContextAccess(call, contextId)) {
call.respond(HttpStatusCode.Forbidden)
return@patch
}
AnswerRepository.copyAnswersFromOtherContext(contextId, copyContextId)
call.respond(HttpStatusCode.OK)
return@patch
} catch (e: BadRequestException) {
logger.error("Bad request: ${e.message}", e)
call.respond(HttpStatusCode.BadRequest, e.message ?: "Bad request")
} catch (e: Exception) {
logger.error("Unexpected error when processing PATCH /contexts", e)
call.respond(HttpStatusCode.InternalServerError, "An unexpected error occurred.")
}
}
}
}
}

@Serializable
data class TeamUpdateRequest(val teamId: String?)

@Serializable
data class CopyContextRequest(val copyContextId: String?)
4 changes: 2 additions & 2 deletions frontend/beCompliant/src/components/table/LastUpdated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function LastUpdated({
{!isComment && isOlderThan(updated, answerExpiry) && (
<Tooltip label="Svaret må oppdateres" aria-label="Svaret må oppdateres">
<Box as="span">
<Icon icon="warning" color="red" size={28} />
<Icon icon="warning" color="red" size={24} />
</Box>
</Tooltip>
)}
Expand All @@ -71,7 +71,7 @@ export function LastUpdated({
icon="autorenew"
color="black"
variant="tertiary"
size="md"
size="xs"
onClick={() => {
submitAnswer(value ?? '', unitAnswer);
}}
Expand Down
123 changes: 93 additions & 30 deletions frontend/beCompliant/src/components/table/SettingsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
ModalHeader,
ModalOverlay,
Select,
Skeleton,
Stack,
useToast,
} from '@kvib/react';
Expand All @@ -18,6 +19,8 @@ import { useFetchContext } from '../../hooks/useFetchContext';
import { useParams } from 'react-router-dom';
import { apiConfig } from '../../api/apiConfig';
import { axiosFetch } from '../../api/Fetch';
import { useFetchAllContexts } from '../../hooks/useFetchAllContexts';
import { Context } from '../../hooks/useFetchTeamContexts';

type Props = {
onOpen: () => void;
Expand All @@ -32,58 +35,97 @@ export function SettingsModal({ onClose, isOpen }: Props) {
const { data: userinfo } = useFetchUserinfo();
const currentContext = useFetchContext(contextId);

const handleChangeContextTeam = async (
e: React.FormEvent<HTMLFormElement>
) => {
const { data: contexts, isPending: contextsIsLoading } =
useFetchAllContexts();

const handleSettingsSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!contextId) return;
const form = e.target as HTMLFormElement;
const changeTeamElement = form.elements.namedItem(
'edit_team'
'editTeam'
) as HTMLSelectElement;
if (!changeTeamElement?.value) {
return;
}
const newTeamId = changeTeamElement.value;
try {
const response = await axiosFetch({
url: apiConfig.contexts.forIdAndTeam.url(contextId),
method: 'PATCH',
data: {
teamId: newTeamId,
},
});
if (response.status === 200 || response.status === 204) {
onClose();
const copyContextElement = form.elements.namedItem(
'copyContextSelect'
) as HTMLSelectElement;

if (changeTeamElement?.value) {
const newTeamId = changeTeamElement.value;
try {
const response = await axiosFetch({
url: apiConfig.contexts.forIdAndTeam.url(contextId) + '/team',
method: 'PATCH',
data: {
teamId: newTeamId,
},
});
if (response.status === 200 || response.status === 204) {
onClose();
}
} catch (error) {
const toastId = 'change-context-team-error';
if (!toast.isActive(toastId)) {
toast({
id: toastId,
title: 'Å nei!',
description: 'Det har skjedd en feil. Prøv på nytt',
status: 'error',
duration: 5000,
isClosable: true,
});
}
}
} catch (error) {
const toastId = 'change-context-team-error';
if (!toast.isActive(toastId)) {
toast({
id: toastId,
title: 'Å nei!',
description: 'Det har skjedd en feil. Prøv på nytt',
status: 'error',
duration: 5000,
isClosable: true,
}
if (copyContextElement?.value) {
try {
const response = await axiosFetch({
url: apiConfig.contexts.byId.url(contextId) + '/answers',
method: 'PATCH',
data: {
copyContextId: copyContextElement.value,
},
});
if (response.status === 200 || response.status === 204) {
onClose();
}
} catch (error) {
const toastId = 'copy-context-error';
if (!toast.isActive(toastId)) {
toast({
id: toastId,
title: 'Å nei!',
description: 'Det har skjedd en feil. Prøv på nytt',
status: 'error',
duration: 5000,
isClosable: true,
});
}
}
}
};

const contextsForTable: Context[] =
contexts?.filter(
(context) =>
context.tableId === currentContext.data?.tableId &&
context.id !== currentContext.data?.id
) ?? [];

const isDisabled = contextsForTable.length === 0;

return (
<Modal onClose={onClose} isOpen={isOpen} isCentered>
<ModalOverlay />
<ModalContent>
<ModalHeader>Endre skjemautfylling</ModalHeader>
<ModalBody>
<form onSubmit={handleChangeContextTeam}>
<form onSubmit={handleSettingsSubmit}>
<Stack gap="1rem">
<FormControl>
<FormLabel>
Endre teamet dette skjemaet skal gjelde for:
</FormLabel>
<Select name="edit_team" placeholder="Velg team">
<Select name="editTeam" placeholder="Velg team">
{userinfo?.groups.map((team) => {
if (team.id === currentContext.data?.teamId) {
return null;
Expand All @@ -96,6 +138,27 @@ export function SettingsModal({ onClose, isOpen }: Props) {
})}
</Select>
</FormControl>
<FormControl>
<FormLabel>Kopier svar fra et annet skjema:</FormLabel>
<Skeleton isLoaded={!contextsIsLoading}>
<Select
name="copyContextSelect"
placeholder={
isDisabled
? 'Ingen eksisterende skjema funnet'
: 'Velg skjema'
}
bgColor="white"
borderColor="gray.200"
>
{contextsForTable?.map((context) => (
<option key={context.id} value={context.id}>
{context.name}
</option>
))}
</Select>
</Skeleton>
</FormControl>

<HStack justifyContent="end">
<Button
Expand Down
Loading