Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions frontend/src/components/console/common-data.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { createContext, useContext } from 'react';
import type {
DomainGitIdentity,
DomainHost,
DomainImage,
DomainModel,
DomainProject,
DomainProjectTask,
DomainUser,
DomainVirtualMachine,
} from '@/api/Api';

export type CommonData = {
user: DomainUser;
reloadUser: () => void;

hosts: DomainHost[];
vms: DomainVirtualMachine[];
loadingHosts: boolean;
hostsInited: boolean;
reloadHosts: () => void;

models: DomainModel[];
loadingModels: boolean;
reloadModels: () => void;

images: DomainImage[];
loadingImages: boolean;
reloadImages: () => void;

identities: DomainGitIdentity[];
loadingIdentities: boolean;
reloadIdentities: () => void;

balance: number;
bonus: number;
reloadWallet: () => void;

members: DomainUser[];
loadingMembers: boolean;
reloadMembers: () => void;

projects: DomainProject[];
loadingProjects: boolean;
reloadProjects: () => void;

/** 未关联项目的任务(quick_start),用于侧边栏「默认」分组展示 */
unlinkedTasks: DomainProjectTask[];
loadingUnlinkedTasks: boolean;
reloadUnlinkedTasks: () => void;
};

export const DataContext = createContext<CommonData | null>(null);

export const useCommonData = () => {
const ctx = useContext(DataContext);
if (!ctx) throw new Error('useCommonData must be used within DataProvider');
return ctx;
};
57 changes: 5 additions & 52 deletions frontend/src/components/console/data-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,10 @@
import { ConstsGitPlatform, ConstsOwnerType, type DomainGitIdentity, type DomainHost, type DomainImage, type DomainModel, type DomainProject, type DomainProjectTask, type DomainUser, type DomainVirtualMachine } from '@/api/Api';
import { ConstsGitPlatform, ConstsOwnerType, type DomainGitIdentity, type DomainHost, type DomainImage, type DomainModel, type DomainProject, type DomainProjectTask, type DomainUser } from '@/api/Api';
import { getImageShortName } from '@/utils/common';
import { apiRequest } from '@/utils/requestUtils';
import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { DataContext } from '@/components/console/common-data';
import React, { useEffect, useMemo, useState } from 'react';
import { toast } from 'sonner';

type CommonData = {
user: DomainUser;
reloadUser: () => void;

hosts: DomainHost[];
vms: DomainVirtualMachine[];
loadingHosts: boolean;
hostsInited: boolean;
reloadHosts: () => void;

models: DomainModel[];
loadingModels: boolean;
reloadModels: () => void;

images: DomainImage[];
loadingImages: boolean;
reloadImages: () => void;

identities: DomainGitIdentity[];
loadingIdentities: boolean;
reloadIdentities: () => void;

balance: number;
bonus: number;
reloadWallet: () => void;

members: DomainUser[];
loadingMembers: boolean;
reloadMembers: () => void;

projects: DomainProject[];
loadingProjects: boolean;
reloadProjects: () => void;

/** 未关联项目的任务(quick_start),用于侧边栏「默认」分组展示 */
unlinkedTasks: DomainProjectTask[];
loadingUnlinkedTasks: boolean;
reloadUnlinkedTasks: () => void;
};

const DataContext = createContext<CommonData | null>(null);

export const DataProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [userInfo, setUserInfo] = useState<DomainUser>({});

Expand Down Expand Up @@ -228,8 +187,8 @@ export const DataProvider: React.FC<{ children: React.ReactNode }> = ({ children
const fetchWallet = () => {
apiRequest('v1UsersWalletList', {}, [], (resp) => {
if (resp.code === 0) {
setBalance(resp.data?.balance / 1000);
setBonus(resp.data?.bonus / 1000);
setBalance((resp.data?.balance || 0) / 1000);
setBonus((resp.data?.bonus || 0) / 1000);
} else {
toast.error("获取余额失败: " + resp.message);
}
Expand Down Expand Up @@ -334,9 +293,3 @@ export const DataProvider: React.FC<{ children: React.ReactNode }> = ({ children
</DataContext.Provider>
);
};

export const useCommonData = () => {
const ctx = useContext(DataContext);
if (!ctx) throw new Error('useCommonData must be used within DataProvider');
return ctx;
};
14 changes: 11 additions & 3 deletions frontend/src/components/console/files/file-picker-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect, useCallback } from "react"
import React, { useState, useEffect, useCallback } from "react"
import {
Dialog,
DialogContent,
Expand Down Expand Up @@ -375,7 +375,11 @@ export default function FilePickerDialog({
(空目录)
</div>
) : (
node.children.map(child => renderNode(child))
node.children.map(child => (
<React.Fragment key={child.path}>
{renderNode(child)}
</React.Fragment>
))
)}
</>
)}
Expand All @@ -400,7 +404,11 @@ export default function FilePickerDialog({
</div>
) : (
<div className="flex flex-col">
{treeNodes.map(node => renderNode(node))}
{treeNodes.map(node => (
<React.Fragment key={node.path}>
{renderNode(node)}
</React.Fragment>
))}
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { toast } from "sonner"
import type { DomainGitBot, DomainHost } from "@/api/Api"
import Icon from "@/components/common/Icon"
import { Badge } from "@/components/ui/badge"
import { useCommonData } from "../data-provider"
import { useCommonData } from "../common-data"
import { getHostBadges } from "@/utils/common"

interface CreateGitBotDialogProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import type { DomainGitBot } from "@/api/Api"
import { ConstsGitPlatform, ConstsHostStatus } from "@/api/Api"
import Icon from "@/components/common/Icon"
import { Badge } from "@/components/ui/badge"
import { useCommonData } from "../data-provider"
import { useCommonData } from "../common-data"
import { getHostBadges } from "@/utils/common"

interface EditGitBotDialogProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { toast } from "sonner"
import { IconLoader } from "@tabler/icons-react"
import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
import { useCommonData } from "../data-provider"
import { useCommonData } from "../common-data"

interface EditGitBotPermissionDialogProps {
open: boolean
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/console/nav/nav-balance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Item, ItemContent, ItemGroup, ItemTitle } from "@/components/ui/item";
import dayjs from "dayjs";
import { cn } from "@/lib/utils";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { useCommonData } from "../data-provider";
import { useCommonData } from "../common-data";

interface NavBalanceProps {
variant?: "sidebar" | "header";
Expand Down
10 changes: 7 additions & 3 deletions frontend/src/components/console/nav/nav-project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
} from "@/components/ui/alert-dialog"
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { useCommonData } from "../data-provider"
import { useCommonData } from "../common-data"
import { IconChevronDown, IconChevronRight, IconCircleMinus, IconDotsVertical, IconLoader, IconPlus, IconReload, IconTrash } from "@tabler/icons-react"
import { Button } from "@/components/ui/button"
import AddProjectDialog from "../project/add-project"
Expand All @@ -44,14 +44,18 @@ const loadExpandedFromStorage = (): Record<string, boolean> => {
try {
const cached = localStorage.getItem(STORAGE_KEY)
if (cached) return JSON.parse(cached)
} catch {}
} catch {
// ignore: storage unavailable or cached value is not valid JSON
}
return {}
}

const saveExpandedToStorage = (state: Record<string, boolean>) => {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
} catch {}
} catch {
// ignore: storage unavailable (e.g. private mode / quota exceeded)
}
}

export default function NavProject() {
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/components/console/nav/nav-user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { Spinner } from "@/components/ui/spinner"
import { Button } from "@/components/ui/button"
import { toast } from "sonner"
import { IconLockCode, IconLogout, IconUserHexagon, IconUpload } from "@tabler/icons-react"
import { useCommonData } from "@/components/console/data-provider"
import { useCommonData } from "@/components/console/common-data"

export default function NavUser() {
const { isMobile } = useSidebar()
Expand All @@ -69,7 +69,7 @@ export default function NavUser() {

const handleLogout = () => {
apiRequest('v1UsersLogoutCreate', {}, [], (resp) => {
if (resp.code === 0) {
if (Number(resp.code) === 0) {
navigate('/');
} else {
toast.error('登出失败: ' + resp.message);
Expand All @@ -94,7 +94,6 @@ export default function NavUser() {
await apiRequest('v1UsersPasswordsChangeUpdate', {
current_password: currentPassword,
new_password: newPassword,
confirm_password: confirmPassword,
}, [], (resp) => {
if (resp?.code === 0) {
toast.success('密码修改成功');
Expand Down Expand Up @@ -212,7 +211,7 @@ export default function NavUser() {
>
<DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar
<Avatar
className="h-8 w-8 rounded-lg cursor-pointer hover:opacity-50 transition-opacity"
onClick={() => setShowChangeAvatarDialog(true)}
>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/console/project/add-project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { useNavigate } from "react-router-dom"
import { useSettingsDialog } from "@/pages/console/user/page"
import { toast } from "sonner"
import { Spinner } from "@/components/ui/spinner"
import { useCommonData } from "@/components/console/data-provider"
import { useCommonData } from "@/components/console/common-data"

interface RepoOption {
gitIdentityId: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import type { DomainImage, DomainProject } from "@/api/Api"
import Icon from "@/components/common/Icon"
import { useCommonData } from "@/components/console/data-provider"
import { useCommonData } from "@/components/console/common-data"
import { apiRequest } from "@/utils/requestUtils"
import { getImageShortName, getOSFromImageName } from "@/utils/common"
import { useEffect, useState } from "react"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type DomainProjectIssue, type DomainProject, ConstsCliName, ConstsGitPlatform, ConstsTaskSubType, ConstsTaskType, type DomainBranch } from "@/api/Api"
import { useCommonData } from "@/components/console/data-provider"
import { useCommonData } from "@/components/console/common-data"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type DomainProjectIssue, type DomainProject, ConstsCliName, ConstsGitPlatform, ConstsTaskType, type DomainBranch } from "@/api/Api"
import { useCommonData } from "@/components/console/data-provider"
import { useCommonData } from "@/components/console/common-data"
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/console/project/project-info.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type DomainProject } from "@/api/Api"
import { useCommonData } from "@/components/console/data-provider"
import { useCommonData } from "@/components/console/common-data"
import EditProjectEnvDialog from "@/components/console/project/edit-project-env"
import EditProjectImageDialog from "@/components/console/project/edit-project-image"
import EditProjectNameDialog from "@/components/console/project/edit-project-name"
Expand Down
Loading
Loading