diff --git a/webui/src/lib/components/auth/layout.jsx b/webui/src/lib/components/auth/layout.jsx index a891b9526cf..f9504d7e5cb 100644 --- a/webui/src/lib/components/auth/layout.jsx +++ b/webui/src/lib/components/auth/layout.jsx @@ -1,59 +1,61 @@ -import React from "react"; - +import React, {useEffect, useState} from "react"; +import {Outlet, useOutletContext} from "react-router-dom"; import Container from "react-bootstrap/Container"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; import Nav from "react-bootstrap/Nav"; import Card from "react-bootstrap/Card"; -import Layout from "../layout"; import {Link} from "../nav"; import {useLoginConfigContext} from "../../hooks/conf"; -export const AuthLayout = ({ children, activeTab }) => { +export const AuthLayout = () => { + const [activeTab, setActiveTab] = useState("credentials"); const {RBAC: rbac} = useLoginConfigContext(); + const [setIsLogged] = useOutletContext(); + useEffect(() => { + setIsLogged(true); + }, [setIsLogged]); return ( - - - - - - - Access Control - - - - -
- - -
-
- - - - {children} - -
-
-
+ + + + + + Access Control + + + + +
+ + +
+
+ + + + + +
+
); }; diff --git a/webui/src/lib/components/layout.jsx b/webui/src/lib/components/layout.jsx index 45f4117f527..9ee719a3faf 100644 --- a/webui/src/lib/components/layout.jsx +++ b/webui/src/lib/components/layout.jsx @@ -1,16 +1,21 @@ -import React from "react"; +import React, {useState} from "react"; +import { Outlet } from "react-router-dom"; +import { StorageConfigProvider } from "../hooks/storageConfig"; import TopNav from './navbar'; -const Layout = ({ logged = true, children }) => { +const Layout = ({ logged }) => { + const [isLogged, setIsLogged] = useState(logged ?? true); return ( <> - +
- {children} + + +
); }; -export default Layout; \ No newline at end of file +export default Layout; diff --git a/webui/src/lib/components/repository/layout.jsx b/webui/src/lib/components/repository/layout.jsx index 9855194dffd..1c5a7c590c3 100644 --- a/webui/src/lib/components/repository/layout.jsx +++ b/webui/src/lib/components/repository/layout.jsx @@ -5,17 +5,23 @@ import Container from "react-bootstrap/Container"; import Breadcrumb from "react-bootstrap/Breadcrumb"; import {useRefs} from "../../hooks/repo"; -import Layout from "../layout"; +import { Outlet } from "react-router-dom"; import {RepositoryNavTabs} from "./tabs"; import {Link} from "../nav"; import { config } from "../../api"; import { useAPI } from "../../hooks/api"; import RepoOnboardingChecklistSlider from "./repoOnboardingChecklistSlider"; +import { RefContextProvider } from "../../hooks/repo"; const RepoNav = () => { const { repo } = useRefs(); - const repoId = (repo) ? repo.id : '#'; - + const [repoId, setRepoId] = useState(""); + useEffect(() => { + if (repo) { + setRepoId(repo.id); + } + }, [repo]); + return ( @@ -25,11 +31,11 @@ const RepoNav = () => { {repoId} - - ) + ); }; -export const RepositoryPageLayout = ({ activePage, children, fluid = "sm" }) => { +export const RepositoryPageLayout = ({ fluid = "sm" }) => { + const [activePage, setActivePage] = useState("objects"); const [showChecklist, setShowChecklist] = useLocalStorage( "showChecklist", false @@ -53,7 +59,7 @@ export const RepositoryPageLayout = ({ activePage, children, fluid = "sm" }) => }, [response, setConfigRes]); return ( - +
{configRes && !dismissedChecklistForRepo && ( -
{children}
+
+ +
-
+ ); }; diff --git a/webui/src/pages/auth/credentials.jsx b/webui/src/pages/auth/credentials.jsx index 5384d4cb730..69945b1a015 100644 --- a/webui/src/pages/auth/credentials.jsx +++ b/webui/src/pages/auth/credentials.jsx @@ -1,6 +1,5 @@ -import React from "react"; - -import {AuthLayout} from "../../lib/components/auth/layout"; +import React, {useEffect} from "react"; +import { useOutletContext } from "react-router-dom"; import { ActionGroup, ActionsBar, @@ -81,11 +80,9 @@ const CredentialsContainer = () => { }; const CredentialsPage = () => { - return ( - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab("credentials"), [setActiveTab]); + return ; }; diff --git a/webui/src/pages/auth/groups/group/index.jsx b/webui/src/pages/auth/groups/group/index.jsx deleted file mode 100644 index 5f66e550077..00000000000 --- a/webui/src/pages/auth/groups/group/index.jsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from "react"; - -import {Navigate, Route, Routes} from "react-router-dom"; -import {useRouter} from "../../../../lib/hooks/router"; -import GroupMembersPage from "./members"; -import GroupPoliciesPage from "./policies"; - - -const GroupRedirect = ({ subPath }) => { - const router = useRouter(); - const { groupId } = router.params; - return ; -}; - -export default function GroupPage() { - return ( - - } /> - } /> - } /> - - ); -} diff --git a/webui/src/pages/auth/groups/group/members.jsx b/webui/src/pages/auth/groups/group/members.jsx index a3b65ed85b9..c71cb094cbb 100644 --- a/webui/src/pages/auth/groups/group/members.jsx +++ b/webui/src/pages/auth/groups/group/members.jsx @@ -1,9 +1,8 @@ import React, {useEffect, useState} from "react"; - +import { useOutletContext } from "react-router-dom"; import Button from "react-bootstrap/Button"; import {GroupHeader} from "../../../../lib/components/auth/nav"; -import {AuthLayout} from "../../../../lib/components/auth/layout"; import {useAPIWithPagination} from "../../../../lib/hooks/api"; import {auth} from "../../../../lib/api"; import {Paginator} from "../../../../lib/components/pagination"; @@ -120,11 +119,9 @@ const GroupMembersContainer = () => { }; const GroupMembersPage = () => { - return ( - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab('groups'), [setActiveTab]); + return ; }; export default GroupMembersPage; diff --git a/webui/src/pages/auth/groups/group/policies.jsx b/webui/src/pages/auth/groups/group/policies.jsx index 44a160aa077..9cac9eb0137 100644 --- a/webui/src/pages/auth/groups/group/policies.jsx +++ b/webui/src/pages/auth/groups/group/policies.jsx @@ -1,8 +1,7 @@ import React, {useEffect, useState} from "react"; - +import { useOutletContext } from "react-router-dom"; import Button from "react-bootstrap/Button"; -import {AuthLayout} from "../../../../lib/components/auth/layout"; import {GroupHeader} from "../../../../lib/components/auth/nav"; import {useAPIWithPagination} from "../../../../lib/hooks/api"; import {auth} from "../../../../lib/api"; @@ -120,11 +119,9 @@ const GroupPoliciesContainer = () => { }; const GroupPoliciesPage = () => { - return ( - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab('groups'), [setActiveTab]); + return ; }; export default GroupPoliciesPage; diff --git a/webui/src/pages/auth/groups/index.tsx b/webui/src/pages/auth/groups/index.tsx index 8c50e9ba058..f145adf6b5a 100644 --- a/webui/src/pages/auth/groups/index.tsx +++ b/webui/src/pages/auth/groups/index.tsx @@ -1,9 +1,8 @@ import React, {useEffect, useState} from "react"; - +import { useOutletContext } from "react-router-dom"; import Button from "react-bootstrap/Button"; import Dropdown from "react-bootstrap/Dropdown"; -import {AuthLayout} from "../../../lib/components/auth/layout"; import {useAPIWithPagination} from "../../../lib/hooks/api"; import {auth} from "../../../lib/api"; import {ConfirmationButton} from "../../../lib/components/modals"; @@ -18,10 +17,8 @@ import { Loading, RefreshButton } from "../../../lib/components/controls"; -import {Route, Routes} from "react-router-dom"; import {useRouter} from "../../../lib/hooks/router"; import {Link} from "../../../lib/components/nav"; -import GroupPage from "./group"; import {EntityActionModal} from "../../../lib/components/auth/forms"; import { disallowPercentSign, INVALID_GROUP_NAME_ERROR_MESSAGE } from "../validation"; import {useLoginConfigContext} from "../../../lib/hooks/conf"; @@ -184,21 +181,10 @@ const GroupsContainer = () => { ); }; -const GroupsPage = () => { - return ( - - - - ); +export const GroupsPage = () => { + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab('groups'), [setActiveTab]); + return ; }; -const GroupsIndexPage = () => { - return ( - - } /> - } /> - - ) -} - -export default GroupsIndexPage; +export default GroupsPage; diff --git a/webui/src/pages/auth/index.jsx b/webui/src/pages/auth/index.jsx deleted file mode 100644 index 0ff37acb707..00000000000 --- a/webui/src/pages/auth/index.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; - -import {Navigate, Route, Routes} from "react-router-dom"; -import CredentialsPage from "./credentials"; -import GroupsIndexPage from "./groups"; -import UsersIndexPage from "./users"; -import PoliciesIndexPage from "./policies"; -import LoginPage from "./login"; -import ActivateInvitedUserPage from "./users/create-user-with-password"; - -const Auth = () => { - return ( - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - ) -} - -export default Auth; diff --git a/webui/src/pages/auth/login.tsx b/webui/src/pages/auth/login.tsx index 8e3a999693f..e8c650fb99a 100644 --- a/webui/src/pages/auth/login.tsx +++ b/webui/src/pages/auth/login.tsx @@ -1,5 +1,4 @@ import React, {useState} from "react"; -import Layout from "../../lib/components/layout"; import Row from "react-bootstrap/Row"; import Card from "react-bootstrap/Card"; import Form from "react-bootstrap/Form"; @@ -100,9 +99,7 @@ const LoginPage = () => { router.push({pathname: '/auth/login', query: router.query}) } return ( - - - + ); }; diff --git a/webui/src/pages/auth/policies/index.jsx b/webui/src/pages/auth/policies/index.jsx index f6a31a9c14f..020f94d9325 100644 --- a/webui/src/pages/auth/policies/index.jsx +++ b/webui/src/pages/auth/policies/index.jsx @@ -1,10 +1,9 @@ import React, {useEffect, useState} from "react"; - +import { useOutletContext } from "react-router-dom"; import Button from "react-bootstrap/Button"; import {auth} from "../../../lib/api"; import {useAPIWithPagination} from "../../../lib/hooks/api"; -import {AuthLayout} from "../../../lib/components/auth/layout"; import {ConfirmationButton} from "../../../lib/components/modals"; import {Paginator} from "../../../lib/components/pagination"; import {PolicyEditor} from "../../../lib/components/policy"; @@ -22,8 +21,6 @@ import { import {useRouter} from "../../../lib/hooks/router"; import {useLoginConfigContext} from "../../../lib/hooks/conf"; import {Link} from "../../../lib/components/nav"; -import {Route, Routes} from "react-router-dom"; -import PolicyPage from "./policy"; import { disallowPercentSign, INVALID_POLICY_ID_ERROR_MESSAGE } from "../validation"; @@ -135,20 +132,9 @@ const PoliciesContainer = () => { const PoliciesPage = () => { - return ( - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab("policies"), [setActiveTab]); + return ; }; -const PoliciesIndexPage = () => { - return ( - - } /> - } /> - - ) -} - -export default PoliciesIndexPage; +export default PoliciesPage; diff --git a/webui/src/pages/auth/policies/policy.jsx b/webui/src/pages/auth/policies/policy.jsx index 9110697ca75..c11d8b96599 100644 --- a/webui/src/pages/auth/policies/policy.jsx +++ b/webui/src/pages/auth/policies/policy.jsx @@ -1,10 +1,9 @@ -import React, {useState} from "react"; - +import React, {useEffect, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import Button from "react-bootstrap/Button"; import Form from "react-bootstrap/Form"; import {PencilIcon} from "@primer/octicons-react"; -import {AuthLayout} from "../../../lib/components/auth/layout"; import {PolicyHeader} from "../../../lib/components/auth/nav"; import {useAPI} from "../../../lib/hooks/api"; import {auth} from "../../../lib/api"; @@ -84,11 +83,9 @@ const PolicyContainer = () => { } const PolicyPage = () => { - return ( - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab("policies"), [setActiveTab]); + return ; } export default PolicyPage; diff --git a/webui/src/pages/auth/users/create-user-with-password.jsx b/webui/src/pages/auth/users/create-user-with-password.jsx index da8aa989f5f..e650ee77537 100644 --- a/webui/src/pages/auth/users/create-user-with-password.jsx +++ b/webui/src/pages/auth/users/create-user-with-password.jsx @@ -1,6 +1,6 @@ import Layout from "../../../lib/components/layout"; import React, {useRef, useState} from "react"; -import {Navigate, Route} from "react-router-dom"; +import {Navigate} from "react-router-dom"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; import Card from "react-bootstrap/Card"; @@ -103,7 +103,7 @@ export const ActivateInvitedUserPage = () => { { token ? : - } /> + } ); diff --git a/webui/src/pages/auth/users/index.jsx b/webui/src/pages/auth/users/index.jsx index 665e36e573b..65de576134c 100644 --- a/webui/src/pages/auth/users/index.jsx +++ b/webui/src/pages/auth/users/index.jsx @@ -1,9 +1,9 @@ import React, {createContext, useCallback, useEffect, useState} from "react"; -import {Route, Routes} from "react-router-dom"; +import {Outlet} from "react-router-dom"; +import { useOutletContext } from "react-router-dom"; import Button from "react-bootstrap/Button"; -import {AuthLayout} from "../../../lib/components/auth/layout"; import {useAPI, useAPIWithPagination} from "../../../lib/hooks/api"; import {auth} from "../../../lib/api"; import useUser from "../../../lib/hooks/user"; @@ -22,7 +22,6 @@ import { Loading, RefreshButton } from "../../../lib/components/controls"; -import UserPage from "./user"; import validator from "validator/es"; import { disallowPercentSign, INVALID_USER_NAME_ERROR_MESSAGE } from "../validation"; @@ -160,22 +159,23 @@ const UserActionsActionGroup = ({canInviteUsers, selected, onClickInvite, onClic ); } -const UsersPage = ({nextPage, refresh, setRefresh, error, loading, userListResults}) => { +export const UsersPage = () => { + const { setActiveTab, refresh, loading, error, nextPage, setRefresh, usersList } = useOutletContext(); + useEffect(() => setActiveTab("users"), [setActiveTab]); return ( - - - + ); }; const UsersIndexPage = () => { + const [setActiveTab] = useOutletContext(); const [refresh, setRefresh] = useState(false); const [usersList, setUsersList] = useState([]); const router = useRouter(); @@ -201,19 +201,7 @@ const UsersIndexPage = () => { return ( - - } /> - - } /> - + ) } diff --git a/webui/src/pages/auth/users/user/credentials.jsx b/webui/src/pages/auth/users/user/credentials.jsx index d0051fec7b3..4ef2eba697d 100644 --- a/webui/src/pages/auth/users/user/credentials.jsx +++ b/webui/src/pages/auth/users/user/credentials.jsx @@ -1,6 +1,5 @@ -import React, {useState} from "react"; - -import {AuthLayout} from "../../../../lib/components/auth/layout"; +import React, {useEffect, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import {UserHeaderWithContext} from "./userHeaderWithContext"; import {auth} from "../../../../lib/api"; import {CredentialsShowModal, CredentialsTable} from "../../../../lib/components/auth/credentials"; @@ -95,11 +94,9 @@ const UserCredentialsContainer = () => { }; const UserCredentialsPage = () => { - return ( - - - - ); + const {setActiveTab} = useOutletContext(); + useEffect(() => setActiveTab("users"), [setActiveTab]); + return ; }; export default UserCredentialsPage; diff --git a/webui/src/pages/auth/users/user/groups.jsx b/webui/src/pages/auth/users/user/groups.jsx index ead5816199c..f7e7d3ac251 100644 --- a/webui/src/pages/auth/users/user/groups.jsx +++ b/webui/src/pages/auth/users/user/groups.jsx @@ -1,6 +1,6 @@ -import React from "react"; +import React, {useEffect} from "react"; +import { useOutletContext } from "react-router-dom"; -import {AuthLayout} from "../../../../lib/components/auth/layout"; import {UserHeaderWithContext} from "./userHeaderWithContext"; import { ActionGroup, @@ -116,11 +116,9 @@ const UserGroupsContainer = () => { }; const UserGroupsPage = () => { - return ( - - - - ); + const {setActiveTab} = useOutletContext(); + useEffect(() => setActiveTab("users"), [setActiveTab]); + return ; }; export default UserGroupsPage; diff --git a/webui/src/pages/auth/users/user/index.jsx b/webui/src/pages/auth/users/user/index.jsx deleted file mode 100644 index f7f1698aee6..00000000000 --- a/webui/src/pages/auth/users/user/index.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; - -import {Navigate, Route, Routes} from "react-router-dom"; - -import {useRouter} from "../../../../lib/hooks/router"; -import UserGroupsPage from "./groups"; -import UserCredentialsPage from "./credentials"; -import UserEffectivePoliciesPage from "./effectivePolicies"; -import UserPoliciesPage from "./policies"; - - -const UserRedirect = ({ subPath }) => { - const router = useRouter(); - const {userId} = router.params; - return ; -} - -export default function UserPage() { - return ( - - } /> - } /> - } /> - } /> - } /> - - ); -} diff --git a/webui/src/pages/index.jsx b/webui/src/pages/index.jsx index 4c4c9459dde..cf56d4d306c 100644 --- a/webui/src/pages/index.jsx +++ b/webui/src/pages/index.jsx @@ -1,26 +1,116 @@ -import React from 'react'; - -import {BrowserRouter as Router, Routes, Route, Navigate} from 'react-router-dom'; -import {WithLoginConfigContext} from "../lib/hooks/conf"; +import React from "react"; +import { + BrowserRouter as Router, + Routes, + Route, + Navigate, +} from "react-router-dom"; +import { WithLoginConfigContext } from "../lib/hooks/conf"; // pages -import Repositories from './repositories'; -import Auth from './auth'; -import Setup from './setup'; +import RepositoriesPage from "./repositories"; +import { RepositoryPageLayout } from "../lib/components/repository/layout.jsx"; +import RepositoryObjectsPage from "./repositories/repository/objects"; +import RepositoryObjectsViewPage from "./repositories/repository/objectViewer"; +import RepositoryChangesPage from "./repositories/repository/changes"; +import RepositoryCommitsPage from "./repositories/repository/commits"; +import RepositoryCommitPage from "./repositories/repository/commits/commit"; +import RepositoryBranchesPage from "./repositories/repository/branches"; +import RepositoryTagsPage from "./repositories/repository/tags"; +import RepositoryComparePage from "./repositories/repository/compare"; +import RepositoryActionsPage from "./repositories/repository/actions"; +import RepositoryGeneralSettingsPage from "./repositories/repository/settings/general"; +import RepositoryRetentionPage from "./repositories/repository/settings/retention"; +import RepositorySettingsBranchesPage from "./repositories/repository/settings/branches"; +import { SettingsLayout } from "./repositories/repository/settings/layout"; +import Layout from "../lib/components/layout"; +import CredentialsPage from "./auth/credentials"; +import GroupsPage from "./auth/groups"; +import GroupMembersPage from "./auth/groups/group/members"; +import GroupPoliciesPage from "./auth/groups/group/policies"; +import UsersIndexPage, {UsersPage} from "./auth/users"; +import UserGroupsPage from "./auth/users/user/groups"; +import UserPoliciesPage from "./auth/users/user/policies"; +import UserEffectivePoliciesPage from "./auth/users/user/effectivePolicies"; +import UserCredentialsPage from "./auth/users/user/credentials"; +import PoliciesPage from "./auth/policies"; +import PolicyPage from "./auth/policies/policy"; +import LoginPage from "./auth/login"; +import ActivateInvitedUserPage from "./auth/users/create-user-with-password"; +import Setup from "./setup"; +import { AuthLayout } from "../lib/components/auth/layout"; +import RepositoryActionPage from "./repositories/repository/actions/run"; export const IndexPage = () => { - return ( - - - - } /> - } /> - } /> - } /> - } /> - - - - ); + return ( + + + + } /> + }> + } /> + }> + } /> + } /> + } /> + + } /> + } /> + + } /> + } /> + } /> + + } /> + } /> + + }> + } /> + } /> + } /> + } /> + + } /> + + + }> + } /> + } /> + } /> + }> + } /> + }> + } /> + + } /> + } /> + } /> + } /> + } /> + + + + } /> + + } /> + } /> + } /> + + + + } /> + } /> + + + + }> + } /> + } /> + + } /> + + + + ); }; diff --git a/webui/src/pages/repositories/index.jsx b/webui/src/pages/repositories/index.jsx index 52fe16cd7a3..72c1a42c9a8 100644 --- a/webui/src/pages/repositories/index.jsx +++ b/webui/src/pages/repositories/index.jsx @@ -1,4 +1,4 @@ -import React, {useCallback, useState} from "react"; +import React, {useCallback, useEffect, useState} from "react"; import Form from "react-bootstrap/Form"; import Row from "react-bootstrap/Row"; @@ -13,7 +13,6 @@ import {RepoIcon, SearchIcon} from "@primer/octicons-react"; import dayjs from "dayjs"; import relativeTime from "dayjs/plugin/relativeTime"; -import Layout from "../../lib/components/layout"; import {ActionsBar, AlertError, Loading, useDebouncedState} from "../../lib/components/controls"; import {config, repositories} from '../../lib/api'; import {RepositoryCreateForm} from "../../lib/components/repositoryCreateForm"; @@ -23,8 +22,6 @@ import Container from "react-bootstrap/Container"; import {Link} from "../../lib/components/nav"; import {useRouter} from "../../lib/hooks/router"; -import {Route, Routes} from "react-router-dom"; -import RepositoryPage from './repository'; import Button from "react-bootstrap/Button"; import Alert from "react-bootstrap/Alert"; @@ -137,15 +134,15 @@ const RepositoryList = ({ onPaginate, prefix, after, refresh, onCreateSampleRepo const {results, loading, error, nextPage} = useAPIWithPagination(() => { return repositories.list(prefix, after); }, [refresh, prefix, after]); - + useEffect(() => { + toggleShowActionsBar(); + }, [toggleShowActionsBar]); if (loading) return ; if (error) return ; if (!after && !prefix && results.length === 0) { return ; } - toggleShowActionsBar(); - return (
{results.map(repo => ( @@ -244,30 +241,29 @@ const RepositoriesPage = () => { }, [showCreateRepositoryModal, setShowCreateRepositoryModal, loading, err, response, createRepo]); return ( - - - {showActionsBar && -
{ e.preventDefault(); }}> - - - - - - - setPrefix(event.target.value)} - /> - - - -
- - - -
} + + {showActionsBar && +
{ e.preventDefault(); }}> + + + + + + + setPrefix(event.target.value)} + /> + + + +
+ + + +
} { createRepoError={createRepoError} /> - { - setShowCreateRepositoryModal(false); - setCreateRepoError(null); - }} - show={showCreateRepositoryModal} - error={createRepoError} - onSubmit={(repo) => createRepo(repo, true)} - samlpleRepoChecked={sampleRepoChecked} - inProgress={creatingRepo} - /> + { + setShowCreateRepositoryModal(false); + setCreateRepoError(null); + }} + show={showCreateRepositoryModal} + error={createRepoError} + onSubmit={(repo) => createRepo(repo, true)} + samlpleRepoChecked={sampleRepoChecked} + inProgress={creatingRepo} + /> -
-
+ ); } -const RepositoriesIndex = () => { - return ( - - } /> - } /> - - ); -}; - -export default RepositoriesIndex; +export default RepositoriesPage; diff --git a/webui/src/pages/repositories/repository/actions/index.jsx b/webui/src/pages/repositories/repository/actions/index.jsx index c370c1bc89a..c1c9dab93c5 100644 --- a/webui/src/pages/repositories/repository/actions/index.jsx +++ b/webui/src/pages/repositories/repository/actions/index.jsx @@ -1,5 +1,5 @@ -import React, {useState} from "react"; -import {RepositoryPageLayout} from "../../../../lib/components/repository/layout"; +import React, {useEffect, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import { ActionGroup, ActionsBar, @@ -18,10 +18,8 @@ import { import {Table} from "react-bootstrap"; import {Paginator} from "../../../../lib/components/pagination"; import {ActionStatusIcon} from "../../../../lib/components/repository/actions"; -import {Route, Routes} from "react-router-dom"; import {Link} from "../../../../lib/components/nav"; import {useRouter} from "../../../../lib/hooks/router"; -import RepositoryActionPage from "./run"; import Alert from "react-bootstrap/Alert"; import {RepoError} from "../error"; @@ -211,21 +209,10 @@ const ActionsContainer = () => { ); }; -const RepositoryActionsPage = () => { - return ( - - - - ); -}; - -const RepositoryActionsIndexPage = () => { - return ( - - } /> - } /> - - ); +export const RepositoryActionsPage = () => { + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage("actions"), [setActivePage]); + return ; }; -export default RepositoryActionsIndexPage; +export default RepositoryActionsPage; diff --git a/webui/src/pages/repositories/repository/branches.jsx b/webui/src/pages/repositories/repository/branches.jsx index 92a0b571de2..4dbc5d37c0b 100644 --- a/webui/src/pages/repositories/repository/branches.jsx +++ b/webui/src/pages/repositories/repository/branches.jsx @@ -1,5 +1,5 @@ -import React, {useMemo, useRef, useState} from "react"; - +import React, {useEffect, useMemo, useRef, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import { GitBranchIcon, LinkIcon, @@ -19,7 +19,6 @@ import { AlertError, LinkButton, Loading, PrefixSearchWidget, RefreshButton } from "../../../lib/components/controls"; -import {RepositoryPageLayout} from "../../../lib/components/repository/layout"; import {useRefs} from "../../../lib/hooks/repo"; import {useAPIWithPagination} from "../../../lib/hooks/api"; import {Paginator} from "../../../lib/components/pagination"; @@ -278,11 +277,9 @@ const BranchesContainer = () => { const RepositoryBranchesPage = () => { - return ( - - - - ) + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage("branches"), [setActivePage]); + return ; } export default RepositoryBranchesPage; diff --git a/webui/src/pages/repositories/repository/changes.jsx b/webui/src/pages/repositories/repository/changes.jsx index 1723fb0d11f..ddaf1090c2d 100644 --- a/webui/src/pages/repositories/repository/changes.jsx +++ b/webui/src/pages/repositories/repository/changes.jsx @@ -1,5 +1,5 @@ -import React, {useRef, useState} from "react"; - +import React, {useEffect, useRef, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import {GitCommitIcon, HistoryIcon,} from "@primer/octicons-react"; import Modal from "react-bootstrap/Modal"; @@ -14,7 +14,6 @@ import {useRefs} from "../../../lib/hooks/repo"; import {ConfirmationModal} from "../../../lib/components/modals"; import {ActionGroup, ActionsBar, AlertError, Loading, RefreshButton} from "../../../lib/components/controls"; import RefDropdown from "../../../lib/components/repository/refDropdown"; -import {RepositoryPageLayout} from "../../../lib/components/repository/layout"; import {formatAlertText} from "../../../lib/components/repository/errors"; import {ChangesTreeContainer, MetadataFields} from "../../../lib/components/repository/changes"; import {useRouter} from "../../../lib/hooks/router"; @@ -257,11 +256,9 @@ const ChangesContainer = () => { } const RepositoryChangesPage = () => { - return ( - - - - ) + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage('changes'), [setActivePage]); + return ; } -export default RepositoryChangesPage; +export default RepositoryChangesPage; \ No newline at end of file diff --git a/webui/src/pages/repositories/repository/commits/commit/index.jsx b/webui/src/pages/repositories/repository/commits/commit/index.jsx index 832556d2c3c..24faa52d739 100644 --- a/webui/src/pages/repositories/repository/commits/commit/index.jsx +++ b/webui/src/pages/repositories/repository/commits/commit/index.jsx @@ -1,5 +1,4 @@ -import React, {useState} from "react"; -import {RepositoryPageLayout} from "../../../../../lib/components/repository/layout"; +import React, {useEffect, useState} from "react"; import {AlertError, Loading} from "../../../../../lib/components/controls"; import {useRefs} from "../../../../../lib/hooks/repo"; import {useAPI, useAPIWithPagination} from "../../../../../lib/hooks/api"; @@ -9,6 +8,7 @@ import {useRouter} from "../../../../../lib/hooks/router"; import {URINavigator} from "../../../../../lib/components/repository/tree"; import {appendMoreResults} from "../../changes"; import {CommitInfoCard} from "../../../../../lib/components/repository/commits"; +import { useOutletContext } from "react-router-dom"; @@ -113,11 +113,10 @@ const CommitContainer = () => { } const RepositoryCommitPage = () => { - return ( - - - - ) + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage('commits'), [setActivePage]); + + return ; } export default RepositoryCommitPage; diff --git a/webui/src/pages/repositories/repository/commits/index.jsx b/webui/src/pages/repositories/repository/commits/index.jsx index 87985ddfbaf..479a02b06cc 100644 --- a/webui/src/pages/repositories/repository/commits/index.jsx +++ b/webui/src/pages/repositories/repository/commits/index.jsx @@ -1,5 +1,5 @@ -import React, {useState} from "react"; - +import React, {useEffect, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import dayjs from "dayjs"; import {BrowserIcon, LinkIcon, PackageIcon, PlayIcon} from "@primer/octicons-react"; @@ -16,15 +16,12 @@ import { LinkButton, Loading, RefreshButton } from "../../../../lib/components/controls"; -import {RepositoryPageLayout} from "../../../../lib/components/repository/layout"; import {useRefs} from "../../../../lib/hooks/repo"; import {useAPIWithPagination} from "../../../../lib/hooks/api"; import {Paginator} from "../../../../lib/components/pagination"; import RefDropdown from "../../../../lib/components/repository/refDropdown"; import {Link} from "../../../../lib/components/nav"; import {useRouter} from "../../../../lib/hooks/router"; -import {Route, Routes} from "react-router-dom"; -import RepositoryCommitPage from "./commit"; import {RepoError} from "../error"; @@ -159,20 +156,9 @@ const CommitsContainer = () => { const RepositoryCommitsPage = () => { - return ( - - - - ); + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage('commits'), [setActivePage]); + return ; }; -const RepositoryCommitsIndexPage = () => { - return ( - - } /> - } /> - - ) -} - -export default RepositoryCommitsIndexPage; +export default RepositoryCommitsPage; diff --git a/webui/src/pages/repositories/repository/compare.jsx b/webui/src/pages/repositories/repository/compare.jsx index 2a350853977..0f95c669c1f 100644 --- a/webui/src/pages/repositories/repository/compare.jsx +++ b/webui/src/pages/repositories/repository/compare.jsx @@ -1,6 +1,5 @@ -import React, {useCallback, useRef, useState} from "react"; - -import {RepositoryPageLayout} from "../../../lib/components/repository/layout"; +import React, {useCallback, useEffect, useState, useRef} from "react"; +import { useOutletContext } from "react-router-dom"; import {ActionGroup, ActionsBar, AlertError, Loading, RefreshButton} from "../../../lib/components/controls"; import {useRefs} from "../../../lib/hooks/repo"; import RefDropdown from "../../../lib/components/repository/refDropdown"; @@ -330,11 +329,9 @@ const CompareContainer = () => { }; const RepositoryComparePage = () => { - return ( - - - - ); + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage("compare"), [setActivePage]); + return ; }; export default RepositoryComparePage; diff --git a/webui/src/pages/repositories/repository/index.jsx b/webui/src/pages/repositories/repository/index.jsx deleted file mode 100644 index abe95d9816a..00000000000 --- a/webui/src/pages/repositories/repository/index.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from "react"; - -import { Navigate, Route, Routes } from "react-router-dom"; -import RepositoryObjectsPage from "./objects"; -import RepositoryChangesPage from "./changes"; -import RepositoryBranchesPage from "./branches"; -import RepositoryTagsPage from "./tags"; -import RepositoryComparePage from "./compare"; -import RepositoryCommitsIndexPage from "./commits"; -import RepositoryActionsIndexPage from "./actions"; -import RepositoryGeneralSettingsPage from "./settings/general"; -import RepositoryRetentionPage from "./settings/retention"; -import RepositorySettingsBranchesPage from "./settings/branches"; -import RepositoryObjectsViewPage from "./objectViewer"; -import { RefContextProvider } from "../../../lib/hooks/repo"; -import { StorageConfigProvider } from "../../../lib/hooks/storageConfig"; - -const RepositoryPage = () => { - return ( - - - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } - /> - } - /> - } - /> - } - /> - } /> - - - - ); -}; - -export default RepositoryPage; diff --git a/webui/src/pages/repositories/repository/objectViewer.tsx b/webui/src/pages/repositories/repository/objectViewer.tsx index 5767d55ff28..9f2ebcda5fb 100644 --- a/webui/src/pages/repositories/repository/objectViewer.tsx +++ b/webui/src/pages/repositories/repository/objectViewer.tsx @@ -11,7 +11,6 @@ import { ObjectRenderer } from "./fileRenderers"; import { AlertError } from "../../../lib/components/controls"; import { URINavigator } from "../../../lib/components/repository/tree"; import { RefTypeBranch } from "../../../constants"; -import { RepositoryPageLayout } from "../../../lib/components/repository/layout"; import { RefContextProvider } from "../../../lib/hooks/repo"; import { useStorageConfig } from "../../../lib/hooks/storageConfig"; import { linkToPath } from "../../../lib/api"; @@ -101,9 +100,7 @@ const FileObjectsViewerPage = () => { return ( - {content} - ); }; diff --git a/webui/src/pages/repositories/repository/objects.jsx b/webui/src/pages/repositories/repository/objects.jsx index ae1783d98b4..7f3d4c8b719 100644 --- a/webui/src/pages/repositories/repository/objects.jsx +++ b/webui/src/pages/repositories/repository/objects.jsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useRef, useState } from "react"; import dayjs from "dayjs"; +import { useOutletContext } from "react-router-dom"; import {CheckboxIcon, UploadIcon, XIcon} from "@primer/octicons-react"; -import { RepositoryPageLayout } from "../../../lib/components/repository/layout"; import RefDropdown from "../../../lib/components/repository/refDropdown"; import { ActionGroup, @@ -775,13 +775,10 @@ const ObjectsBrowser = ({ config, configError }) => { const RepositoryObjectsPage = () => { const config = useStorageConfig(); + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage("objects"), [setActivePage]); - return ( - - {config.loading && } - - - ); + return ; }; export default RepositoryObjectsPage; diff --git a/webui/src/pages/repositories/repository/settings/branches.jsx b/webui/src/pages/repositories/repository/settings/branches.jsx index 5f93e841c54..fcfdc83cc37 100644 --- a/webui/src/pages/repositories/repository/settings/branches.jsx +++ b/webui/src/pages/repositories/repository/settings/branches.jsx @@ -1,9 +1,8 @@ -import React, {useRef, useState} from "react"; -import {RepositoryPageLayout} from "../../../../lib/components/repository/layout"; +import React, {useEffect, useRef, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import {AlertError, Loading, RefreshButton} from "../../../../lib/components/controls"; import {useRefs} from "../../../../lib/hooks/repo"; import Card from "react-bootstrap/Card"; -import {SettingsLayout} from "./layout"; import {Button, ListGroup, Row} from "react-bootstrap"; import Col from "react-bootstrap/Col"; import {useAPI} from "../../../../lib/hooks/api"; @@ -134,13 +133,9 @@ const CreateRuleModal = ({show, hideFn, onSuccess, repoID, currentRulesResponse} } const RepositorySettingsBranchesPage = () => { - return ( - - - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab("branches"), [setActiveTab]); + return ; }; export default RepositorySettingsBranchesPage; diff --git a/webui/src/pages/repositories/repository/settings/general.jsx b/webui/src/pages/repositories/repository/settings/general.jsx index 73dc2863002..3e30d402f00 100644 --- a/webui/src/pages/repositories/repository/settings/general.jsx +++ b/webui/src/pages/repositories/repository/settings/general.jsx @@ -1,5 +1,5 @@ -import React, {useRef, useState} from "react"; - +import React, {useEffect, useRef, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import {useRefs} from "../../../../lib/hooks/repo"; import Container from "react-bootstrap/Container"; import Row from "react-bootstrap/Row"; @@ -11,8 +11,6 @@ import {AlertError, Loading} from "../../../../lib/components/controls"; import Modal from "react-bootstrap/Modal"; import {repositories} from "../../../../lib/api"; import {useRouter} from "../../../../lib/hooks/router"; -import {SettingsLayout} from "./layout"; -import {RepositoryPageLayout} from "../../../../lib/components/repository/layout"; const DeleteRepositoryModal = ({repo, show, onSubmit, onCancel}) => { const [isDisabled, setIsDisabled] = useState(true); @@ -119,13 +117,9 @@ const SettingsContainer = () => { const RepositoryGeneralSettingsPage = () => { - return ( - - - - - - ) + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab("general"), [setActiveTab]); + return ; } diff --git a/webui/src/pages/repositories/repository/settings/layout.jsx b/webui/src/pages/repositories/repository/settings/layout.jsx index ee469b03309..2359f1cdf96 100644 --- a/webui/src/pages/repositories/repository/settings/layout.jsx +++ b/webui/src/pages/repositories/repository/settings/layout.jsx @@ -1,5 +1,5 @@ -import React from "react"; - +import React, {useEffect, useState} from "react"; +import { Outlet, useOutletContext } from "react-router-dom"; import Container from "react-bootstrap/Container"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; @@ -11,8 +11,13 @@ import {Loading} from "../../../../lib/components/controls"; import {RepoError} from "../error"; -export const SettingsLayout = ({ children, activeTab }) => { +export const SettingsLayout = () => { + const [activeTab, setActiveTab] = useState("general"); const { repo, loading, error} = useRefs(); + const [setActivePage] = useOutletContext(); + useEffect(() => { + setActivePage("settings"); + }, [setActivePage]); if (loading) return ; if (error) return ; const repoId = repo.id @@ -44,10 +49,9 @@ export const SettingsLayout = ({ children, activeTab }) => { - {children} + ); }; - diff --git a/webui/src/pages/repositories/repository/settings/retention.jsx b/webui/src/pages/repositories/repository/settings/retention.jsx index 061858bd5d6..7903bf23ccb 100644 --- a/webui/src/pages/repositories/repository/settings/retention.jsx +++ b/webui/src/pages/repositories/repository/settings/retention.jsx @@ -1,5 +1,5 @@ -import React, {useState} from "react"; -import {RepositoryPageLayout} from "../../../../lib/components/repository/layout"; +import React, {useEffect, useState} from "react"; +import { useOutletContext } from "react-router-dom"; import { ActionGroup, ActionsBar, @@ -14,7 +14,6 @@ import {useAPI} from "../../../../lib/hooks/api"; import {useRefs} from "../../../../lib/hooks/repo"; import Card from "react-bootstrap/Card"; import Table from "react-bootstrap/Table"; -import {SettingsLayout} from "./layout"; import {PolicyEditor} from "../../../../lib/components/policy"; import Alert from "react-bootstrap/Alert"; @@ -168,13 +167,9 @@ const RetentionContainer = () => { } const RepositoryRetentionPage = () => { - return ( - - - - - - ); + const [setActiveTab] = useOutletContext(); + useEffect(() => setActiveTab("retention"), [setActiveTab]); + return ; }; export default RepositoryRetentionPage; diff --git a/webui/src/pages/repositories/repository/tags.jsx b/webui/src/pages/repositories/repository/tags.jsx index dd060cf0ea4..112559d615a 100644 --- a/webui/src/pages/repositories/repository/tags.jsx +++ b/webui/src/pages/repositories/repository/tags.jsx @@ -1,5 +1,5 @@ -import React, { useMemo, useRef, useState } from "react"; - +import React, { useEffect, useMemo, useRef, useState } from "react"; +import { useOutletContext } from "react-router-dom"; import { TagIcon, LinkIcon, @@ -19,7 +19,6 @@ import { AlertError, LinkButton, Loading, PrefixSearchWidget, RefreshButton } from "../../../lib/components/controls"; -import { RepositoryPageLayout } from "../../../lib/components/repository/layout"; import { useRefs } from "../../../lib/hooks/repo"; import { useAPIWithPagination } from "../../../lib/hooks/api"; import { Paginator } from "../../../lib/components/pagination"; @@ -255,11 +254,9 @@ const TagsContainer = () => { const RepositoryTagsPage = () => { - return ( - - - - ) + const [setActivePage] = useOutletContext(); + useEffect(() => setActivePage("tags"), [setActivePage]); + return ; } export default RepositoryTagsPage; diff --git a/webui/src/pages/setup/index.jsx b/webui/src/pages/setup/index.jsx index 2e35754c3f7..c475c48a889 100644 --- a/webui/src/pages/setup/index.jsx +++ b/webui/src/pages/setup/index.jsx @@ -1,5 +1,4 @@ import React, {useCallback, useEffect} from "react"; -import Layout from "../../lib/components/layout"; import {useState} from "react"; import {API_ENDPOINT, setup, SETUP_STATE_NOT_INITIALIZED, SETUP_STATE_INITIALIZED} from "../../lib/api"; import {useRouter} from "../../lib/hooks/router"; @@ -61,28 +60,24 @@ const SetupContents = () => { if (setupData && setupData.access_key_id) { return ( - - - + ); } const notInitialized = currentStep !== SETUP_STATE_INITIALIZED; if (notInitialized || commPrefsMissing) { return ( - - - + ); }