diff --git a/app/components/common/ChipsFilters.tsx b/app/components/common/ChipsFilters.tsx index faf66d4..4fb79a9 100644 --- a/app/components/common/ChipsFilters.tsx +++ b/app/components/common/ChipsFilters.tsx @@ -10,6 +10,7 @@ const ChipsFilters = () => { const [name, setName] = useState() const [userType, setUserType] = useState() const [search, setSearchName] = useState() + const [orgUnitName, setOrgUnitName] = useState() useEffect(() => { const orgsParam = searchParams.get("orgUnits") @@ -17,11 +18,14 @@ const ChipsFilters = () => { const nameParam = searchParams.get("name") const userTypeParam = searchParams.get("userType") const searchNameParam = searchParams.get("search") + const orgUnitName = searchParams.get("orgUnitName") + orgsParam ? setOrgUnits(orgsParam) : setOrgUnits(undefined) accessRoleIdParam ? setAccessRoleId(accessRoleIdParam) : setAccessRoleId(undefined) nameParam ? setName(nameParam) : setName(undefined) userTypeParam ? setUserType(userTypeParam) : setUserType(undefined) searchNameParam ? setSearchName(searchNameParam) : setSearchName(undefined) + orgUnitName ? setOrgUnitName(orgUnitName) : setOrgUnitName(undefined) }, [searchParams]); const removeFilter = (filterToRemove: string) => { @@ -42,6 +46,9 @@ const ChipsFilters = () => { case "searchName": setSearchName(undefined) return + case "orgUnitName": + setOrgUnitName(undefined) + return default: setUserType(undefined) return @@ -90,6 +97,17 @@ const ChipsFilters = () => { {search} } + {orgUnitName && + { + handleClearSearchFieldString(setSearchParams) + removeFilter("orgUnitName") + }} + id="org-unit-name-chip" + > + {`Søkenavn: ${orgUnitName}`} + + } ) } diff --git a/app/components/common/CommonFunctions.ts b/app/components/common/CommonFunctions.ts index 811dc55..81ba21c 100644 --- a/app/components/common/CommonFunctions.ts +++ b/app/components/common/CommonFunctions.ts @@ -58,4 +58,15 @@ export const handleClearNameFieldString = (setSearchParams: SetURLSearchParams) return searchParameter }) } +// ----- + + + +// When any filter is changed, reset "page" query param +export const filterResetPageParam = (pageParam: string | null, setSearchParams: SetURLSearchParams) => { + pageParam ? setSearchParams((prev) => { + prev.get("page") ? prev.delete("page") : null + return prev + }) : null +} // ----- \ No newline at end of file diff --git a/app/components/kontroll-admin/KontrollAccessRolesRadioGroup.tsx b/app/components/kontroll-admin/KontrollAccessRolesRadioGroup.tsx new file mode 100644 index 0000000..8979e76 --- /dev/null +++ b/app/components/kontroll-admin/KontrollAccessRolesRadioGroup.tsx @@ -0,0 +1,39 @@ +import {Radio, RadioGroup} from "@navikt/ds-react"; +import React, {useEffect} from "react"; +import {IRole} from "~/data/kontrollAdmin/types"; +import {useNavigate, useParams} from "@remix-run/react"; + +interface AccessRolesRadioGroupProps { + roles: IRole[] +} + +export default function KontrollAccessRolesRadioGroup ({roles}: AccessRolesRadioGroupProps) { + const params = useParams() + + const roleProp = params.id + const navigate = useNavigate(); + + const handleChangeSelectedRole = (role: string) => { + navigate(role) + } + + useEffect(() => { + !roleProp ? navigate(roles[0].accessRoleId) : "" + }, []); + + return ( +
+ handleChangeSelectedRole(val)} + value={roleProp ? roleProp : ""} + > + {roles.map((role, index) => + + {role.name} + ) + } + +
+ ) +} \ No newline at end of file diff --git a/app/components/resource-module-admin/ResourceModuleAdminUsersTable.tsx b/app/components/resource-module-admin/ResourceModuleAdminUsersTable.tsx index 91f5932..84ead9b 100644 --- a/app/components/resource-module-admin/ResourceModuleAdminUsersTable.tsx +++ b/app/components/resource-module-admin/ResourceModuleAdminUsersTable.tsx @@ -40,7 +40,6 @@ const ResourceModuleAdminUsersTable = ({usersPage, orgUnitList, roles}: Resource - diff --git a/app/components/resource-module-admin/ResourceModuleRoleFilter.tsx b/app/components/resource-module-admin/ResourceModuleRoleFilter.tsx index 1907d3e..52bb9bc 100644 --- a/app/components/resource-module-admin/ResourceModuleRoleFilter.tsx +++ b/app/components/resource-module-admin/ResourceModuleRoleFilter.tsx @@ -1,29 +1,45 @@ import {Radio, RadioGroup} from "@navikt/ds-react"; -import {IResourceModuleAccessRole} from "~/data/resourceModuleAdmin/types"; +import {IResourceModuleAccessRole, IResourceModuleUserRole} from "~/data/resourceModuleAdmin/types"; import {useSearchParams} from "@remix-run/react"; +import {filterResetPageParam} from "~/components/common/CommonFunctions"; interface ResourceModuleRoleFilterProps { - roles: IResourceModuleAccessRole[] + roles: IResourceModuleAccessRole[] | IResourceModuleUserRole[] } const ResourceModuleRoleFilter = ({roles}: ResourceModuleRoleFilterProps) => { const [searchParams, setSearchParams] = useSearchParams(); const roleProp = searchParams.get("accessroleid") + const pageParam = searchParams.get("page") const handleFilterRole = (value: string) => { setSearchParams((prev) => { - prev.set("accessroleid", value) + value ? prev.set("accessroleid", value) : prev.delete("accessroleid") return prev }) + filterResetPageParam(pageParam, setSearchParams) } - return ( - - { - roles.map((role) => {role.name}) - } - - ) + // Check which type roles is of, to allow reusability of this component. + if (roles.every(role => typeof role === 'object' && 'accessRoleId' in role)) { + const newRoles: any = roles + return ( + + { + newRoles.map((role: IResourceModuleAccessRole) => {role.name}) + } + + ) + } else { + const newRoles: any = roles + return ( + + { + newRoles.map((role: IResourceModuleUserRole) => {role.roleName}) + } + + ) + } } export default ResourceModuleRoleFilter \ No newline at end of file diff --git a/app/components/resource-module-admin/administer/AdministerToolbar.tsx b/app/components/resource-module-admin/administer/AdministerToolbar.tsx index 714af9b..c810a71 100644 --- a/app/components/resource-module-admin/administer/AdministerToolbar.tsx +++ b/app/components/resource-module-admin/administer/AdministerToolbar.tsx @@ -1,19 +1,24 @@ import {HStack, Search, Select} from "@navikt/ds-react"; import {useState} from "react"; import {useSearchParams} from "@remix-run/react"; +import {filterResetPageParam} from "~/components/common/CommonFunctions"; interface ToolbarProps { objectTypesForUser: string[] } + const AdministerToolbar = ({objectTypesForUser}: ToolbarProps) => { const [searchValue, setSearchValue] = useState("") - const [, setSearchParams] = useSearchParams() + const [searchParams, setSearchParams] = useSearchParams() + + const pageParam = searchParams.get("page") const setObjectTypeFilter = (val: string) => { setSearchParams(searchParams => { val ? searchParams.set("objectType", val) : searchParams.delete("objectType") return searchParams }) + filterResetPageParam(pageParam, setSearchParams) } const handleSearch = () => { @@ -21,6 +26,8 @@ const AdministerToolbar = ({objectTypesForUser}: ToolbarProps) => { searchValue ? searchParams.set("orgUnitName", searchValue) : searchParams.delete("orgUnitName") return searchParams }) + setSearchValue("") + filterResetPageParam(pageParam, setSearchParams) } return ( @@ -38,7 +45,18 @@ const AdministerToolbar = ({objectTypesForUser}: ToolbarProps) => { handleSearch() event.preventDefault() }}> - setSearchValue(event)} /> + setSearchValue(event)} + value={searchValue} + onClear={() => { + setSearchParams(searchParameter => { + searchParameter.delete("orgUnitName") + return searchParameter + }) + }} + /> ) diff --git a/app/data/resourceModuleAdmin/resource-module-admin.ts b/app/data/resourceModuleAdmin/resource-module-admin.ts index 8178fb0..fa54c23 100644 --- a/app/data/resourceModuleAdmin/resource-module-admin.ts +++ b/app/data/resourceModuleAdmin/resource-module-admin.ts @@ -26,8 +26,6 @@ export const postNewTildelingForUser = async (token: string | null, resourceId: const url = `${ACCESS_MANAGEMENT_API_URL}${BASE_PATH}/api/accessmanagement/v1/accessassignment`; - console.log(scopeId) - const response = await fetch(url, { method: "POST", headers: ({ diff --git a/app/data/resourceModuleAdmin/types.ts b/app/data/resourceModuleAdmin/types.ts index ddebddc..cb3142b 100644 --- a/app/data/resourceModuleAdmin/types.ts +++ b/app/data/resourceModuleAdmin/types.ts @@ -22,7 +22,7 @@ export interface IResourceModuleUser { lastName: string userType: string userName: string - roles?: IResourceModuleUserRole[] // Optional to allow use of same type + roles: IResourceModuleUserRole[] } export interface IResourceModuleUserRole { diff --git a/app/routes/kontroll-admin.define-role.tsx b/app/routes/kontroll-admin.define-role.tsx index 832f5af..74b06a2 100644 --- a/app/routes/kontroll-admin.define-role.tsx +++ b/app/routes/kontroll-admin.define-role.tsx @@ -12,6 +12,7 @@ import {json} from "@remix-run/node"; import {fetchAccessRoles} from "~/data/kontrollAdmin/kontroll-admin-define-role"; import React, {Suspense, useEffect} from "react"; import {IRole} from "~/data/kontrollAdmin/types"; +import KontrollAccessRolesRadioGroup from "~/components/kontroll-admin/KontrollAccessRolesRadioGroup"; export async function loader({request}: LoaderFunctionArgs) { @@ -24,37 +25,11 @@ export default function KontrollAdminDefineRole() { const roles: IRole[] = useLoaderData(); const context = useOutletContext() - const params = useParams() - - const roleProp = params.id - const navigate = useNavigate(); - - const handleChangeSelectedRole = (role: string) => { - navigate(role) - } - - useEffect(() => { - !roleProp ? navigate(roles[0].accessRoleId) : "" - }, []); - return (
-
- handleChangeSelectedRole(val)} - value={roleProp ? roleProp : ""} - > - {roles.map((role, index) => - - {role.name} - ) - } - -
- +
diff --git a/app/routes/kontroll-admin.features-to-role.tsx b/app/routes/kontroll-admin.features-to-role.tsx index a5279f1..8f4f4ec 100644 --- a/app/routes/kontroll-admin.features-to-role.tsx +++ b/app/routes/kontroll-admin.features-to-role.tsx @@ -5,6 +5,7 @@ import {LoaderFunctionArgs} from "@remix-run/router"; import {fetchAccessRoles} from "~/data/kontrollAdmin/kontroll-admin-define-role"; import {IResourceModuleAccessRole} from "~/data/resourceModuleAdmin/types"; import styles from "../components/kontroll-admin/kontroll-admin.css?url"; +import KontrollAccessRolesRadioGroup from "~/components/kontroll-admin/KontrollAccessRolesRadioGroup"; export function links() { return [{rel: 'stylesheet', href: styles}] @@ -39,17 +40,7 @@ export default () => {
- handleChangeSelectedRole(val)} - value={roleProp ? roleProp : ""} - > - {accessRoles.map((role, index) => - - {role.name} - ) - } - +
diff --git a/app/routes/resource-module-admin.administer.$id.tsx b/app/routes/resource-module-admin.administer.$id.tsx index f6b618e..f45d92b 100644 --- a/app/routes/resource-module-admin.administer.$id.tsx +++ b/app/routes/resource-module-admin.administer.$id.tsx @@ -5,8 +5,16 @@ import { fetchUserAssignments, deleteAllAssignmentsOnUser, deleteUserAssignmentByAccessRoleId, deleteOrgUnitFromAssignment } from "~/data/resourceModuleAdmin/resource-module-admin"; -import {Links, Meta, Scripts, useActionData, useLoaderData, useNavigate, useRouteError} from "@remix-run/react"; -import {Alert, Box, Button, Heading, HStack, Select, VStack} from "@navikt/ds-react"; +import { + Links, + Meta, + Scripts, + useActionData, + useLoaderData, + useNavigate, + useRouteError, useSearchParams +} from "@remix-run/react"; +import {Alert, Box, Button, Heading, HStack, VStack} from "@navikt/ds-react"; import {ArrowLeftIcon, TrashIcon} from "@navikt/aksel-icons"; import { IResourceModuleAccessRole, @@ -21,6 +29,8 @@ import ResourceModuleResetModal from "../components/resource-module-admin/admini import RoleAssignmentTable from "../components/resource-module-admin/administer/RoleAssignmentTable"; import styles from "../components/resource-module-admin/resourceModuleAdmin.css?url"; import {toast} from "react-toastify"; +import ChipsFilters from "~/components/common/ChipsFilters"; +import ResourceModuleRoleFilter from "~/components/resource-module-admin/ResourceModuleRoleFilter"; export function links() { return [{rel: 'stylesheet', href: styles}] @@ -93,6 +103,11 @@ const ResourceModuleAdminAdministerId = () => { const userAssignmentsPaginated = loaderData.userAssignmentsPaginated as IResourceModuleUserAssignmentsPaginated const accessRoles = loaderData.accessRoles as IResourceModuleAccessRole[] + const [searchParams, setSearchParams] = useSearchParams() + const roleProp = searchParams.get("accessroleid") + const objectTypeParam = searchParams.get("objectType") + const orgUnitNameParam = searchParams.get("orgUnitName") + const navigate = useNavigate() const [selectedRole, setSelectedRole] = useState({ accessRoleId: "", name: "" }) @@ -117,17 +132,13 @@ const ResourceModuleAdminAdministerId = () => { actionData?.message ? toast.success(actionData.message) : null }, [actionData]); - - const handleChangeRole = (selectedRoleParam: string) => { + useEffect(() => { const paramMappedToAccessRoleType: IResourceModuleAccessRole | undefined = accessRoles.find( - (role) => role.accessRoleId === selectedRoleParam + (role) => role.accessRoleId === roleProp ) - if (paramMappedToAccessRoleType === undefined) { - setSelectedRole({ accessRoleId: "", name: "" }) - } else { - setSelectedRole(paramMappedToAccessRoleType) - } - } + + paramMappedToAccessRoleType === undefined ? setSelectedRole({ accessRoleId: "", name: "" }) : setSelectedRole(paramMappedToAccessRoleType) + }, [roleProp]); const toggleRolesResetModal = (value: boolean) => { setIsResetRolesModalOpen(value) @@ -137,6 +148,19 @@ const ResourceModuleAdminAdministerId = () => { setIsDeleteModalOpen(true) } + if(userDetails.roles.length === 0) { + return +
+ +
+
+ {`${userDetails.firstName} ${userDetails.lastName}`} har ingen roller +
+
+ } + return ( <> @@ -163,39 +187,34 @@ const ResourceModuleAdminAdministerId = () => { - - -
- {selectedRole.accessRoleId !== "" && ( - - )} -
-
- {userDetails?.roles?.length === 0 ? ( + {userDetails.roles.length === 0 ? ( <>Brukeren har ingen roller ) : (
+ + + + +
+ {selectedRole.accessRoleId !== "" && ( + + )} +
+
+ + + +
)} @@ -228,20 +247,20 @@ export function ErrorBoundary() { // console.error(error); return ( - - Feil oppstod - - - - - - - Det oppsto en feil med følgende melding: -
{error.message}
-
-
- - + + Feil oppstod + + + + + + + Det oppsto en feil med følgende melding: +
{error.message}
+
+
+ + ); } \ No newline at end of file diff --git a/cypress/e2e/brukere/users.cy.ts b/cypress/e2e/brukere/users.cy.ts index d75625f..82c3417 100644 --- a/cypress/e2e/brukere/users.cy.ts +++ b/cypress/e2e/brukere/users.cy.ts @@ -1,6 +1,6 @@ import {wait} from "@testing-library/user-event/dist/utils"; -describe('Check the user page with no backend', () => { +describe('Check the user page', () => { const searchText = 'TEST'; const userType = 'STUDENT'; diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts index 64533b0..646f2ed 100644 --- a/cypress/support/commands.ts +++ b/cypress/support/commands.ts @@ -66,7 +66,7 @@ export function goToHome() { Cypress.Commands.add("goToHome", goToHome) export function goToUser() { - return cy.visit('http://localhost:3000/beta/fintlabs-no/users/442'); + return cy.visit('http://localhost:3000/beta/fintlabs-no/users/442/orgunit/194'); } Cypress.Commands.add('goToInfo', goToUser)