diff --git a/client/packages/lowcoder/src/components/PermissionDialog/DatasourcePermissionDialog.tsx b/client/packages/lowcoder/src/components/PermissionDialog/DatasourcePermissionDialog.tsx
index 9bad678a1..41273467a 100644
--- a/client/packages/lowcoder/src/components/PermissionDialog/DatasourcePermissionDialog.tsx
+++ b/client/packages/lowcoder/src/components/PermissionDialog/DatasourcePermissionDialog.tsx
@@ -13,6 +13,7 @@ import { DatasourceRole } from "../../api/datasourcePermissionApi";
import { getDataSourcePermissionInfo } from "../../redux/selectors/datasourceSelectors";
import { StyledLoading } from "./commonComponents";
import { PermissionRole } from "./Permission";
+import { getUser } from "../../redux/selectors/usersSelectors";
export const DatasourcePermissionDialog = (props: {
datasourceId: string;
@@ -22,6 +23,7 @@ export const DatasourcePermissionDialog = (props: {
const { datasourceId } = props;
const dispatch = useDispatch();
const permissionInfo = useSelector(getDataSourcePermissionInfo)[datasourceId];
+ const user = useSelector(getUser);
useEffect(() => {
dispatch(fetchDatasourcePermissions({ datasourceId: datasourceId }));
@@ -75,6 +77,8 @@ export const DatasourcePermissionDialog = (props: {
{ label: trans("share.datasourceOwner"), value: PermissionRole.Owner },
]}
permissionItems={permissions}
+ contextType="organization"
+ organizationId={user.currentOrgId}
viewBodyRender={(list) => {
if (!permissionInfo) {
return ;
diff --git a/client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx b/client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx
index adb9e9ffb..f6fffc37d 100644
--- a/client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx
+++ b/client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx
@@ -27,7 +27,7 @@ import { EmptyContent } from "pages/common/styledComponent";
import { trans } from "i18n";
import { PermissionItem } from "./PermissionList";
import { currentApplication } from "@lowcoder-ee/redux/selectors/applicationSelector";
-import { fetchAvailableGroupsMembers } from "@lowcoder-ee/util/pagination/axios";
+import { fetchAvailableGroupsMembers, fetchAvailableOrgGroupsMembers } from "@lowcoder-ee/util/pagination/axios";
const AddAppUserContent = styled.div`
display: flex;
@@ -186,6 +186,13 @@ const AddRoleSelect = styled(StyledRoleSelect)<{ $isVisible: boolean }>`
display: ${(props) => (props.$isVisible ? "unset" : "none")};
`;
+type PermissionContextType = "application" | "organization";
+
+type PermissionContextProps = {
+ contextType: PermissionContextType;
+ organizationId?: string;
+};
+
type AddAppOptionView = {
type: ApplicationPermissionType;
id: string;
@@ -294,8 +301,10 @@ const PermissionSelector = (props: {
user: User;
filterItems: PermissionItem[];
supportRoles: { label: string; value: PermissionRole }[];
+ contextType: PermissionContextType;
+ organizationId?: string;
}) => {
- const { selectedItems, setSelectRole, setSelectedItems, user } = props;
+ const { selectedItems, setSelectRole, setSelectedItems, user, contextType, organizationId } = props;
const [roleSelectVisible, setRoleSelectVisible] = useState(false);
const selectRef = useRef(null);
const [optionViews, setOptionViews] = useState()
@@ -305,42 +314,41 @@ const PermissionSelector = (props: {
const debouncedUserSearch = useCallback(
debounce((searchTerm: string) => {
- if (!application) return;
-
setIsLoading(true);
- fetchAvailableGroupsMembers(application.applicationId, searchTerm).then(res => {
- if(res.success) {
- setOptionViews(getPermissionOptionView(res.data, props.filterItems))
- }
- setIsLoading(false);
- }).catch(() => {
+
+ if (contextType === "application" && application) {
+ fetchAvailableGroupsMembers(application.applicationId, searchTerm).then(res => {
+ if(res.success) {
+ setOptionViews(getPermissionOptionView(res.data, props.filterItems))
+ }
+ setIsLoading(false);
+ }).catch(() => {
+ setIsLoading(false);
+ });
+ } else if (contextType === "organization" && organizationId) {
+ fetchAvailableOrgGroupsMembers(organizationId, searchTerm).then(res => {
+ if(res.success) {
+ setOptionViews(getPermissionOptionView(res.data || [], props.filterItems))
+ }
+ setIsLoading(false);
+ }).catch(() => {
+ setIsLoading(false);
+ });
+ } else {
setIsLoading(false);
- });
+ }
}, 500),
- [application, props.filterItems]
+ [application, props.filterItems, contextType, organizationId]
);
useEffect(() => {
debouncedUserSearch(searchValue);
-
return () => {
debouncedUserSearch.cancel();
};
}, [searchValue, debouncedUserSearch]);
- useEffect(() => {
- if (!application) return;
-
- setIsLoading(true);
- fetchAvailableGroupsMembers(application.applicationId, "").then(res => {
- if(res.success) {
- setOptionViews(getPermissionOptionView(res.data, props.filterItems))
- }
- setIsLoading(false);
- }).catch(() => {
- setIsLoading(false);
- });
- }, [application, props.filterItems]);
+
useEffect(() => {
setRoleSelectVisible(selectedItems.length > 0);
@@ -425,8 +433,8 @@ export const Permission = (props: {
supportRoles: { label: string; value: PermissionRole }[];
onCancel: () => void;
addPermission: (userIds: string[], groupIds: string[], role: string) => void;
-}) => {
- const { onCancel } = props;
+} & PermissionContextProps) => {
+ const { onCancel, contextType = "application", organizationId } = props;
const user = useSelector(getUser);
const [selectRole, setSelectRole] = useState("viewer");
const [selectedItems, setSelectedItems] = useState([]);
@@ -443,6 +451,8 @@ export const Permission = (props: {
user={user}
filterItems={props.filterItems}
supportRoles={props.supportRoles}
+ contextType={contextType}
+ organizationId={organizationId}
/>
diff --git a/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx b/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx
index b3645f788..42fb2a070 100644
--- a/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx
+++ b/client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx
@@ -57,8 +57,10 @@ export const PermissionDialog = (props: {
) => void;
updatePermission: (permissionId: string, role: string) => void;
deletePermission: (permissionId: string) => void;
+ contextType?: "application" | "organization";
+ organizationId?: string;
}) => {
- const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender } =
+ const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender, contextType, organizationId } =
props;
const [activeStepKey, setActiveStepKey] = useState("view");
@@ -117,6 +119,8 @@ export const PermissionDialog = (props: {
addPermission={(userIds, groupIds, role) =>
addPermission(userIds, groupIds, role, props.back)
}
+ contextType={contextType || "application"}
+ organizationId={organizationId}
/>
),
footerRender: (props) => null,
diff --git a/client/packages/lowcoder/src/util/pagination/axios.ts b/client/packages/lowcoder/src/util/pagination/axios.ts
index e59ccbfec..13a81157e 100644
--- a/client/packages/lowcoder/src/util/pagination/axios.ts
+++ b/client/packages/lowcoder/src/util/pagination/axios.ts
@@ -118,6 +118,60 @@ export const fetchAvailableGroupsMembers = async (applicationId: string, search:
}
}
+export const fetchAvailableOrgGroupsMembers = async (orgId: string, search: string = "") => {
+ try {
+
+
+ // Fetch org members and groups in parallel
+ const [orgMembersResponse, groupsResponse] = await Promise.all([
+ OrgApi.fetchOrgUsers(orgId),
+ OrgApi.fetchGroup()
+ ]);
+
+ const orgMembers = orgMembersResponse.data.data.members || [];
+ const groups = groupsResponse.data.data || [];
+
+ // Transform to the same format as application groups/members
+ const transformedData = [
+ // Add groups
+ ...groups.map((group: any) => ({
+ type: "Group",
+ data: {
+ groupId: group.groupId,
+ groupName: group.groupName,
+ }
+ })),
+ // Add users
+ ...orgMembers.map((member: any) => ({
+ type: "User",
+ data: {
+ userId: member.userId,
+ name: member.name,
+ avatarUrl: member.avatarUrl,
+ }
+ }))
+ ];
+
+ // Filter by search term if provided
+ const filteredData = search ?
+ transformedData.filter((item: any) => {
+ const name = item.type === "Group" ? item.data.groupName : item.data.name;
+ return name.toLowerCase().includes(search.toLowerCase());
+ }) : transformedData;
+
+ return {
+ success: true,
+ data: filteredData
+ };
+ } catch (error: any) {
+ console.error('Failed to fetch org data: ', error);
+ return {
+ success: false,
+ error: error
+ };
+ }
+}
+
export const fetchOrgUsrPagination = async (request: fetchOrgUserRequestType)=> {
try {
const response = await OrgApi.fetchOrgUsersPagination(request);