0
+ ? 'danger'
+ : successfulApiDelegations.length > 0
+ ? 'success'
+ : 'dark'
+ }
size={isSm ? 'small' : 'medium'}
>
}>{t('api_delegation.give_access_to_new_api')}
- {showErrorPanel() ? (
+ {shouldShowErrorPanel() ? (
{
) : (
delegationContent()
)}
+ {isError && (
+
+ {t('common.general_error_title')}
+ {`${t('common.general_error_paragraph')}`}
+
+ )}
diff --git a/src/features/apiDelegation/offered/ConfirmationPage/DelegationLists.tsx b/src/features/apiDelegation/offered/ConfirmationPage/DelegationLists.tsx
new file mode 100644
index 000000000..3141e4630
--- /dev/null
+++ b/src/features/apiDelegation/offered/ConfirmationPage/DelegationLists.tsx
@@ -0,0 +1,75 @@
+import { BorderedList, CompactDeletableListItem } from '@/components';
+import React, { Key } from 'react';
+import classes from './ConfirmationPage.module.css';
+import { ListTextColor } from '@/components/CompactDeletableListItem/CompactDeletableListItem';
+import { ApiDelegationResult } from '@/dataObjects/dtos/resourceDelegation';
+import { removeOrg } from '@/rtk/features/apiDelegation/apiDelegationSlice';
+import { useAppDispatch, useAppSelector } from '@/rtk/app/hooks';
+import {
+ DelegableApi,
+ ApiDelegation,
+ softRemoveApi,
+} from '@/rtk/features/apiDelegation/delegableApi/delegableApiSlice';
+import { Organization } from '@/rtk/features/lookup/lookupApi';
+import { CogIcon, Buldings3Icon } from '@navikt/aksel-icons';
+import { t } from 'i18next';
+
+interface DelegationReceiptListProps {
+ items: ApiDelegationResult[];
+ contentColor?: ListTextColor;
+}
+
+export const DelegationReceiptList = ({ items, contentColor }: DelegationReceiptListProps) => (
+
+ {items?.map((item, index) => (
+
+ ))}
+
+);
+
+export const DelegableApiList = () => {
+ const chosenApis = useAppSelector((state) => state.delegableApi.chosenApis);
+ const dispatch = useAppDispatch();
+
+ return (
+
+
+ {chosenApis?.map((api: DelegableApi | ApiDelegation, index: Key) => (
+ }
+ removeCallback={chosenApis.length > 1 ? () => dispatch(softRemoveApi(api)) : null}
+ leftText={api.apiName}
+ middleText={api.orgName}
+ >
+ ))}
+
+
+ );
+};
+
+export const DelegableOrgList = () => {
+ const chosenOrgs = useAppSelector((state) => state.apiDelegation.chosenOrgs);
+ const dispatch = useAppDispatch();
+
+ return (
+
+
+ {chosenOrgs?.map((org: Organization, index: Key | null | undefined) => (
+ }
+ removeCallback={chosenOrgs.length > 1 ? () => dispatch(removeOrg(org)) : null}
+ leftText={org.name}
+ middleText={t('common.org_nr') + ' ' + org.orgNumber}
+ >
+ ))}
+
+
+ );
+};
diff --git a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css b/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css
deleted file mode 100644
index 769e39bcc..000000000
--- a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.module.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.list {
- margin-bottom: 40px !important;
-}
diff --git a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx b/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx
deleted file mode 100644
index 9601fb494..000000000
--- a/src/features/apiDelegation/offered/ReceiptPage/ReceiptPage.tsx
+++ /dev/null
@@ -1,161 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import type { Key } from 'react';
-import * as React from 'react';
-import { Button, Heading, Paragraph } from '@digdir/designsystemet-react';
-import { useNavigate } from 'react-router-dom';
-
-import { useAppDispatch, useAppSelector } from '@/rtk/app/hooks';
-import { ApiDelegationPath } from '@/routes/paths';
-import ApiIcon from '@/assets/Api.svg?react';
-import { setLoading as setOveviewToReload } from '@/rtk/features/apiDelegation/overviewOrg/overviewOrgSlice';
-import {
- PageContainer,
- Page,
- PageHeader,
- PageContent,
- CompactDeletableListItem,
- RestartPrompter,
- BorderedList,
-} from '@/components';
-import { ListTextColor } from '@/components/CompactDeletableListItem/CompactDeletableListItem';
-import type { ApiDelegation } from '@/rtk/features/apiDelegation/delegationRequest/delegationRequestSlice';
-import { useMediaQuery } from '@/resources/hooks';
-import { useDocumentTitle } from '@/resources/hooks/useDocumentTitle';
-
-import classes from './ReceiptPage.module.css';
-
-export const ReceiptPage = () => {
- const failedApiDelegations = useAppSelector(
- (state) => state.delegationRequest.failedApiDelegations,
- );
- const successfulApiDelegations = useAppSelector(
- (state) => state.delegationRequest.succesfulApiDelegations,
- );
- const { t } = useTranslation();
- const dispatch = useAppDispatch();
- const isSm = useMediaQuery('(max-width: 768px)');
- const navigate = useNavigate();
- useDocumentTitle(t('api_delegation.delegate_page_title'));
-
- const failedDelegationContent = () => {
- return (
- <>
-
- {t('api_delegation.failed_delegations')}
-
-
- {failedApiDelegations?.map(
- (apiDelegation: ApiDelegation, index: Key | null | undefined) => (
-
- ),
- )}
-
- >
- );
- };
-
- const successfulDelegationsContent = () => {
- return (
- <>
-
- {t('api_delegation.succesful_delegations')}
-
-
- {successfulApiDelegations?.map(
- (apiDelegation: ApiDelegation, index: Key | null | undefined) => (
-
- ),
- )}
-
- >
- );
- };
-
- const delegatedContent = () => {
- return (
- <>
- {showTopSection() && failedDelegationContent()}
- {showBottomSection() && successfulDelegationsContent()}
- >
- );
- };
-
- const showTopSection = () => {
- return (
- failedApiDelegations !== null &&
- failedApiDelegations !== undefined &&
- failedApiDelegations?.length > 0
- );
- };
-
- const showBottomSection = () => {
- return (
- successfulApiDelegations !== null &&
- successfulApiDelegations !== undefined &&
- successfulApiDelegations?.length > 0
- );
- };
-
- const showErrorAlert = () => {
- return !showTopSection() && !showBottomSection();
- };
-
- const navigateToOverview = () => {
- dispatch(setOveviewToReload());
- navigate('/' + ApiDelegationPath.OfferedApiDelegations + '/' + ApiDelegationPath.Overview);
- };
-
- return (
-
-
- }>{t('api_delegation.give_access_to_new_api')}
-
- {showErrorAlert() ? (
-
- ) : (
-
- {delegatedContent()}
-
- {successfulApiDelegations.length === 0
- ? t('api_delegation.receipt_page_failed_text')
- : t('api_delegation.receipt_page_bottom_text')}
-
-
- )}
-
-
-
-
- );
-};
diff --git a/src/features/apiDelegation/offered/ReceiptPage/index.ts b/src/features/apiDelegation/offered/ReceiptPage/index.ts
deleted file mode 100644
index ab707e96d..000000000
--- a/src/features/apiDelegation/offered/ReceiptPage/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { ReceiptPage } from './ReceiptPage';
diff --git a/src/routes/Router/Router.tsx b/src/routes/Router/Router.tsx
index 8ef72ad7b..637da1566 100644
--- a/src/routes/Router/Router.tsx
+++ b/src/routes/Router/Router.tsx
@@ -5,7 +5,6 @@ import { ChooseApiPage } from '@/features/apiDelegation/offered/ChooseApiPage';
import { OverviewPage as OfferedOverviewPage } from '@/features/apiDelegation/offered/OverviewPage';
import { OverviewPage as ReceivedOverviewPage } from '@/features/apiDelegation/received/OverviewPage';
import { ChooseOrgPage } from '@/features/apiDelegation/offered/ChooseOrgPage';
-import { ReceiptPage } from '@/features/apiDelegation/offered/ReceiptPage';
import { ConfirmationPage } from '@/features/apiDelegation/offered/ConfirmationPage';
import { ErrorPage } from '@/sites/ErrorPage';
import { ChooseServicePage as DelegateChooseServicePage } from '@/features/singleRight/delegate/ChooseServicePage/ChooseServicePage';
@@ -43,10 +42,6 @@ export const Router = createBrowserRouter(
path={ApiDelegationPath.Confirmation}
element={
}
/>
-
}
- />
({
+ query: ({ partyId, apis, orgs }) => ({
+ url: `apidelegation/${partyId}/offered/batch`,
+ method: 'POST',
+ body: JSON.stringify({
+ apiIdentifiers: apis.map((api) => api.identifier),
+ orgNumbers: orgs.map((org) => org.orgNumber),
+ }),
+ }),
+ transformResponse: (response: ApiDelegationResult[], _meta, args) => {
+ return response.map((d) => {
+ return {
+ orgNumber: d.orgNumber,
+ orgName: args.orgs.find((org) => org.orgNumber === d.orgNumber)?.name || '',
+ apiId: d.apiId,
+ apiName: args.apis.find((api) => api.identifier === d.apiId)?.apiName || '',
+ success: d.success,
+ };
+ });
+ },
+ transformErrorResponse: (response: { status: string | number }) => {
+ return response.status;
+ },
+ }),
}),
});
-export const { useDelegationCheckMutation, useSearchQuery } = apiDelegationApi;
+export const { useDelegationCheckMutation, useSearchQuery, usePostApiDelegationMutation } =
+ apiDelegationApi;
diff --git a/src/rtk/features/apiDelegation/delegableApi/delegableApiSlice.ts b/src/rtk/features/apiDelegation/delegableApi/delegableApiSlice.ts
index 0b4167516..0a3aa0a94 100644
--- a/src/rtk/features/apiDelegation/delegableApi/delegableApiSlice.ts
+++ b/src/rtk/features/apiDelegation/delegableApi/delegableApiSlice.ts
@@ -2,6 +2,11 @@ import { createSlice } from '@reduxjs/toolkit';
import type { IdValuePair } from '@/dataObjects/dtos/IdValuePair';
+export interface ApiDelegation {
+ orgName: string;
+ apiName: string;
+}
+
export interface DelegableApi {
identifier: string;
apiName: string;
diff --git a/src/rtk/features/apiDelegation/delegationRequest/delegationRequestSlice.ts b/src/rtk/features/apiDelegation/delegationRequest/delegationRequestSlice.ts
deleted file mode 100644
index b0b52cd49..000000000
--- a/src/rtk/features/apiDelegation/delegationRequest/delegationRequestSlice.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
-import axios from 'axios';
-
-import { getCookie } from '@/resources/Cookie/CookieMethods';
-
-export interface ApiDelegation {
- orgName: string;
- apiName: string;
-}
-
-export interface SliceState {
- loading: boolean;
- error: string;
- succesfulApiDelegations: ApiDelegation[];
- failedApiDelegations: ApiDelegation[];
- batchPostSize: number;
- batchPostCounter: number;
-}
-
-export interface DelegationRequest {
- apiIdentifier: string;
- apiName: string;
- orgNr: string;
- orgName: string;
-}
-
-const initialState: SliceState = {
- loading: true,
- error: '',
- succesfulApiDelegations: [],
- failedApiDelegations: [],
- batchPostSize: 0,
- batchPostCounter: 0,
-};
-
-export const postApiDelegation = createAsyncThunk(
- 'delegationRequestSlice/postApiDelegation',
- async (delegationInfo: DelegationRequest) => {
- const { apiIdentifier, apiName, orgNr, orgName }: DelegationRequest = delegationInfo;
- const delegation: ApiDelegation = {
- apiName,
- orgName,
- };
- const altinnPartyId = getCookie('AltinnPartyId');
-
- if (!altinnPartyId) {
- throw new Error(String('Could not get AltinnPartyId cookie value'));
- }
-
- return await axios
- .post(`/accessmanagement/api/v1/apidelegation/${altinnPartyId}/offered`, {
- to: [
- {
- id: 'urn:altinn:organizationnumber',
- value: String(orgNr),
- },
- ],
- rights: [
- {
- resource: [
- {
- id: 'urn:altinn:resource',
- value: String(apiIdentifier),
- },
- ],
- },
- ],
- })
- .then(() => {
- return delegation;
- })
- .catch((error) => {
- throw error;
- });
- },
-);
-
-const delegationRequestSlice = createSlice({
- name: 'delegationRequest',
- initialState,
- reducers: {
- resetDelegationRequests: () => initialState,
- setBatchPostSize: (state, action) => {
- state.batchPostSize = action.payload;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(postApiDelegation.fulfilled, (state, action) => {
- const sucessfulDelegations = state.succesfulApiDelegations;
- const delegation: ApiDelegation = {
- apiName: action.payload.apiName,
- orgName: action.payload.orgName,
- };
-
- sucessfulDelegations.push(delegation);
- state.succesfulApiDelegations = sucessfulDelegations.sort((a, b) => {
- const orgNameCompared = a.orgName.localeCompare(b.orgName);
- if (orgNameCompared === 0) {
- // Equal orgnames
- return a.apiName.localeCompare(b.apiName);
- }
- return orgNameCompared;
- });
- state.batchPostCounter += 1;
- if (state.batchPostCounter === state.batchPostSize) {
- state.loading = false;
- }
- })
- .addCase(postApiDelegation.rejected, (state, action) => {
- const failedDelegations = state.failedApiDelegations;
- const delegation: ApiDelegation = {
- apiName: action.meta.arg.apiName,
- orgName: action.meta.arg.orgName,
- };
- failedDelegations.push(delegation);
- state.failedApiDelegations = failedDelegations.sort((a, b) => {
- const orgNameCompared = a.orgName.localeCompare(b.orgName);
- if (orgNameCompared === 0) {
- // Equal orgnames
- return a.apiName.localeCompare(b.apiName);
- }
- return orgNameCompared;
- });
- state.batchPostCounter += 1;
- if (state.batchPostCounter === state.batchPostSize) {
- state.loading = false;
- }
- });
- },
-});
-
-export default delegationRequestSlice.reducer;
-export const { resetDelegationRequests, setBatchPostSize } = delegationRequestSlice.actions;