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 (
-
-
-
- )
-}
+
+
+
+
+ {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 (
)
}
+// 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