diff --git a/backend/ee/LICENSE b/backend/ee/LICENSE index 6343eec5e..3f735345e 100644 --- a/backend/ee/LICENSE +++ b/backend/ee/LICENSE @@ -1,36 +1 @@ -The Phase Console Enterprise license (the “Enterprise License”) -Copyright © 2023 Phase Security Inc. - With regard to the Phase Software: - -This software and associated documentation files (the "Software") may only be -used in production, if you (and any entity that you represent) have agreed to, -and are in compliance with, the Phase Subscription Terms of Service, available -at https://phase.dev/legal/terms, or other -agreement governing the use of the Software, as agreed by you and Phase, -and otherwise have a valid Phase Console Enterprise License for the -correct number of user seats. Subject to the foregoing sentence, you are free to -modify this Software and publish patches to the Software. You agree that Phase -and/or its licensors (as applicable) retain all right, title and interest in and -to all such modifications and/or patches, and all such modifications and/or -patches may only be used, copied, modified, displayed, distributed, or otherwise -exploited with a valid Phase Console Enterprise subscription for the correct number of -user seats. Notwithstanding the foregoing, you may copy and modify -the Software for development and testing purposes, without requiring a -subscription. You agree that Phase and/or its licensors (as applicable) retain -all right, title and interest in and to all such modifications. You are not -granted any other rights beyond what is expressly stated herein. Subject to the -foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, -and/or sell the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -For all third party components incorporated into the Phase Software, those -components are licensed under the original license provided by the owner of the -applicable component. diff --git a/frontend/app/[team]/layout.tsx b/frontend/app/[team]/layout.tsx index 42095eaf3..afa786b07 100644 --- a/frontend/app/[team]/layout.tsx +++ b/frontend/app/[team]/layout.tsx @@ -6,8 +6,12 @@ import Sidebar from '@/components/layout/Sidebar' import { organisationContext } from '@/contexts/organisationContext' import clsx from 'clsx' import { usePathname, useRouter } from 'next/navigation' -import { useContext, useEffect } from 'react' - +import { useContext, useEffect,useState } from 'react' +//Importing utilities for tree sidebar +import { useQuery } from '@apollo/client' +import { GetApps } from '@/graphql/queries/getApps.gql' +import { AppType } from '@/apollo/graphql' +import loading from '../loading' import UnlockKeyringDialog from '@/components/auth/UnlockKeyringDialog' export default function RootLayout({ @@ -15,10 +19,22 @@ export default function RootLayout({ params, }: { children: React.ReactNode - params: { team: string } -}) { - const { activeOrganisation, setActiveOrganisation, organisations, loading } = + params: { team: string, app:string } +}) { + + //Fetching app data + const { activeOrganisation, setActiveOrganisation, organisations } = useContext(organisationContext) + const { activeOrganisation: organisation } = useContext(organisationContext) + const { data } = useQuery(GetApps, { + variables: { + organisationId: organisation?.id, + }, + skip: !organisation, + }) + + const apps = data?.apps as AppType[] + const router = useRouter() @@ -44,7 +60,6 @@ export default function RootLayout({ const path = usePathname() const showNav = !path?.split('/').includes('recovery') - return (
{activeOrganisation && } {showNav && } - {showNav && } + {showNav && } {/*Sending app data*/}
{children}
) -} +} \ No newline at end of file diff --git a/frontend/components/layout/Sidebar.tsx b/frontend/components/layout/Sidebar.tsx index aac3907d0..aaba9736f 100644 --- a/frontend/components/layout/Sidebar.tsx +++ b/frontend/components/layout/Sidebar.tsx @@ -13,47 +13,95 @@ import { FaPlus, FaUsersCog, FaProjectDiagram, + FaCube } from 'react-icons/fa' import { organisationContext } from '@/contexts/organisationContext' import { Fragment, useContext } from 'react' import { OrganisationType } from '@/apollo/graphql' import { Menu, Transition } from '@headlessui/react' import { Button } from '../common/Button' +import { useState } from 'react' +//importing +import { GetAppEnvironments } from '@/graphql/queries/secrets/getAppEnvironments.gql' +import { useQuery } from '@apollo/client' + export type SidebarLinkT = { name: string href: string icon: React.ReactNode active: boolean + //added for dropdown logic + handleAppsDropDown?: () => void + arrow: boolean } const SidebarLink = (props: SidebarLinkT) => { - const { name, href, icon, active } = props + const { name, href, icon, active, handleAppsDropDown, arrow } = props; return ( - -
-
{icon}
- {name} -
- - ) -} +
+ +
+
{icon}
+ {name} +
+ + {arrow === true && ( +
+ + + +
+ )} +
+ ); +}; -const Sidebar = () => { +//Fetching App data +const Sidebar = (props:any) => { const team = usePathname()?.split('/')[1] - const { organisations, activeOrganisation } = useContext(organisationContext) + const { organisations, activeOrganisation } = useContext(organisationContext) const showOrgsMenu = organisations === null ? false : organisations?.length > 1 + const getEnvironmentData = (index:number) => { + if(props.apps){ + const { data: appEnvsData } = useQuery(GetAppEnvironments, { + variables: { + appId: props?.apps[index].id, + }, + skip: !props.apps + }) + return appEnvsData?.appEnvironments + } + } +// console.log(getEnvironmentData(0)) const OrgsMenu = () => { return ( @@ -115,6 +163,27 @@ const Sidebar = () => { ) } +// Formatting into json +// Formatting for app dropdown + if (props.apps) { + const newAppNames = props.apps.map((item:any) => ({ + name: `${item.name}`, + href: `/${team}/apps/${item.id}`, + icon: , // Replace with appropriate icon if needed + active: usePathname()?.split('/')[3] === `${item.id}`, + arrow: true + })); +// FOrmatting for each app environments dropdown + const newEnvNames = props.apps.map((app:any, index:any) => { + const environments = getEnvironmentData(index); + return environments?.map((item:any) => ({ + name: item.name, + href: `/${team}/apps/${app.id}/environments/${item.id}`, + icon: "", + active: usePathname() === `/${team}/apps/${app.id}/environments/${item.id}`, + arrow: false + })); + }).flat(); const links: SidebarLinkT[] = [ { @@ -122,67 +191,153 @@ const Sidebar = () => { href: `/${team}`, icon: , active: usePathname() === `/${team}`, + arrow: false }, { name: 'Apps', href: `/${team}/apps`, icon: , active: usePathname()?.split('/')[2] === 'apps', + arrow: true }, + ...newAppNames, + ...newEnvNames, + //Added app objects into the array { name: 'Members', href: `/${team}/members`, icon: , active: usePathname() === `/${team}/members`, + arrow: false }, { name: 'Integrations', href: `/${team}/integrations`, icon: , active: usePathname() === `/${team}/integrations`, + arrow: false }, { name: 'Personal access tokens', href: `/${team}/tokens`, icon: , active: usePathname() === `/${team}/tokens`, + arrow: false }, { name: 'Settings', href: `/${team}/settings`, icon: , active: usePathname() === `/${team}/settings`, + arrow: false }, ] + //Logic for both dropdowns + const [showDropDown, setShowDropDown] = useState(false); + const [appDropdownStates, setAppDropdownStates] = useState( + Array(newAppNames.length).fill(false) + ); + + const handleAppsDropDown = () => { + setShowDropDown(prev => !prev) + } + + const toggleDropdown = (index: number) => { + setAppDropdownStates(prev => { + const newStates = [...prev]; + newStates[index] = !newStates[index]; + return newStates; + }); + } return (
-
) -} +}} -export default Sidebar +export default Sidebar \ No newline at end of file