fixed members login and permissions issues

This commit is contained in:
2026-02-23 00:57:34 +00:00
parent ed0debfeac
commit 97da2e2736
42 changed files with 574 additions and 113 deletions
+5 -6
View File
@@ -4,18 +4,17 @@ import { Text, Button } from '@react-email/components';
type EmailProps = {
invitedBy: string;
companyName: string;
url: string;
};
const Email = ({ invitedBy, companyName, url }: EmailProps) => {
const Email = ({ invitedBy, url }: EmailProps) => {
return (
<Layout>
<Container>
<Text className="pt-4 text-2xl">Invitation to our platform</Text>
<Text>You have been invited by {invitedBy || '<invitedBy>'} to join Pertento.ai</Text>
<Text>as a member of {companyName || '<companyName>'}</Text>
<Button href={url || 'https://example.com'}>Click here to accept our invitation</Button>
<Text className="pt-4 text-2xl">You're invited to Officer</Text>
<Text>You have been invited by {invitedBy || '<invitedBy>'} to join Officer.</Text>
<Text>Click the button below to set up your account.</Text>
<Button href={url || 'https://example.com'}>Accept Invitation</Button>
</Container>
</Layout>
);
+1 -1
View File
@@ -4,7 +4,7 @@ export type SignupUserForm = {
password?: string;
};
export type UpdateUserPayload = { name: string; avatar: string };
export type UpdateUserPayload = { name: string; username?: string; avatar: string };
export type ResetPasswordPayload = { password: string; verificationCode: string };
@@ -130,6 +130,7 @@ export type SignupUserForm = {
export type UpdateUserPayload = {
name: string;
username?: string;
avatar: string;
};
@@ -1,3 +1,17 @@
import { useWorkspace } from '../../components/Workspace';
import { EmbeddableChat } from './EmbeddableChat';
export const ChatPanelWrapper = () => <EmbeddableChat className="h-full" />;
export const ChatPanelWrapper = () => {
const { cwd, root } = useWorkspace();
const scoped = cwd !== '~';
const hostRoot = root === '~' || root === 'officer.dev';
const sandboxed = !hostRoot;
return (
<EmbeddableChat
className="h-full"
cwd={scoped ? { root, path: cwd } : undefined}
sandboxed={sandboxed}
/>
);
};
@@ -17,6 +17,7 @@ type EmbeddableChatProps = {
className?: string;
cwd?: { root?: string; path: string };
sandboxed?: boolean;
replaceUrl?: boolean;
autoSend?: boolean;
chat?: UsePiChatType;
};
@@ -18,6 +18,7 @@ type UseEmbeddableChatParams = {
promptPrefix?: string;
cwd?: { root?: string; path: string };
sandboxed?: boolean;
replaceUrl?: boolean;
autoSend?: boolean;
chat?: UsePiChatType;
};
@@ -25,7 +26,7 @@ type UseEmbeddableChatParams = {
export function useEmbeddableChat(params: UseEmbeddableChatParams) {
const { initialMessage, defaultInput = '', promptPrefix, cwd, sandboxed, autoSend = false, chat: externalChat } = params;
const internalChat = usePiChat(params.sessionId, params.initialModel);
const internalChat = usePiChat(params.sessionId, params.initialModel, { replaceUrl: params.replaceUrl ?? false });
const chat = externalChat ?? internalChat;
const {
@@ -7,10 +7,10 @@ import { useTerminalMode } from './useTerminalMode';
const EMPTY_TERMINALS: Record<string, string> = {};
export const TerminalWrapper = ({ panelId }: { panelId: string }) => {
const { workspaceId, cwd } = useWorkspace();
const { workspaceId, cwd, root } = useWorkspace();
const { mode } = useTerminalMode(panelId);
const scoped = cwd !== '~';
const sandboxed = scoped || mode === 'sandboxed';
const hostRoot = root === '~' || root === 'officer.dev';
const sandboxed = !hostRoot && (cwd !== '~' || mode === 'sandboxed');
const stateKey = workspaceId ? `ws-terminals-${mode}-${workspaceId}` : `ws-terminals-${mode}-default`;
const { value: terminals, setValue: setTerminals } = useWorkspacesState<Record<string, string>>(stateKey, EMPTY_TERMINALS);
const setTerminalsRef = useRef(setTerminals);
@@ -20,7 +20,8 @@ export const TerminalWrapper = ({ panelId }: { panelId: string }) => {
useEffect(() => {
if (!sessionId) {
setTerminals((prev) => ({ ...prev, [panelId]: crypto.randomUUID() }));
const id = crypto.randomUUID?.() ?? Math.random().toString(36).slice(2) + Date.now().toString(36);
setTerminals((prev) => ({ ...prev, [panelId]: id }));
}
}, [panelId, sessionId, setTerminals]);
@@ -7,7 +7,7 @@ import { useClient } from 'hooks/useClient';
import { useUserState } from 'state/useUserState';
import { useWorkspacesState } from 'state/useWorkspacesState';
import { WorkspaceLayout, WorkspaceView, createDefaultLayout } from '../../components/Workspace';
import type { LayoutNode, WorkspaceDefinition } from '../../components/Workspace';
import type { LayoutNode, WorkspaceDefinition, HomeRoot } from '../../components/Workspace';
import { Button } from '@/components/ui/button';
import { generateSlug, slugify } from 'helpers/slug';
import { FileBrowserApp } from '../FileBrowser';
@@ -276,6 +276,7 @@ const CreatePanel = () => {
const client = useClient();
const [name, setName] = useGlobal<string>(NEW_WS_NAME_KEY, '');
const [filePath] = useUserState<string>('files/currentPath', '/');
const [homeRoot] = useUserState<HomeRoot>('files/homeRoot', 'home');
const { value: workspaces, setValue: setWorkspaces } = useWorkspacesState<WorkspaceDefinition[]>('workspaces', []);
const cwd = filePath === '/' ? '~' : `~/${filePath.replace(/^\//, '')}`;
@@ -337,6 +338,7 @@ const CreatePanel = () => {
id,
name: trimmed,
cwd,
root: homeRoot !== 'home' ? homeRoot : undefined,
description: desc || undefined,
templateIdx,
};
@@ -480,7 +482,7 @@ const WorkspacePreviewEmpty = () => {
const WorkspacePreviewInner = ({ workspace }: { workspace: WorkspaceDefinition }) => {
const ws = useWorkspacesState<LayoutNode>(`ws-layout-${workspace.id}`, createDefaultLayout());
return <WorkspaceView workspace={ws} cwd={workspace.cwd} />;
return <WorkspaceView workspace={ws} cwd={workspace.cwd} root={workspace.root} />;
};
// --- Main Export ---
@@ -5,6 +5,7 @@ import type { DropPosition } from './layout-utils';
type WorkspaceContextValue = {
workspaceId: string | null;
cwd: string;
root?: string;
swapSourceId: string | null;
setSwapSourceId: (id: string | null) => void;
onSwap: (sourceId: string, targetId: string) => void;
@@ -11,12 +11,13 @@ import { useAppRegistry } from '../../AppRegistry/useAppRegistry';
type WorkspaceViewProps = {
workspace: WorkspaceState;
cwd?: string;
root?: string;
ephemeral?: EphemeralPanels | null;
};
const noop = () => {};
export const WorkspaceView = ({ workspace, cwd = '~', ephemeral }: WorkspaceViewProps) => {
export const WorkspaceView = ({ workspace, cwd = '~', root, ephemeral }: WorkspaceViewProps) => {
const { registry } = useAppRegistry();
const layout = workspace.value;
@@ -147,6 +148,7 @@ export const WorkspaceView = ({ workspace, cwd = '~', ephemeral }: WorkspaceView
value={{
workspaceId: workspace.key,
cwd,
root,
swapSourceId,
setSwapSourceId,
onSwap: handleSwap,
@@ -1,4 +1,4 @@
export type { LayoutNode, LayoutGroup, LayoutPanel, WorkspaceDefinition, WorkspaceState, ProjectType, ProjectDefinition, AppRegistry, AppRegistryEntry, PanelComponents, PanelComponentEntry, EphemeralPanels } from './types';
export type { LayoutNode, LayoutGroup, LayoutPanel, WorkspaceDefinition, WorkspaceState, ProjectType, ProjectDefinition, AppRegistry, AppRegistryEntry, PanelComponents, PanelComponentEntry, EphemeralPanels, HomeRoot } from './types';
export type { DropPosition } from './layout-utils';
export { createDefaultLayout, splitPanel, removePanel, setApp, updateSizes, swapPanels, movePanel, pruneEmptyPanels, countPanels, hasAnyApp } from './layout-utils';
export { WorkspaceProvider, useWorkspace } from './WorkspaceContext';
@@ -16,10 +16,13 @@ export type LayoutPanel = {
export type LayoutNode = LayoutGroup | LayoutPanel;
export type HomeRoot = 'home' | '~' | 'officer.dev';
export type WorkspaceDefinition = {
id: string;
name: string;
cwd: string;
root?: HomeRoot;
description?: string;
templateIdx?: number;
};
@@ -283,6 +283,7 @@ export function usePiChat(initialSessionId?: string, initialModel?: string | nul
sessionId: sessionIdRef.current,
...(selectedModel ? { model: selectedModel } : {}),
...(cwdParam?.path ? { cwd: cwdParam.path } : {}),
...(cwdParam?.root ? { cwdRoot: cwdParam.root } : {}),
...(sandboxed !== undefined ? { sandboxed } : {}),
...(groupSlug !== undefined ? { groupSlug } : {}),
...(attachmentIds?.length ? { attachmentIds } : {}),
+1 -1
View File
@@ -20,4 +20,4 @@ export { ProjectListApp, ProjectPreview, SELECTED_PROJECT, CREATING_PROJECT, EDI
// Workspace
export { WorkspaceView, WorkspaceLayout, WorkspaceProvider, useWorkspace } from './components/Workspace';
export { createDefaultLayout, splitPanel, removePanel, setApp, updateSizes, swapPanels, movePanel, pruneEmptyPanels, countPanels, hasAnyApp } from './components/Workspace';
export type { LayoutNode, LayoutGroup, LayoutPanel, WorkspaceDefinition, WorkspaceState, ProjectType, ProjectDefinition, AppRegistry, AppRegistryEntry, PanelComponents, PanelComponentEntry, EphemeralPanels, DropPosition } from './components/Workspace';
export type { LayoutNode, LayoutGroup, LayoutPanel, WorkspaceDefinition, WorkspaceState, ProjectType, ProjectDefinition, AppRegistry, AppRegistryEntry, PanelComponents, PanelComponentEntry, EphemeralPanels, DropPosition, HomeRoot } from './components/Workspace';