diff --git a/src/components/component/unknown-ad-groups-alert.tsx b/src/components/component/unknown-ad-groups-alert.tsx new file mode 100644 index 000000000..d6508a9b8 --- /dev/null +++ b/src/components/component/unknown-ad-groups-alert.tsx @@ -0,0 +1,22 @@ +import { Alert } from '../alert'; +import { List } from '@equinor/eds-core-react'; + +interface Props { + unknownADGroups?: Array; +} +export function UnknownADGroupsAlert({ unknownADGroups }: Props) { + return ( + <> + {unknownADGroups?.length > 0 && ( + + Unknown or deleted AD group(s) + + {unknownADGroups.map((adGroup) => ( + {adGroup} + ))} + + + )} + + ); +} diff --git a/src/components/graph/adGroups.tsx b/src/components/graph/adGroups.tsx index 8457d420c..08653069b 100644 --- a/src/components/graph/adGroups.tsx +++ b/src/components/graph/adGroups.tsx @@ -1,7 +1,7 @@ import { Typography } from '@equinor/eds-core-react'; import { debounce } from 'lodash'; import * as PropTypes from 'prop-types'; -import { ActionMeta, OnChangeValue } from 'react-select'; +import { ActionMeta, CSSObjectWithLabel, OnChangeValue } from 'react-select'; import AsyncSelect from 'react-select/async'; import { @@ -9,15 +9,18 @@ import { msGraphApi, useGetAdGroupsQuery, } from '../../store/ms-graph-api'; +import { UnknownADGroupsAlert } from '../component/unknown-ad-groups-alert'; import AsyncResource from '../async-resource/async-resource'; +type DisplayAdGroups = AdGroup & { deleted?: boolean }; + type SearchGroupFunctionType = ReturnType< typeof msGraphApi.endpoints.searchAdGroups.useLazyQuery >[0]; const loadOptions = debounce( ( - callback: (options: Array) => void, + callback: (options: Array) => void, searchGroup: SearchGroupFunctionType, value: string ) => filterOptions(searchGroup, value).then(callback), @@ -31,9 +34,19 @@ async function filterOptions( return (await searchGroups({ groupName, limit: 10 }).unwrap()).value; } +function selectValueStyle( + base: CSSObjectWithLabel, + props: { data: DisplayAdGroups } +): CSSObjectWithLabel { + if (props.data.deleted) { + base.backgroundColor = 'var(--eds_interactive_danger__highlight)'; + } + return base; +} + export type HandleAdGroupsChangeCB = ( - value: OnChangeValue, - actionMeta: ActionMeta + value: OnChangeValue, + actionMeta: ActionMeta ) => void; interface Props { handleAdGroupsChange: HandleAdGroupsChangeCB; @@ -49,37 +62,48 @@ export function ADGroups({ ids: adGroups ?? [], }); const [searchGroups] = msGraphApi.endpoints.searchAdGroups.useLazyQuery(); + const displayGroups = adGroups + ?.map((id) => ({ id, info: groupsInfo?.find((g) => g.id === id) })) + .map((g) => ({ + id: g.id, + displayName: g.info?.displayName ?? g.id, + deleted: !g.info, + })); + + const unknownADGroups = adGroups?.filter( + (adGroupId) => !groupsInfo?.some((adGroup) => adGroup.id === adGroupId) + ); return ( - {groupsInfo && ( - <> - { - const target = e.target as HTMLInputElement; - return ( - target?.parentElement?.className && - !target.parentElement.className.match(/menu/) - ); - }} - noOptionsMessage={() => null} - loadOptions={(inputValue, callback) => { - inputValue?.length < 3 - ? callback([]) - : loadOptions(callback, searchGroups, inputValue); - }} - onChange={handleAdGroupsChange} - getOptionLabel={({ displayName }) => displayName} - getOptionValue={({ id }) => id} - closeMenuOnSelect={false} - defaultValue={groupsInfo} - isDisabled={isDisabled} - /> - - )} + { + const target = e.target as HTMLInputElement; + return ( + target?.parentElement?.className && + !target.parentElement.className.match(/menu/) + ); + }} + noOptionsMessage={() => null} + loadOptions={(inputValue, callback) => { + inputValue?.length < 3 + ? callback([]) + : loadOptions(callback, searchGroups, inputValue); + }} + onChange={handleAdGroupsChange} + getOptionLabel={({ displayName }) => displayName} + getOptionValue={({ id }) => id} + closeMenuOnSelect={false} + defaultValue={displayGroups} + isDisabled={isDisabled} + styles={{ + multiValueLabel: selectValueStyle, + multiValueRemove: selectValueStyle, + }} + /> Azure Active Directory groups (type 3 characters to search) + {!state.isFetching && unknownADGroups?.length > 0 && ( + + )} ); } diff --git a/src/components/page-configuration/change-admin-form.tsx b/src/components/page-configuration/change-admin-form.tsx index ebdf3584c..2d57ca119 100644 --- a/src/components/page-configuration/change-admin-form.tsx +++ b/src/components/page-configuration/change-admin-form.tsx @@ -58,7 +58,7 @@ export default function ChangeAdminForm({ registration, refetch }: Props) { return ( - + Access control diff --git a/src/components/page-configuration/overview.tsx b/src/components/page-configuration/overview.tsx index 3e12a3c26..1c0ffa81c 100644 --- a/src/components/page-configuration/overview.tsx +++ b/src/components/page-configuration/overview.tsx @@ -1,9 +1,15 @@ -import { List, Tooltip, Typography } from '@equinor/eds-core-react'; +import { + CircularProgress, + List, + Tooltip, + Typography, +} from '@equinor/eds-core-react'; import * as PropTypes from 'prop-types'; import { Alert } from '../alert'; -import AsyncResource from '../async-resource/async-resource'; import { useGetAdGroupsQuery } from '../../store/ms-graph-api'; +import { UnknownADGroupsAlert } from '../component/unknown-ad-groups-alert'; +import AsyncResource from '../async-resource/async-resource'; interface Props { adGroups?: Array; @@ -12,6 +18,9 @@ interface Props { export function Overview({ adGroups, appName }: Props) { const { data, ...state } = useGetAdGroupsQuery({ ids: adGroups }); + const unknownADGroups = adGroups?.filter( + (adGroupId) => !data?.some((adGroup) => adGroup.id === adGroupId) + ); return (
@@ -32,22 +41,33 @@ export function Overview({ adGroups, appName }: Props) { {' '} groups): - - - {data?.map(({ id, displayName }) => ( - - - {displayName} - - - ))} - - + {state.isLoading ? ( + <> + Updating… + + ) : ( + + + {data?.map(({ id, displayName }) => ( + + + {displayName} + + + ))} + + {!state.isFetching && unknownADGroups?.length > 0 && ( + + )} + + )} ) : ( diff --git a/src/store/ms-graph-api.ts b/src/store/ms-graph-api.ts index bf388c588..24b9f8a66 100644 --- a/src/store/ms-graph-api.ts +++ b/src/store/ms-graph-api.ts @@ -97,7 +97,6 @@ type GetAdGroupArg = { }; type GetAdGroupResponse = AdGroup; export type AdGroup = { - '@odaga.context': string; displayName: string; id: string; };