forked from baron/baron-sso
org chart 연동기능 추가
This commit is contained in:
@@ -63,6 +63,13 @@ export type TenantUpdateRequest = {
|
||||
config?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type TenantImportResult = {
|
||||
created: number;
|
||||
updated: number;
|
||||
failed: number;
|
||||
errors: string[];
|
||||
};
|
||||
|
||||
export type ApiKeySummary = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -145,6 +152,36 @@ export async function deleteTenantsBulk(ids: string[]) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function exportTenantsCSV() {
|
||||
const response = await apiClient.get<Blob>("/v1/admin/tenants/export", {
|
||||
responseType: "blob",
|
||||
});
|
||||
const dispositionHeader = response.headers["content-disposition"];
|
||||
const disposition = Array.isArray(dispositionHeader)
|
||||
? dispositionHeader[0]
|
||||
: String(dispositionHeader ?? "");
|
||||
const filenameMatch = disposition?.match(/filename="?([^"]+)"?/i);
|
||||
return {
|
||||
blob: response.data,
|
||||
filename: filenameMatch?.[1] ?? "tenants.csv",
|
||||
};
|
||||
}
|
||||
|
||||
export async function importTenantsCSV(file: File) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
const { data } = await apiClient.post<TenantImportResult>(
|
||||
"/v1/admin/tenants/import",
|
||||
formData,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
},
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function approveTenant(tenantId: string) {
|
||||
const { data } = await apiClient.post<TenantSummary>(
|
||||
`/v1/admin/tenants/${tenantId}/approve`,
|
||||
@@ -266,44 +303,6 @@ export async function removeGroupMember(
|
||||
);
|
||||
}
|
||||
|
||||
export interface ImportResult {
|
||||
totalRows: number;
|
||||
processed: number;
|
||||
userCreated: number;
|
||||
userUpdated: number;
|
||||
tenantCreated: number;
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export async function fetchImportProgress(
|
||||
tenantId: string,
|
||||
progressId: string,
|
||||
) {
|
||||
const { data } = await apiClient.get<{ current: number; total: number }>(
|
||||
`/v1/admin/tenants/${tenantId}/organization/import/progress/${progressId}`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function importOrgChart(
|
||||
tenantId: string,
|
||||
file: File,
|
||||
progressId?: string,
|
||||
) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
const url = progressId
|
||||
? `/v1/admin/tenants/${tenantId}/organization/import?progressId=${progressId}`
|
||||
: `/v1/admin/tenants/${tenantId}/organization/import`;
|
||||
|
||||
const { data } = await apiClient.post<{ data: ImportResult }>(url, formData, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
return data.data;
|
||||
}
|
||||
|
||||
export type GroupRole = {
|
||||
tenantId: string;
|
||||
tenantName: string;
|
||||
@@ -412,6 +411,10 @@ export type UserCreateRequest = {
|
||||
department?: string;
|
||||
position?: string;
|
||||
jobTitle?: string;
|
||||
primaryTenantId?: string;
|
||||
primaryTenantName?: string;
|
||||
primaryTenantIsOwner?: boolean;
|
||||
additionalAppointments?: UserAppointment[];
|
||||
metadata?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
@@ -430,9 +433,22 @@ export type UserUpdateRequest = {
|
||||
department?: string;
|
||||
position?: string;
|
||||
jobTitle?: string;
|
||||
primaryTenantId?: string;
|
||||
primaryTenantName?: string;
|
||||
primaryTenantIsOwner?: boolean;
|
||||
additionalAppointments?: UserAppointment[];
|
||||
metadata?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type UserAppointment = {
|
||||
tenantId: string;
|
||||
tenantSlug?: string;
|
||||
tenantName: string;
|
||||
isOwner: boolean;
|
||||
jobTitle?: string;
|
||||
position?: string;
|
||||
};
|
||||
|
||||
export type BulkUserItem = {
|
||||
email: string;
|
||||
loginId?: string;
|
||||
@@ -492,19 +508,20 @@ export async function createUser(payload: UserCreateRequest) {
|
||||
return data;
|
||||
}
|
||||
|
||||
export function exportUsersCSVUrl(search?: string, tenantSlug?: string) {
|
||||
const params = new URLSearchParams();
|
||||
if (search) params.append("search", search);
|
||||
if (tenantSlug) params.append("tenantSlug", tenantSlug);
|
||||
|
||||
// Get mock role from storage if exists for dev environment
|
||||
const isMockRoleEnabled =
|
||||
window.localStorage.getItem("X-Mock-Role-Enabled") === "true";
|
||||
const mockRole = window.localStorage.getItem("X-Mock-Role");
|
||||
if (isMockRoleEnabled && mockRole) params.append("x-test-role", mockRole);
|
||||
|
||||
const baseUrl = import.meta.env.VITE_ADMIN_API_BASE ?? "/api/v1";
|
||||
return `${baseUrl}/admin/users/export?${params.toString()}`;
|
||||
export async function exportUsersCSV(search?: string, tenantSlug?: string) {
|
||||
const response = await apiClient.get<Blob>("/v1/admin/users/export", {
|
||||
params: { search, tenantSlug },
|
||||
responseType: "blob",
|
||||
});
|
||||
const dispositionHeader = response.headers["content-disposition"];
|
||||
const disposition = Array.isArray(dispositionHeader)
|
||||
? dispositionHeader[0]
|
||||
: String(dispositionHeader ?? "");
|
||||
const filenameMatch = disposition?.match(/filename="?([^"]+)"?/i);
|
||||
return {
|
||||
blob: response.data,
|
||||
filename: filenameMatch?.[1] ?? "users.csv",
|
||||
};
|
||||
}
|
||||
|
||||
export async function bulkCreateUsers(users: BulkUserItem[]) {
|
||||
|
||||
Reference in New Issue
Block a user