mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-07-10 22:32:16 +02:00
feat(rename): complete searchSpace to workspace transition across frontend and backend
- Introduced a comprehensive specification for renaming `searchSpace` to `workspace` in `surfsense_web` and `surfsense_desktop`, ensuring all TypeScript identifiers, React props, and local data structures are updated. - Implemented migration shims for persisted local state to prevent data loss during the transition. - Updated observability metrics and IPC channels to reflect the new naming convention. - Removed legacy `active-search-space` module and replaced it with `active-workspace` to maintain consistency. - Ensured no behavioral changes or data loss for users during the renaming process.
This commit is contained in:
parent
2a020629c5
commit
a8c1fb660d
259 changed files with 5480 additions and 2285 deletions
|
|
@ -39,7 +39,7 @@ export function AutoReloadSettings() {
|
|||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const queryClient = useQueryClient();
|
||||
const searchSpaceId = getWorkspaceIdNumber(params) ?? 0;
|
||||
const workspaceId = getWorkspaceIdNumber(params) ?? 0;
|
||||
|
||||
const [enabled, setEnabled] = useState(false);
|
||||
const [thresholdInput, setThresholdInput] = useState("");
|
||||
|
|
@ -79,8 +79,7 @@ export function AutoReloadSettings() {
|
|||
}, [searchParams, router, pathname, queryClient]);
|
||||
|
||||
const setupMutation = useMutation({
|
||||
mutationFn: () =>
|
||||
stripeApiService.createAutoReloadSetupSession({ workspace_id: searchSpaceId }),
|
||||
mutationFn: () => stripeApiService.createAutoReloadSetupSession({ workspace_id: workspaceId }),
|
||||
onSuccess: (response) => {
|
||||
window.location.assign(response.checkout_url);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const formatUsd = (micros: number) => {
|
|||
|
||||
export function BuyCreditsContent() {
|
||||
const params = useParams();
|
||||
const searchSpaceId = getWorkspaceIdNumber(params) ?? 0;
|
||||
const workspaceId = getWorkspaceIdNumber(params) ?? 0;
|
||||
const [quantity, setQuantity] = useState(1);
|
||||
// Raw text of the amount field so the user can clear it while typing;
|
||||
// committed back to a clamped integer on blur.
|
||||
|
|
@ -177,7 +177,7 @@ export function BuyCreditsContent() {
|
|||
<Button
|
||||
className="w-full"
|
||||
disabled={purchaseMutation.isPending}
|
||||
onClick={() => purchaseMutation.mutate({ quantity, workspace_id: searchSpaceId })}
|
||||
onClick={() => purchaseMutation.mutate({ quantity, workspace_id: workspaceId })}
|
||||
>
|
||||
{purchaseMutation.isPending ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ const formatRewardUsd = (micros: number) => {
|
|||
export function EarnCreditsContent() {
|
||||
const params = useParams();
|
||||
const queryClient = useQueryClient();
|
||||
const searchSpaceId = getWorkspaceIdParam(params) ?? "";
|
||||
const workspaceId = getWorkspaceIdParam(params) ?? "";
|
||||
|
||||
useEffect(() => {
|
||||
trackIncentivePageViewed();
|
||||
|
|
@ -163,7 +163,7 @@ export function EarnCreditsContent() {
|
|||
<p className="text-sm text-muted-foreground">Need more?</p>
|
||||
{creditBuyingEnabled ? (
|
||||
<Button asChild variant="link" className="text-emerald-600 dark:text-emerald-400">
|
||||
<Link href={`/dashboard/${searchSpaceId}/buy-more`}>Buy credits at $1 per $1</Link>
|
||||
<Link href={`/dashboard/${workspaceId}/buy-more`}>Buy credits at $1 per $1</Link>
|
||||
</Button>
|
||||
) : (
|
||||
<p className="text-xs text-muted-foreground">
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@ import { useTranslations } from "next-intl";
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import {
|
||||
updateSearchSpaceApiAccessMutationAtom,
|
||||
updateSearchSpaceMutationAtom,
|
||||
updateWorkspaceApiAccessMutationAtom,
|
||||
updateWorkspaceMutationAtom,
|
||||
} from "@/atoms/workspaces/workspace-mutation.atoms";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { searchSpacesApiService } from "@/lib/apis/workspaces-api.service";
|
||||
import { workspacesApiService } from "@/lib/apis/workspaces-api.service";
|
||||
import { authenticatedFetch } from "@/lib/auth-fetch";
|
||||
import { buildBackendUrl } from "@/lib/env-config";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
|
|
@ -25,23 +25,22 @@ interface GeneralSettingsManagerProps {
|
|||
}
|
||||
|
||||
export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerProps) {
|
||||
const searchSpaceId = workspaceId;
|
||||
const t = useTranslations("searchSpaceSettings");
|
||||
const t = useTranslations("workspaceSettings");
|
||||
const tCommon = useTranslations("common");
|
||||
const {
|
||||
data: searchSpace,
|
||||
data: workspace,
|
||||
isLoading: loading,
|
||||
isError,
|
||||
refetch: fetchSearchSpace,
|
||||
refetch: fetchWorkspace,
|
||||
} = useQuery({
|
||||
queryKey: cacheKeys.searchSpaces.detail(searchSpaceId.toString()),
|
||||
queryFn: () => searchSpacesApiService.getSearchSpace({ id: searchSpaceId }),
|
||||
enabled: !!searchSpaceId,
|
||||
queryKey: cacheKeys.workspaces.detail(workspaceId.toString()),
|
||||
queryFn: () => workspacesApiService.getWorkspace({ id: workspaceId }),
|
||||
enabled: !!workspaceId,
|
||||
});
|
||||
|
||||
const { mutateAsync: updateSearchSpace } = useAtomValue(updateSearchSpaceMutationAtom);
|
||||
const { mutateAsync: updateSearchSpaceApiAccess } = useAtomValue(
|
||||
updateSearchSpaceApiAccessMutationAtom
|
||||
const { mutateAsync: updateWorkspace } = useAtomValue(updateWorkspaceMutationAtom);
|
||||
const { mutateAsync: updateWorkspaceApiAccess } = useAtomValue(
|
||||
updateWorkspaceApiAccessMutationAtom
|
||||
);
|
||||
|
||||
const [name, setName] = useState("");
|
||||
|
|
@ -49,16 +48,16 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
const [saving, setSaving] = useState(false);
|
||||
const [savingApiAccess, setSavingApiAccess] = useState(false);
|
||||
const [isExporting, setIsExporting] = useState(false);
|
||||
const hasSearchSpace = !!searchSpace;
|
||||
const searchSpaceName = searchSpace?.name;
|
||||
const searchSpaceDescription = searchSpace?.description;
|
||||
const hasWorkspace = !!workspace;
|
||||
const workspaceName = workspace?.name;
|
||||
const workspaceDescription = workspace?.description;
|
||||
|
||||
const handleExportKB = useCallback(async () => {
|
||||
if (isExporting) return;
|
||||
setIsExporting(true);
|
||||
try {
|
||||
const response = await authenticatedFetch(
|
||||
buildBackendUrl(`/api/v1/workspaces/${searchSpaceId}/export`),
|
||||
buildBackendUrl(`/api/v1/workspaces/${workspaceId}/export`),
|
||||
{ method: "GET" }
|
||||
);
|
||||
if (!response.ok) {
|
||||
|
|
@ -81,37 +80,37 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
} finally {
|
||||
setIsExporting(false);
|
||||
}
|
||||
}, [searchSpaceId, isExporting]);
|
||||
}, [workspaceId, isExporting]);
|
||||
|
||||
// Initialize state from fetched search space
|
||||
// Initialize state from fetched workspace
|
||||
useEffect(() => {
|
||||
if (hasSearchSpace) {
|
||||
setName(searchSpaceName || "");
|
||||
setDescription(searchSpaceDescription || "");
|
||||
if (hasWorkspace) {
|
||||
setName(workspaceName || "");
|
||||
setDescription(workspaceDescription || "");
|
||||
}
|
||||
}, [hasSearchSpace, searchSpaceName, searchSpaceDescription]);
|
||||
}, [hasWorkspace, workspaceName, workspaceDescription]);
|
||||
|
||||
// Derive hasChanges during render
|
||||
const hasChanges =
|
||||
!!searchSpace &&
|
||||
((searchSpace.name || "") !== name || (searchSpace.description || "") !== description);
|
||||
!!workspace &&
|
||||
((workspace.name || "") !== name || (workspace.description || "") !== description);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
setSaving(true);
|
||||
|
||||
await updateSearchSpace({
|
||||
id: searchSpaceId,
|
||||
await updateWorkspace({
|
||||
id: workspaceId,
|
||||
data: {
|
||||
name: name.trim(),
|
||||
description: description.trim() || undefined,
|
||||
},
|
||||
});
|
||||
|
||||
await fetchSearchSpace();
|
||||
await fetchWorkspace();
|
||||
} catch (error: unknown) {
|
||||
console.error("Error saving search space details:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Failed to save search space details");
|
||||
console.error("Error saving workspace details:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Failed to save workspace details");
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
|
|
@ -126,11 +125,11 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
async (enabled: boolean) => {
|
||||
try {
|
||||
setSavingApiAccess(true);
|
||||
await updateSearchSpaceApiAccess({
|
||||
id: searchSpaceId,
|
||||
await updateWorkspaceApiAccess({
|
||||
id: workspaceId,
|
||||
api_access_enabled: enabled,
|
||||
});
|
||||
await fetchSearchSpace();
|
||||
await fetchWorkspace();
|
||||
} catch (error) {
|
||||
console.error("Error updating API access:", error);
|
||||
toast.error(error instanceof Error ? error.message : "Failed to update API access");
|
||||
|
|
@ -138,7 +137,7 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
setSavingApiAccess(false);
|
||||
}
|
||||
},
|
||||
[fetchSearchSpace, searchSpaceId, updateSearchSpaceApiAccess]
|
||||
[fetchWorkspace, workspaceId, updateWorkspaceApiAccess]
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
|
|
@ -156,7 +155,7 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
return (
|
||||
<div className="flex flex-col items-center justify-center gap-3 py-8 text-center">
|
||||
<p className="text-sm text-destructive">Failed to load settings.</p>
|
||||
<Button variant="outline" size="sm" onClick={() => fetchSearchSpace()}>
|
||||
<Button variant="outline" size="sm" onClick={() => fetchWorkspace()}>
|
||||
Retry
|
||||
</Button>
|
||||
</div>
|
||||
|
|
@ -168,9 +167,9 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
<form onSubmit={onSubmit} className="space-y-6">
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="search-space-name">{t("general_name_label")}</Label>
|
||||
<Label htmlFor="workspace-name">{t("general_name_label")}</Label>
|
||||
<Input
|
||||
id="search-space-name"
|
||||
id="workspace-name"
|
||||
maxLength={100}
|
||||
placeholder={t("general_name_placeholder")}
|
||||
value={name}
|
||||
|
|
@ -180,12 +179,12 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="search-space-description">
|
||||
<Label htmlFor="workspace-description">
|
||||
{t("general_description_label")}{" "}
|
||||
<span className="text-muted-foreground font-normal">({tCommon("optional")})</span>
|
||||
</Label>
|
||||
<Input
|
||||
id="search-space-description"
|
||||
id="workspace-description"
|
||||
placeholder={t("general_description_placeholder")}
|
||||
value={description}
|
||||
onChange={(e) => setDescription(e.target.value)}
|
||||
|
|
@ -210,13 +209,11 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
<div className="border-t pt-6 flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||
<div className="space-y-1">
|
||||
<Label htmlFor="api-access-enabled">API key access</Label>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Allow API keys to access this search space.
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">Allow API keys to access this workspace.</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="api-access-enabled"
|
||||
checked={!!searchSpace?.api_access_enabled}
|
||||
checked={!!workspace?.api_access_enabled}
|
||||
disabled={savingApiAccess}
|
||||
onCheckedChange={handleApiAccessToggle}
|
||||
/>
|
||||
|
|
@ -226,7 +223,7 @@ export function GeneralSettingsManager({ workspaceId }: GeneralSettingsManagerPr
|
|||
<div className="space-y-1">
|
||||
<Label>Export knowledge base</Label>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Download all documents in this search space as a ZIP of markdown files.
|
||||
Download all documents in this workspace as a ZIP of markdown files.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ function renderAutoModeOption() {
|
|||
}
|
||||
|
||||
export function ModelConnectionsSettings({ workspaceId }: { workspaceId: number }) {
|
||||
const searchSpaceId = workspaceId;
|
||||
const [{ data: globalConnections = [] }] = useAtom(globalModelConnectionsAtom);
|
||||
const [{ data: connections = [] }] = useAtom(modelConnectionsAtom);
|
||||
const [{ data: roles }] = useAtom(modelRolesAtom);
|
||||
|
|
@ -148,7 +147,7 @@ export function ModelConnectionsSettings({ workspaceId }: { workspaceId: number
|
|||
|
||||
<Separator />
|
||||
|
||||
<ModelProviderConnectionsPanel searchSpaceId={searchSpaceId} connections={connections} />
|
||||
<ModelProviderConnectionsPanel workspaceId={workspaceId} connections={connections} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export function ConnectionCard({ connection }: { connection: ConnectionRead }) {
|
|||
<AlertDialogTitle>Delete this provider?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
<span className="font-medium text-foreground">{providerLabel}</span> and all of
|
||||
its models will be removed from this search space. This cannot be undone.
|
||||
its models will be removed from this workspace. This cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import {
|
|||
} from "./provider-metadata";
|
||||
|
||||
interface ModelProviderConnectionsPanelProps {
|
||||
searchSpaceId: number;
|
||||
workspaceId: number;
|
||||
connections: ConnectionRead[];
|
||||
className?: string;
|
||||
addProviderTitle?: string;
|
||||
|
|
@ -49,7 +49,7 @@ function toModelSelection(model: SelectableModel): ModelSelection {
|
|||
}
|
||||
|
||||
export function ModelProviderConnectionsPanel({
|
||||
searchSpaceId,
|
||||
workspaceId,
|
||||
connections,
|
||||
className,
|
||||
addProviderTitle = "Add Provider",
|
||||
|
|
@ -126,7 +126,7 @@ export function ModelProviderConnectionsPanel({
|
|||
// Each provider connect form builds its own credential payload; the backend
|
||||
// resolver (`to_litellm`) forwards `extra.litellm_params` straight to LiteLLM.
|
||||
function handleCreate(draft: ConnectionDraft) {
|
||||
if (!Number.isFinite(searchSpaceId) || searchSpaceId <= 0) {
|
||||
if (!Number.isFinite(workspaceId) || workspaceId <= 0) {
|
||||
toast.error("Workspace is still loading. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ export function ModelProviderConnectionsPanel({
|
|||
base_url: draft.base_url,
|
||||
api_key: draft.api_key,
|
||||
scope: "SEARCH_SPACE" as const,
|
||||
workspace_id: searchSpaceId,
|
||||
workspace_id: workspaceId,
|
||||
extra: draft.extra,
|
||||
enabled: true,
|
||||
models,
|
||||
|
|
@ -170,7 +170,7 @@ export function ModelProviderConnectionsPanel({
|
|||
setProvider(providerId);
|
||||
setIsAddProviderOpen(true);
|
||||
if (providerId === "vertex_ai") {
|
||||
if (!Number.isFinite(searchSpaceId) || searchSpaceId <= 0) {
|
||||
if (!Number.isFinite(workspaceId) || workspaceId <= 0) {
|
||||
toast.error("Workspace is still loading. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ export function ModelProviderConnectionsPanel({
|
|||
base_url: null,
|
||||
api_key: null,
|
||||
scope: "SEARCH_SPACE",
|
||||
workspace_id: searchSpaceId,
|
||||
workspace_id: workspaceId,
|
||||
extra: {},
|
||||
enabled: true,
|
||||
models: [],
|
||||
|
|
@ -194,7 +194,7 @@ export function ModelProviderConnectionsPanel({
|
|||
}
|
||||
|
||||
function refreshConnectModels(draft: ConnectionDraft) {
|
||||
if (!Number.isFinite(searchSpaceId) || searchSpaceId <= 0) {
|
||||
if (!Number.isFinite(workspaceId) || workspaceId <= 0) {
|
||||
toast.error("Workspace is still loading. Please try again.");
|
||||
return;
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ export function ModelProviderConnectionsPanel({
|
|||
base_url: draft.base_url,
|
||||
api_key: draft.api_key,
|
||||
scope: "SEARCH_SPACE",
|
||||
workspace_id: searchSpaceId,
|
||||
workspace_id: workspaceId,
|
||||
extra: draft.extra,
|
||||
enabled: true,
|
||||
models: [],
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import { useAtomValue } from "jotai";
|
|||
import { AlertTriangle, Info } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { updateSearchSpaceMutationAtom } from "@/atoms/workspaces/workspace-mutation.atoms";
|
||||
import { updateWorkspaceMutationAtom } from "@/atoms/workspaces/workspace-mutation.atoms";
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { searchSpacesApiService } from "@/lib/apis/workspaces-api.service";
|
||||
import { workspacesApiService } from "@/lib/apis/workspaces-api.service";
|
||||
import { cacheKeys } from "@/lib/query-client/cache-keys";
|
||||
import { Spinner } from "../ui/spinner";
|
||||
|
||||
|
|
@ -20,36 +20,35 @@ interface PromptConfigManagerProps {
|
|||
}
|
||||
|
||||
export function PromptConfigManager({ workspaceId }: PromptConfigManagerProps) {
|
||||
const searchSpaceId = workspaceId;
|
||||
const { data: searchSpace, isLoading: loading } = useQuery({
|
||||
queryKey: cacheKeys.searchSpaces.detail(searchSpaceId.toString()),
|
||||
queryFn: () => searchSpacesApiService.getSearchSpace({ id: searchSpaceId }),
|
||||
enabled: !!searchSpaceId,
|
||||
const { data: workspace, isLoading: loading } = useQuery({
|
||||
queryKey: cacheKeys.workspaces.detail(workspaceId.toString()),
|
||||
queryFn: () => workspacesApiService.getWorkspace({ id: workspaceId }),
|
||||
enabled: !!workspaceId,
|
||||
});
|
||||
|
||||
const { mutateAsync: updateSearchSpace, isPending: isSaving } = useAtomValue(
|
||||
updateSearchSpaceMutationAtom
|
||||
const { mutateAsync: updateWorkspace, isPending: isSaving } = useAtomValue(
|
||||
updateWorkspaceMutationAtom
|
||||
);
|
||||
|
||||
const [customInstructions, setCustomInstructions] = useState("");
|
||||
const hasSearchSpace = !!searchSpace;
|
||||
const searchSpaceInstructions = searchSpace?.qna_custom_instructions;
|
||||
const hasWorkspace = !!workspace;
|
||||
const workspaceInstructions = workspace?.qna_custom_instructions;
|
||||
|
||||
// Initialize state from fetched search space
|
||||
// Initialize state from fetched workspace
|
||||
useEffect(() => {
|
||||
if (hasSearchSpace) {
|
||||
setCustomInstructions(searchSpaceInstructions || "");
|
||||
if (hasWorkspace) {
|
||||
setCustomInstructions(workspaceInstructions || "");
|
||||
}
|
||||
}, [hasSearchSpace, searchSpaceInstructions]);
|
||||
}, [hasWorkspace, workspaceInstructions]);
|
||||
|
||||
// Derive hasChanges during render
|
||||
const hasChanges =
|
||||
!!searchSpace && (searchSpace.qna_custom_instructions || "") !== customInstructions;
|
||||
!!workspace && (workspace.qna_custom_instructions || "") !== customInstructions;
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
await updateSearchSpace({
|
||||
id: searchSpaceId,
|
||||
await updateWorkspace({
|
||||
id: workspaceId,
|
||||
data: { qna_custom_instructions: customInstructions.trim() || "" },
|
||||
});
|
||||
toast.success("System instructions saved successfully");
|
||||
|
|
@ -98,8 +97,8 @@ export function PromptConfigManager({ workspaceId }: PromptConfigManagerProps) {
|
|||
<Alert>
|
||||
<Info />
|
||||
<AlertDescription>
|
||||
System instructions apply to all AI interactions in this search space. They guide how the
|
||||
AI responds, its tone, focus areas, and behavior patterns.
|
||||
System instructions apply to all AI interactions in this workspace. They guide how the AI
|
||||
responds, its tone, focus areas, and behavior patterns.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
|
|
@ -112,7 +111,7 @@ export function PromptConfigManager({ workspaceId }: PromptConfigManagerProps) {
|
|||
</h3>
|
||||
<p className="text-xs md:text-sm text-muted-foreground">
|
||||
Provide specific guidelines for how you want the AI to respond. These instructions
|
||||
will be applied to all answers in this search space.
|
||||
will be applied to all answers in this workspace.
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-3 md:space-y-4">
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ const CATEGORY_CONFIG: Record<
|
|||
settings: {
|
||||
label: "Settings",
|
||||
icon: Settings,
|
||||
description: "Manage search space settings",
|
||||
description: "Manage workspace settings",
|
||||
order: 10,
|
||||
},
|
||||
public_sharing: {
|
||||
|
|
@ -172,7 +172,7 @@ const CATEGORY_CONFIG: Record<
|
|||
general: {
|
||||
label: "General",
|
||||
icon: SlidersHorizontal,
|
||||
description: "General search space permissions",
|
||||
description: "General workspace permissions",
|
||||
order: 12,
|
||||
},
|
||||
};
|
||||
|
|
@ -270,7 +270,6 @@ type PermissionWithDescription = PermissionInfo;
|
|||
// ============ Roles Manager (for Settings page) ============
|
||||
|
||||
export function RolesManager({ workspaceId }: { workspaceId: number }) {
|
||||
const searchSpaceId = workspaceId;
|
||||
const { data: access = null } = useAtomValue(myAccessAtom);
|
||||
|
||||
const hasPermission = useCallback(
|
||||
|
|
@ -279,9 +278,9 @@ export function RolesManager({ workspaceId }: { workspaceId: number }) {
|
|||
);
|
||||
|
||||
const { data: roles = [], isLoading: rolesLoading } = useQuery({
|
||||
queryKey: cacheKeys.roles.all(searchSpaceId.toString()),
|
||||
queryFn: () => rolesApiService.getRoles({ workspace_id: searchSpaceId }),
|
||||
enabled: !!searchSpaceId,
|
||||
queryKey: cacheKeys.roles.all(workspaceId.toString()),
|
||||
queryFn: () => rolesApiService.getRoles({ workspace_id: workspaceId }),
|
||||
enabled: !!workspaceId,
|
||||
});
|
||||
|
||||
const { data: permissionsData } = useAtomValue(permissionsAtom);
|
||||
|
|
@ -312,36 +311,36 @@ export function RolesManager({ workspaceId }: { workspaceId: number }) {
|
|||
}
|
||||
): Promise<Role> => {
|
||||
const request: UpdateRoleRequest = {
|
||||
workspace_id: searchSpaceId,
|
||||
workspace_id: workspaceId,
|
||||
role_id: roleId,
|
||||
data: data,
|
||||
};
|
||||
return await updateRole(request);
|
||||
},
|
||||
[updateRole, searchSpaceId]
|
||||
[updateRole, workspaceId]
|
||||
);
|
||||
|
||||
const handleDeleteRole = useCallback(
|
||||
async (roleId: number): Promise<boolean> => {
|
||||
const request: DeleteRoleRequest = {
|
||||
workspace_id: searchSpaceId,
|
||||
workspace_id: workspaceId,
|
||||
role_id: roleId,
|
||||
};
|
||||
await deleteRole(request);
|
||||
return true;
|
||||
},
|
||||
[deleteRole, searchSpaceId]
|
||||
[deleteRole, workspaceId]
|
||||
);
|
||||
|
||||
const handleCreateRole = useCallback(
|
||||
async (roleData: CreateRoleRequest["data"]): Promise<Role> => {
|
||||
const request: CreateRoleRequest = {
|
||||
workspace_id: searchSpaceId,
|
||||
workspace_id: workspaceId,
|
||||
data: roleData,
|
||||
};
|
||||
return await createRole(request);
|
||||
},
|
||||
[createRole, searchSpaceId]
|
||||
[createRole, workspaceId]
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
@ -885,7 +884,7 @@ function CreateRoleDialog({
|
|||
<DialogHeader className="px-5 pt-5 pb-4 shrink-0">
|
||||
<DialogTitle className="text-lg">Create Custom Role</DialogTitle>
|
||||
<DialogDescription className="text-sm text-muted-foreground">
|
||||
Define permissions for a new role in this search space
|
||||
Define permissions for a new role in this workspace
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="flex-1 min-h-0 overflow-y-auto">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue