Просмотр исходного кода

refs 125405: separate UserGroup ExternalUserGroup stores

Futa Arai 2 лет назад
Родитель
Сommit
ce4cba6808

+ 55 - 0
apps/app/src/client/services/user-group.ts

@@ -0,0 +1,55 @@
+import { IUserGroupHasId, IUserGroupRelationHasId } from '@growi/core';
+import { SWRResponse } from 'swr';
+
+import {
+  useSWRxAncestorExternalUserGroups,
+  useSWRxChildExternalUserGroupList,
+  useSWRxExternalUserGroup,
+  useSWRxExternalUserGroupRelationList,
+  useSWRxExternalUserGroupRelations,
+} from '~/features/external-user-group/client/stores/external-user-group';
+import { IExternalUserGroupHasId, IExternalUserGroupRelationHasId } from '~/features/external-user-group/interfaces/external-user-group';
+import { ChildUserGroupListResult, IUserGroupRelationHasIdPopulatedUser } from '~/interfaces/user-group-response';
+import {
+  useSWRxAncestorUserGroups,
+  useSWRxChildUserGroupList, useSWRxUserGroup, useSWRxUserGroupRelationList, useSWRxUserGroupRelations,
+} from '~/stores/user-group';
+
+export const useUserGroup = (userGroupId: string, isExternalGroup: boolean):
+SWRResponse<IUserGroupHasId, Error, any> | SWRResponse<IExternalUserGroupHasId, Error, any> => {
+  const userGroupRes = useSWRxUserGroup(isExternalGroup ? null : userGroupId);
+  const externalUserGroupRes = useSWRxExternalUserGroup(isExternalGroup ? userGroupId : null);
+  return isExternalGroup ? externalUserGroupRes : userGroupRes;
+};
+
+export const useUserGroupRelations = (userGroupId: string, isExternalGroup: boolean):
+SWRResponse<IUserGroupRelationHasIdPopulatedUser[], Error, any> => {
+  const userGroupRes = useSWRxUserGroupRelations(isExternalGroup ? null : userGroupId);
+  const externalUserGroupRes = useSWRxExternalUserGroupRelations(isExternalGroup ? userGroupId : null);
+  return isExternalGroup ? externalUserGroupRes : userGroupRes;
+};
+
+export const useChildUserGroupList = (userGroupId: string, isExternalGroup: boolean):
+SWRResponse<ChildUserGroupListResult, Error, any> | SWRResponse<ChildUserGroupListResult<IExternalUserGroupHasId>, Error, any> => {
+  const userGroupRes = useSWRxChildUserGroupList(
+    !isExternalGroup ? [userGroupId] : [], true,
+  );
+  const externalUserGroupRes = useSWRxChildExternalUserGroupList(
+    isExternalGroup ? [userGroupId] : [], true,
+  );
+  return isExternalGroup ? externalUserGroupRes : userGroupRes;
+};
+
+export const useUserGroupRelationList = (userGroupIds: string[], isExternalGroup: boolean):
+SWRResponse<IUserGroupRelationHasId[], Error, any> | SWRResponse<IExternalUserGroupRelationHasId[], Error, any> => {
+  const userGroupRes = useSWRxUserGroupRelationList(isExternalGroup ? null : userGroupIds);
+  const externalUserGroupRes = useSWRxExternalUserGroupRelationList(isExternalGroup ? userGroupIds : null);
+  return isExternalGroup ? externalUserGroupRes : userGroupRes;
+};
+
+export const useAncestorUserGroups = (userGroupId: string, isExternalGroup: boolean):
+SWRResponse<IUserGroupHasId[], Error, any> | SWRResponse<IExternalUserGroupHasId[], Error, any> => {
+  const userGroupRes = useSWRxAncestorUserGroups(isExternalGroup ? null : userGroupId);
+  const externalUserGroupRes = useSWRxAncestorExternalUserGroups(isExternalGroup ? userGroupId : null);
+  return isExternalGroup ? externalUserGroupRes : userGroupRes;
+};

+ 20 - 19
apps/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -8,6 +8,10 @@ import dynamic from 'next/dynamic';
 import Link from 'next/link';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
 
 
+import {
+  useAncestorUserGroups,
+  useChildUserGroupList, useUserGroup, useUserGroupRelationList, useUserGroupRelations,
+} from '~/client/services/user-group';
 import {
 import {
   apiv3Get, apiv3Put, apiv3Delete, apiv3Post,
   apiv3Get, apiv3Put, apiv3Delete, apiv3Post,
 } from '~/client/util/apiv3-client';
 } from '~/client/util/apiv3-client';
@@ -17,10 +21,7 @@ import { SearchTypes, SearchType } from '~/interfaces/user-group';
 import Xss from '~/services/xss';
 import Xss from '~/services/xss';
 import { useIsAclEnabled } from '~/stores/context';
 import { useIsAclEnabled } from '~/stores/context';
 import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
 import { useUpdateUserGroupConfirmModal } from '~/stores/modal';
-import {
-  useSWRxUserGroupPages, useSWRxUserGroupRelationList, useSWRxChildUserGroupList, useSWRxUserGroup,
-  useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups, useSWRxAncestorUserGroups, useSWRxUserGroupRelations,
-} from '~/stores/user-group';
+import { useSWRxUserGroupPages, useSWRxSelectableParentUserGroups, useSWRxSelectableChildUserGroups } from '~/stores/user-group';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 import styles from './UserGroupDetailPage.module.scss';
 import styles from './UserGroupDetailPage.module.scss';
@@ -51,7 +52,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
   const xss = useMemo(() => new Xss(), []);
   const xss = useMemo(() => new Xss(), []);
   const { userGroupId: currentUserGroupId, isExternalGroup } = props;
   const { userGroupId: currentUserGroupId, isExternalGroup } = props;
 
 
-  const { data: currentUserGroup } = useSWRxUserGroup(currentUserGroupId, isExternalGroup);
+  const { data: currentUserGroup } = useUserGroup(currentUserGroupId, isExternalGroup);
 
 
   const [searchType, setSearchType] = useState<SearchType>(SearchTypes.PARTIAL);
   const [searchType, setSearchType] = useState<SearchType>(SearchTypes.PARTIAL);
   const [isAlsoMailSearched, setAlsoMailSearched] = useState<boolean>(false);
   const [isAlsoMailSearched, setAlsoMailSearched] = useState<boolean>(false);
@@ -77,24 +78,24 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
    */
    */
   const { data: userGroupPages } = useSWRxUserGroupPages(currentUserGroupId, 10, 0);
   const { data: userGroupPages } = useSWRxUserGroupPages(currentUserGroupId, 10, 0);
 
 
-  const { data: userGroupRelations, mutate: mutateUserGroupRelations } = useSWRxUserGroupRelations(currentUserGroupId, isExternalGroup);
+  const { data: userGroupRelations, mutate: mutateUserGroupRelations } = useUserGroupRelations(currentUserGroupId, isExternalGroup);
 
 
-  const { data: childUserGroupsList, mutate: mutateChildUserGroups } = useSWRxChildUserGroupList(
-    currentUserGroupId ? [currentUserGroupId] : [], true, isExternalGroup,
-  );
+  const { data: childUserGroupsList, mutate: mutateChildUserGroups } = useChildUserGroupList(currentUserGroupId, isExternalGroup);
   const childUserGroups = childUserGroupsList != null ? childUserGroupsList.childUserGroups : [];
   const childUserGroups = childUserGroupsList != null ? childUserGroupsList.childUserGroups : [];
   const grandChildUserGroups = childUserGroupsList != null ? childUserGroupsList.grandChildUserGroups : [];
   const grandChildUserGroups = childUserGroupsList != null ? childUserGroupsList.grandChildUserGroups : [];
   const childUserGroupIds = childUserGroups.map(group => group._id);
   const childUserGroupIds = childUserGroups.map(group => group._id);
 
 
-  const { data: userGroupRelationList, mutate: mutateUserGroupRelationList } = useSWRxUserGroupRelationList(
-    childUserGroupIds, undefined, undefined, isExternalGroup,
-  );
+  const { data: userGroupRelationList, mutate: mutateUserGroupRelationList } = useUserGroupRelationList(childUserGroupIds, isExternalGroup);
   const childUserGroupRelations = userGroupRelationList != null ? userGroupRelationList : [];
   const childUserGroupRelations = userGroupRelationList != null ? userGroupRelationList : [];
 
 
-  const { data: selectableParentUserGroups, mutate: mutateSelectableParentUserGroups } = useSWRxSelectableParentUserGroups(currentUserGroupId);
-  const { data: selectableChildUserGroups, mutate: mutateSelectableChildUserGroups } = useSWRxSelectableChildUserGroups(currentUserGroupId);
+  const { data: selectableParentUserGroups, mutate: mutateSelectableParentUserGroups } = useSWRxSelectableParentUserGroups(
+    isExternalGroup ? null : currentUserGroupId,
+  );
+  const { data: selectableChildUserGroups, mutate: mutateSelectableChildUserGroups } = useSWRxSelectableChildUserGroups(
+    isExternalGroup ? null : currentUserGroupId,
+  );
 
 
-  const { data: ancestorUserGroups, mutate: mutateAncestorUserGroups } = useSWRxAncestorUserGroups(currentUserGroupId, isExternalGroup);
+  const { data: ancestorUserGroups, mutate: mutateAncestorUserGroups } = useAncestorUserGroups(currentUserGroupId, isExternalGroup);
 
 
   const { data: isAclEnabled } = useIsAclEnabled();
   const { data: isAclEnabled } = useIsAclEnabled();
 
 
@@ -388,7 +389,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
           selectableParentUserGroups={selectableParentUserGroups}
           selectableParentUserGroups={selectableParentUserGroups}
           submitButtonLabel={t('Update')}
           submitButtonLabel={t('Update')}
           onSubmit={onClickSubmitForm}
           onSubmit={onClickSubmitForm}
-          isExternalGroup
+          isExternalGroup={isExternalGroup}
         />
         />
       </div>
       </div>
       <h2 className="admin-setting-header mt-4">{t('user_group_management.user_list')}</h2>
       <h2 className="admin-setting-header mt-4">{t('user_group_management.user_list')}</h2>
@@ -396,7 +397,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         userGroupRelations={userGroupRelations}
         userGroupRelations={userGroupRelations}
         onClickPlusBtn={() => setIsUserGroupUserModalShown(true)}
         onClickPlusBtn={() => setIsUserGroupUserModalShown(true)}
         onClickRemoveUserBtn={removeUserByUsername}
         onClickRemoveUserBtn={removeUserByUsername}
-        isExternalGroup
+        isExternalGroup={isExternalGroup}
       />
       />
       <UserGroupUserModal
       <UserGroupUserModal
         isOpen={isUserGroupUserModalShown}
         isOpen={isUserGroupUserModalShown}
@@ -425,7 +426,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         onClickSubmit={updateChildUserGroup}
         onClickSubmit={updateChildUserGroup}
         isShow={isUpdateModalShown}
         isShow={isUpdateModalShown}
         onHide={hideUpdateModal}
         onHide={hideUpdateModal}
-        isExternalGroup
+        isExternalGroup={isExternalGroup}
       />
       />
 
 
       <UserGroupModal
       <UserGroupModal
@@ -445,7 +446,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         onRemove={removeChildUserGroup}
         onRemove={removeChildUserGroup}
         onDelete={showDeleteModal}
         onDelete={showDeleteModal}
         userGroupRelations={childUserGroupRelations}
         userGroupRelations={childUserGroupRelations}
-        isExternalGroup
+        isExternalGroup={isExternalGroup}
       />
       />
 
 
       <UserGroupDeleteModal
       <UserGroupDeleteModal

+ 5 - 4
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/ExternalUserGroupManagement.tsx

@@ -13,19 +13,20 @@ import { UserGroupTable } from '~/components/Admin/UserGroup/UserGroupTable';
 import CustomNav from '~/components/CustomNavigation/CustomNav';
 import CustomNav from '~/components/CustomNavigation/CustomNav';
 import { IExternalUserGroupHasId } from '~/features/external-user-group/interfaces/external-user-group';
 import { IExternalUserGroupHasId } from '~/features/external-user-group/interfaces/external-user-group';
 import { useIsAclEnabled } from '~/stores/context';
 import { useIsAclEnabled } from '~/stores/context';
-import { useSWRxChildUserGroupList, useSWRxUserGroupList, useSWRxUserGroupRelationList } from '~/stores/user-group';
+
+import { useSWRxChildExternalUserGroupList, useSWRxExternalUserGroupList, useSWRxExternalUserGroupRelationList } from '../../stores/external-user-group';
 
 
 import { LdapGroupManagement } from './LdapGroupManagement';
 import { LdapGroupManagement } from './LdapGroupManagement';
 
 
 export const ExternalGroupManagement: FC = () => {
 export const ExternalGroupManagement: FC = () => {
-  const { data: externalUserGroupList, mutate: mutateExternalUserGroups } = useSWRxUserGroupList(undefined, true);
+  const { data: externalUserGroupList, mutate: mutateExternalUserGroups } = useSWRxExternalUserGroupList();
   const externalUserGroups = externalUserGroupList != null ? externalUserGroupList : [];
   const externalUserGroups = externalUserGroupList != null ? externalUserGroupList : [];
   const externalUserGroupIds = externalUserGroups.map(group => group._id);
   const externalUserGroupIds = externalUserGroups.map(group => group._id);
 
 
-  const { data: externalUserGroupRelationList } = useSWRxUserGroupRelationList(externalUserGroupIds, undefined, undefined, true);
+  const { data: externalUserGroupRelationList } = useSWRxExternalUserGroupRelationList(externalUserGroupIds);
   const externalUserGroupRelations = externalUserGroupRelationList != null ? externalUserGroupRelationList : [];
   const externalUserGroupRelations = externalUserGroupRelationList != null ? externalUserGroupRelationList : [];
 
 
-  const { data: childExternalUserGroupsList } = useSWRxChildUserGroupList(externalUserGroupIds, false, true);
+  const { data: childExternalUserGroupsList } = useSWRxChildExternalUserGroupList(externalUserGroupIds);
   const childExternalUserGroups = childExternalUserGroupsList?.childUserGroups != null ? childExternalUserGroupsList.childUserGroups : [];
   const childExternalUserGroups = childExternalUserGroupsList?.childUserGroups != null ? childExternalUserGroupsList.childUserGroups : [];
 
 
   const { data: isAclEnabled } = useIsAclEnabled();
   const { data: isAclEnabled } = useIsAclEnabled();

+ 60 - 1
apps/app/src/features/external-user-group/client/stores/external-user-group.ts

@@ -1,7 +1,9 @@
 import useSWR, { SWRResponse } from 'swr';
 import useSWR, { SWRResponse } from 'swr';
+import useSWRImmutable from 'swr/immutable';
 
 
 import { apiv3Get } from '~/client/util/apiv3-client';
 import { apiv3Get } from '~/client/util/apiv3-client';
-import { LdapGroupSyncSettings } from '~/features/external-user-group/interfaces/external-user-group';
+import { IExternalUserGroupHasId, IExternalUserGroupRelationHasId, LdapGroupSyncSettings } from '~/features/external-user-group/interfaces/external-user-group';
+import { ChildUserGroupListResult, IUserGroupRelationHasIdPopulatedUser, UserGroupRelationListResult } from '~/interfaces/user-group-response';
 
 
 export const useSWRxLdapGroupSyncSettings = (): SWRResponse<LdapGroupSyncSettings, Error> => {
 export const useSWRxLdapGroupSyncSettings = (): SWRResponse<LdapGroupSyncSettings, Error> => {
   return useSWR(
   return useSWR(
@@ -11,3 +13,60 @@ export const useSWRxLdapGroupSyncSettings = (): SWRResponse<LdapGroupSyncSetting
     }),
     }),
   );
   );
 };
 };
+
+export const useSWRxExternalUserGroup = (groupId: string | null): SWRResponse<IExternalUserGroupHasId, Error> => {
+  return useSWRImmutable(
+    groupId != null ? `/external-user-groups/${groupId}` : null,
+    endpoint => apiv3Get(endpoint).then(result => result.data.userGroup),
+  );
+};
+
+export const useSWRxExternalUserGroupList = (initialData?: IExternalUserGroupHasId[]): SWRResponse<IExternalUserGroupHasId[], Error> => {
+  return useSWRImmutable(
+    '/external-user-groups',
+    endpoint => apiv3Get(endpoint, { pagination: false }).then(result => result.data.userGroups),
+    {
+      fallbackData: initialData,
+    },
+  );
+};
+
+export const useSWRxChildExternalUserGroupList = (
+    parentIds?: string[], includeGrandChildren?: boolean,
+): SWRResponse<ChildUserGroupListResult<IExternalUserGroupHasId>, Error> => {
+  const shouldFetch = parentIds != null && parentIds.length > 0;
+  return useSWRImmutable(
+    shouldFetch ? ['/external-user-groups/children', parentIds, includeGrandChildren] : null,
+    ([endpoint, parentIds, includeGrandChildren]) => apiv3Get<ChildUserGroupListResult<IExternalUserGroupHasId>>(
+      endpoint, { parentIds, includeGrandChildren },
+    ).then((result => result.data)),
+  );
+};
+
+export const useSWRxExternalUserGroupRelations = (groupId: string | null): SWRResponse<IUserGroupRelationHasIdPopulatedUser[], Error> => {
+  return useSWRImmutable(
+    groupId != null ? `/external-user-groups/${groupId}/external-user-group-relations` : null,
+    endpoint => apiv3Get(endpoint).then(result => result.data.userGroupRelations),
+  );
+};
+
+export const useSWRxExternalUserGroupRelationList = (
+    groupIds: string[] | null, childGroupIds?: string[], initialData?: IExternalUserGroupRelationHasId[],
+): SWRResponse<IExternalUserGroupRelationHasId[], Error> => {
+  return useSWRImmutable(
+    groupIds != null ? ['/external-user-group-relations', groupIds, childGroupIds] : null,
+    ([endpoint, groupIds, childGroupIds]) => apiv3Get<UserGroupRelationListResult<IExternalUserGroupRelationHasId>>(
+      endpoint, { groupIds, childGroupIds },
+    ).then(result => result.data.userGroupRelations),
+    {
+      fallbackData: initialData,
+    },
+  );
+};
+
+export const useSWRxAncestorExternalUserGroups = (groupId: string | null): SWRResponse<IExternalUserGroupHasId[], Error> => {
+  return useSWRImmutable(
+    groupId != null ? ['/external-user-groups/ancestors', groupId] : null,
+    ([endpoint, groupId]) => apiv3Get(endpoint, { groupId }).then(result => result.data.ancestorUserGroups),
+  );
+};

+ 7 - 7
apps/app/src/interfaces/user-group-response.ts

@@ -13,17 +13,17 @@ export type UserGroupListResult = {
   userGroups: IUserGroupHasId[],
   userGroups: IUserGroupHasId[],
 };
 };
 
 
-export type ChildUserGroupListResult = {
-  childUserGroups: IUserGroupHasId[],
-  grandChildUserGroups: IUserGroupHasId[],
+export type ChildUserGroupListResult<TUSERGROUP extends IUserGroupHasId = IUserGroupHasId> = {
+  childUserGroups: TUSERGROUP[],
+  grandChildUserGroups: TUSERGROUP[],
 };
 };
 
 
-export type UserGroupRelationListResult = {
-  userGroupRelations: IUserGroupRelationHasId[],
+export type UserGroupRelationListResult<TUSERGROUPRELATION extends IUserGroupRelationHasId = IUserGroupRelationHasId> = {
+  userGroupRelations: TUSERGROUPRELATION[],
 };
 };
 
 
-export type IUserGroupRelationHasIdPopulatedUser = {
-  relatedGroup: Ref<IUserGroup>,
+export type IUserGroupRelationHasIdPopulatedUser<TUSERGROUP extends IUserGroup = IUserGroup> = {
+  relatedGroup: Ref<TUSERGROUP>,
   relatedUser: IUserHasId,
   relatedUser: IUserHasId,
   createdAt: Date,
   createdAt: Date,
 } & HasObjectId;
 } & HasObjectId;

+ 12 - 17
apps/app/src/stores/user-group.tsx

@@ -23,10 +23,9 @@ export const useSWRxMyUserGroupRelations = (shouldFetch: boolean): SWRResponse<I
   );
   );
 };
 };
 
 
-export const useSWRxUserGroup = (groupId: string | undefined, isExternalGroup = false): SWRResponse<IUserGroupHasId, Error> => {
-  const url = isExternalGroup ? `/external-user-groups/${groupId}` : `/user-groups/${groupId}`;
+export const useSWRxUserGroup = (groupId: string | null): SWRResponse<IUserGroupHasId, Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
-    groupId != null ? url : null,
+    groupId != null ? `/user-groups/${groupId}` : null,
     endpoint => apiv3Get<UserGroupResult>(endpoint).then(result => result.data.userGroup),
     endpoint => apiv3Get<UserGroupResult>(endpoint).then(result => result.data.userGroup),
   );
   );
 };
 };
@@ -43,32 +42,29 @@ export const useSWRxUserGroupList = (initialData?: IUserGroupHasId[], isExternal
 };
 };
 
 
 export const useSWRxChildUserGroupList = (
 export const useSWRxChildUserGroupList = (
-    parentIds?: string[], includeGrandChildren?: boolean, isExternalGroup = false,
+    parentIds?: string[], includeGrandChildren?: boolean,
 ): SWRResponse<ChildUserGroupListResult, Error> => {
 ): SWRResponse<ChildUserGroupListResult, Error> => {
   const shouldFetch = parentIds != null && parentIds.length > 0;
   const shouldFetch = parentIds != null && parentIds.length > 0;
-  const url = isExternalGroup ? '/external-user-groups/children' : '/user-groups/children';
   return useSWRImmutable(
   return useSWRImmutable(
-    shouldFetch ? [url, parentIds, includeGrandChildren] : null,
+    shouldFetch ? ['/user-groups/children', parentIds, includeGrandChildren] : null,
     ([endpoint, parentIds, includeGrandChildren]) => apiv3Get<ChildUserGroupListResult>(
     ([endpoint, parentIds, includeGrandChildren]) => apiv3Get<ChildUserGroupListResult>(
       endpoint, { parentIds, includeGrandChildren },
       endpoint, { parentIds, includeGrandChildren },
     ).then((result => result.data)),
     ).then((result => result.data)),
   );
   );
 };
 };
 
 
-export const useSWRxUserGroupRelations = (groupId: string, isExternalGroup = false): SWRResponse<IUserGroupRelationHasIdPopulatedUser[], Error> => {
-  const url = isExternalGroup ? `/external-user-groups/${groupId}/external-user-group-relations` : `/user-groups/${groupId}/user-group-relations`;
+export const useSWRxUserGroupRelations = (groupId: string | null): SWRResponse<IUserGroupRelationHasIdPopulatedUser[], Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
-    groupId != null ? url : null,
+    groupId != null ? `/user-groups/${groupId}/user-group-relations` : null,
     endpoint => apiv3Get<UserGroupRelationsResult>(endpoint).then(result => result.data.userGroupRelations),
     endpoint => apiv3Get<UserGroupRelationsResult>(endpoint).then(result => result.data.userGroupRelations),
   );
   );
 };
 };
 
 
 export const useSWRxUserGroupRelationList = (
 export const useSWRxUserGroupRelationList = (
-    groupIds: string[] | undefined, childGroupIds?: string[], initialData?: IUserGroupRelationHasId[], isExternalGroup = false,
+    groupIds: string[] | null, childGroupIds?: string[], initialData?: IUserGroupRelationHasId[],
 ): SWRResponse<IUserGroupRelationHasId[], Error> => {
 ): SWRResponse<IUserGroupRelationHasId[], Error> => {
-  const url = isExternalGroup ? '/external-user-group-relations' : '/user-group-relations';
   return useSWRImmutable(
   return useSWRImmutable(
-    groupIds != null ? [url, groupIds, childGroupIds] : null,
+    groupIds != null ? ['/user-group-relations', groupIds, childGroupIds] : null,
     ([endpoint, groupIds, childGroupIds]) => apiv3Get<UserGroupRelationListResult>(
     ([endpoint, groupIds, childGroupIds]) => apiv3Get<UserGroupRelationListResult>(
       endpoint, { groupIds, childGroupIds },
       endpoint, { groupIds, childGroupIds },
     ).then(result => result.data.userGroupRelations),
     ).then(result => result.data.userGroupRelations),
@@ -85,24 +81,23 @@ export const useSWRxUserGroupPages = (groupId: string | undefined, limit: number
   );
   );
 };
 };
 
 
-export const useSWRxSelectableParentUserGroups = (groupId: string | undefined): SWRResponse<IUserGroupHasId[], Error> => {
+export const useSWRxSelectableParentUserGroups = (groupId: string | null): SWRResponse<IUserGroupHasId[], Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
     groupId != null ? ['/user-groups/selectable-parent-groups', groupId] : null,
     groupId != null ? ['/user-groups/selectable-parent-groups', groupId] : null,
     ([endpoint, groupId]) => apiv3Get<SelectableParentUserGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableParentGroups),
     ([endpoint, groupId]) => apiv3Get<SelectableParentUserGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableParentGroups),
   );
   );
 };
 };
 
 
-export const useSWRxSelectableChildUserGroups = (groupId: string | undefined): SWRResponse<IUserGroupHasId[], Error> => {
+export const useSWRxSelectableChildUserGroups = (groupId: string | null): SWRResponse<IUserGroupHasId[], Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
     groupId != null ? ['/user-groups/selectable-child-groups', groupId] : null,
     groupId != null ? ['/user-groups/selectable-child-groups', groupId] : null,
     ([endpoint, groupId]) => apiv3Get<SelectableUserChildGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableChildGroups),
     ([endpoint, groupId]) => apiv3Get<SelectableUserChildGroupsResult>(endpoint, { groupId }).then(result => result.data.selectableChildGroups),
   );
   );
 };
 };
 
 
-export const useSWRxAncestorUserGroups = (groupId: string | undefined, isExternalGroup = false): SWRResponse<IUserGroupHasId[], Error> => {
-  const url = isExternalGroup ? '/external-user-groups/ancestors' : '/user-groups/ancestors';
+export const useSWRxAncestorUserGroups = (groupId: string | null): SWRResponse<IUserGroupHasId[], Error> => {
   return useSWRImmutable(
   return useSWRImmutable(
-    groupId != null ? [url, groupId] : null,
+    groupId != null ? ['/user-groups/ancestors', groupId] : null,
     ([endpoint, groupId]) => apiv3Get<AncestorUserGroupsResult>(endpoint, { groupId }).then(result => result.data.ancestorUserGroups),
     ([endpoint, groupId]) => apiv3Get<AncestorUserGroupsResult>(endpoint, { groupId }).then(result => result.data.ancestorUserGroups),
   );
   );
 };
 };