From 8d514bd571890dac35d23b521df00277e4add9ce Mon Sep 17 00:00:00 2001 From: Nathan Panchout Date: Wed, 13 Nov 2024 15:10:02 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=84(frontend)=20add=20left=20panel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the new interface there is a new left panel. We implement it and add it to the MainLayout --- CHANGELOG.md | 1 + .../apps/impress/src/components/Icon.tsx | 8 +++ .../apps/impress/src/components/index.ts | 1 + .../separators/SeparatedSection.tsx | 32 +++++++++ .../src/cunningham/useCunninghamTheme.tsx | 3 + .../docs/doc-editor/components/DocEditor.tsx | 6 +- .../docs/doc-header/components/DocHeader.tsx | 1 + .../components/TableContent.tsx | 5 +- .../components/DocsGridContainer.tsx | 40 ----------- .../docs/docs-grid/components/index.ts | 1 - .../src/features/header/components/Header.tsx | 3 +- .../apps/impress/src/features/header/conf.ts | 1 + .../left-panel/components/LeftPanel.tsx | 70 +++++++++++++++++++ .../features/left-panel/components/index.tsx | 1 + .../{docs/docs-grid => left-panel}/index.ts | 0 .../apps/impress/src/layouts/MainLayout.tsx | 55 ++++++++++----- src/frontend/apps/impress/src/layouts/conf.ts | 1 + .../impress/src/pages/docs/[id]/index.tsx | 1 + .../apps/impress/src/pages/docs/index.tsx | 11 ++- .../impress/src/stores/useResponsiveStore.tsx | 32 ++++++++- 20 files changed, 203 insertions(+), 70 deletions(-) create mode 100644 src/frontend/apps/impress/src/components/separators/SeparatedSection.tsx delete mode 100644 src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridContainer.tsx delete mode 100644 src/frontend/apps/impress/src/features/docs/docs-grid/components/index.ts create mode 100644 src/frontend/apps/impress/src/features/header/conf.ts create mode 100644 src/frontend/apps/impress/src/features/left-panel/components/LeftPanel.tsx create mode 100644 src/frontend/apps/impress/src/features/left-panel/components/index.tsx rename src/frontend/apps/impress/src/features/{docs/docs-grid => left-panel}/index.ts (100%) create mode 100644 src/frontend/apps/impress/src/layouts/conf.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index fb27510c..b1dd211b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to - 🔧(backend) add option to configure list of essential OIDC claims #525 & #531 - 🔧(helm) add option to disable default tls setting by @dominikkaminski #519 +- 💄(frontend) Add left panel #420 ## Changed diff --git a/src/frontend/apps/impress/src/components/Icon.tsx b/src/frontend/apps/impress/src/components/Icon.tsx index 94aece6f..cdda0bbe 100644 --- a/src/frontend/apps/impress/src/components/Icon.tsx +++ b/src/frontend/apps/impress/src/components/Icon.tsx @@ -1,6 +1,14 @@ import { Text, TextType } from '@/components'; import { useCunninghamTheme } from '@/cunningham'; +type IconProps = { + iconName: string; + className?: string; +}; +export const Icon = ({ iconName, className }: IconProps) => { + return {iconName}; +}; + interface IconBGProps extends TextType { iconName: string; } diff --git a/src/frontend/apps/impress/src/components/index.ts b/src/frontend/apps/impress/src/components/index.ts index 975edfc3..2724d018 100644 --- a/src/frontend/apps/impress/src/components/index.ts +++ b/src/frontend/apps/impress/src/components/index.ts @@ -6,5 +6,6 @@ export * from './Icon'; export * from './InfiniteScroll'; export * from './Link'; export * from './SideModal'; +export * from './separators/SeparatedSection'; export * from './Text'; export * from './TextErrors'; diff --git a/src/frontend/apps/impress/src/components/separators/SeparatedSection.tsx b/src/frontend/apps/impress/src/components/separators/SeparatedSection.tsx new file mode 100644 index 00000000..9da5aaed --- /dev/null +++ b/src/frontend/apps/impress/src/components/separators/SeparatedSection.tsx @@ -0,0 +1,32 @@ +import { PropsWithChildren } from 'react'; +import { css } from 'styled-components'; + +import { useCunninghamTheme } from '@/cunningham'; + +import { Box } from '../Box'; + +type Props = { + showSeparator?: boolean; +}; + +export const SeparatedSection = ({ + showSeparator = true, + children, +}: PropsWithChildren) => { + const theme = useCunninghamTheme(); + const colors = theme.colorsTokens(); + const spacings = theme.spacingsTokens(); + return ( + + {children} + + ); +}; diff --git a/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx b/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx index 26ea5975..0de4513e 100644 --- a/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx +++ b/src/frontend/apps/impress/src/cunningham/useCunninghamTheme.tsx @@ -5,6 +5,7 @@ import { tokens } from './cunningham-tokens'; type Tokens = typeof tokens.themes.default & Partial; type ColorsTokens = Tokens['theme']['colors']; +type SpacingsTokens = Tokens['theme']['spacings']; type ComponentTokens = Tokens['components']; export type Theme = keyof typeof tokens.themes; @@ -13,6 +14,7 @@ interface AuthStore { setTheme: (theme: Theme) => void; themeTokens: () => Partial; colorsTokens: () => Partial; + spacingsTokens: () => Partial; componentTokens: () => ComponentTokens; } @@ -28,6 +30,7 @@ export const useCunninghamTheme = create((set, get) => { themeTokens: () => currentTheme().theme, colorsTokens: () => currentTheme().theme.colors, componentTokens: () => currentTheme().components, + spacingsTokens: () => currentTheme().theme.spacings, setTheme: (theme: Theme) => { set({ theme }); }, diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx index bd165df1..b297aa37 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/DocEditor.tsx @@ -43,7 +43,7 @@ export const DocEditor = ({ doc }: DocEditorProps) => { <> {!doc.abilities.partial_update && ( - + {t(`Read only, you cannot edit this document.`)} @@ -58,10 +58,10 @@ export const DocEditor = ({ doc }: DocEditorProps) => { )} { return ( <> diff --git a/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx b/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx index 559b268b..5fe946b5 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-table-content/components/TableContent.tsx @@ -1,8 +1,9 @@ -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Box, BoxButton, Text } from '@/components'; import { useEditorStore, useHeadingStore } from '@/features/docs/doc-editor'; +import { MAIN_LAYOUT_ID } from '@/layouts/conf'; import { useResponsiveStore } from '@/stores'; import { Heading } from './Heading'; @@ -43,7 +44,7 @@ export const TableContent = () => { } }; - window.addEventListener('scroll', () => { + document.getElementById(MAIN_LAYOUT_ID)?.addEventListener('scroll', () => { setTimeout(() => { handleScroll(); }, 300); diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridContainer.tsx b/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridContainer.tsx deleted file mode 100644 index 282c3e83..00000000 --- a/src/frontend/apps/impress/src/features/docs/docs-grid/components/DocsGridContainer.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { Button } from '@openfun/cunningham-react'; -import { useRouter } from 'next/router'; -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -import { Box } from '@/components'; -import { useCreateDoc, useTrans } from '@/features/docs/doc-management/'; -import { useResponsiveStore } from '@/stores'; - -import { DocsGrid } from './DocsGrid'; - -export const DocsGridContainer = () => { - const { t } = useTranslation(); - const { untitledDocument } = useTrans(); - const { push } = useRouter(); - const { isMobile } = useResponsiveStore(); - - const { mutate: createDoc } = useCreateDoc({ - onSuccess: (doc) => { - void push(`/docs/${doc.id}`); - }, - }); - - const handleCreateDoc = () => { - createDoc({ title: untitledDocument }); - }; - - return ( - - - - - - - ); -}; diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/components/index.ts b/src/frontend/apps/impress/src/features/docs/docs-grid/components/index.ts deleted file mode 100644 index 5847f905..00000000 --- a/src/frontend/apps/impress/src/features/docs/docs-grid/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './DocsGridContainer'; diff --git a/src/frontend/apps/impress/src/features/header/components/Header.tsx b/src/frontend/apps/impress/src/features/header/components/Header.tsx index c467fd13..2d5c02b7 100644 --- a/src/frontend/apps/impress/src/features/header/components/Header.tsx +++ b/src/frontend/apps/impress/src/features/header/components/Header.tsx @@ -1,5 +1,4 @@ import Image from 'next/image'; -import React from 'react'; import { useTranslation } from 'react-i18next'; import { Box, StyledLink } from '@/components/'; @@ -24,7 +23,7 @@ export const Header = () => { $width="100%" $zIndex="100" $padding={{ vertical: 'xtiny' }} - $css="box-shadow: 0 1px 4px #00000040;" + $css="border-bottom: 1px solid #EDEDED;" > { + const { t } = useTranslation(); + const router = useRouter(); + const { isDesktop } = useResponsiveStore(); + const theme = useCunninghamTheme(); + const colors = theme.colorsTokens(); + + const { mutate: createDoc } = useCreateDoc({ + onSuccess: (doc) => { + router.push(`/docs/${doc.id}`); + }, + }); + + const goToHome = () => { + router.push('/'); + }; + + const createNewDoc = () => { + createDoc({ title: t('Untitled document') }); + }; + + return ( + <> + {isDesktop && ( + +
+ + + + + + + {children} +
+
+ )} + + ); +}; diff --git a/src/frontend/apps/impress/src/features/left-panel/components/index.tsx b/src/frontend/apps/impress/src/features/left-panel/components/index.tsx new file mode 100644 index 00000000..aedb0f9e --- /dev/null +++ b/src/frontend/apps/impress/src/features/left-panel/components/index.tsx @@ -0,0 +1 @@ +export * from './LeftPanel'; diff --git a/src/frontend/apps/impress/src/features/docs/docs-grid/index.ts b/src/frontend/apps/impress/src/features/left-panel/index.ts similarity index 100% rename from src/frontend/apps/impress/src/features/docs/docs-grid/index.ts rename to src/frontend/apps/impress/src/features/left-panel/index.ts diff --git a/src/frontend/apps/impress/src/layouts/MainLayout.tsx b/src/frontend/apps/impress/src/layouts/MainLayout.tsx index bdfe587c..21af21eb 100644 --- a/src/frontend/apps/impress/src/layouts/MainLayout.tsx +++ b/src/frontend/apps/impress/src/layouts/MainLayout.tsx @@ -4,33 +4,56 @@ import { Box } from '@/components'; import { useCunninghamTheme } from '@/cunningham'; import { Footer } from '@/features/footer'; import { Header } from '@/features/header'; +import { HEADER_HEIGHT } from '@/features/header/conf'; +import { LeftPanel } from '@/features/left-panel'; +import { MAIN_LAYOUT_ID } from '@/layouts/conf'; +import { useResponsiveStore } from '@/stores'; -interface MainLayoutProps { +type MainLayoutProps = { + backgroundColor?: 'white' | 'grey'; withoutFooter?: boolean; -} +}; export function MainLayout({ children, - withoutFooter, + backgroundColor = 'white', + withoutFooter = false, }: PropsWithChildren) { + const { isDesktop } = useResponsiveStore(); const { colorsTokens } = useCunninghamTheme(); + const colors = colorsTokens(); + return ( - - -
- - - {children} - +
+
+ + + + {children} {!withoutFooter &&
} - +
); } diff --git a/src/frontend/apps/impress/src/layouts/conf.ts b/src/frontend/apps/impress/src/layouts/conf.ts new file mode 100644 index 00000000..51ff029f --- /dev/null +++ b/src/frontend/apps/impress/src/layouts/conf.ts @@ -0,0 +1 @@ +export const MAIN_LAYOUT_ID = `mainContent`; diff --git a/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx b/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx index a84119ca..ede0f454 100644 --- a/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx +++ b/src/frontend/apps/impress/src/pages/docs/[id]/index.tsx @@ -33,6 +33,7 @@ export function DocLayout() { + diff --git a/src/frontend/apps/impress/src/pages/docs/index.tsx b/src/frontend/apps/impress/src/pages/docs/index.tsx index 86414d94..729c97a8 100644 --- a/src/frontend/apps/impress/src/pages/docs/index.tsx +++ b/src/frontend/apps/impress/src/pages/docs/index.tsx @@ -1,15 +1,20 @@ import type { ReactElement } from 'react'; -import { DocsGridContainer } from '@/features/docs/docs-grid'; +import { Box } from '@/components'; +import { DocsGrid } from '@/features/docs/docs-grid/components/DocsGrid'; import { MainLayout } from '@/layouts'; import { NextPageWithLayout } from '@/types/next'; const Page: NextPageWithLayout = () => { - return ; + return ( + + + + ); }; Page.getLayout = function getLayout(page: ReactElement) { - return {page}; + return {page}; }; export default Page; diff --git a/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx b/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx index 1ca49370..4b202161 100644 --- a/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx +++ b/src/frontend/apps/impress/src/stores/useResponsiveStore.tsx @@ -4,41 +4,67 @@ export type ScreenSize = 'small-mobile' | 'mobile' | 'tablet' | 'desktop'; export interface UseResponsiveStore { isMobile: boolean; + isTablet: boolean; isSmallMobile: boolean; screenSize: ScreenSize; screenWidth: number; setScreenSize: (size: ScreenSize) => void; + isDesktop: boolean; initializeResizeListener: () => () => void; } const initialState = { isMobile: false, isSmallMobile: false, + isTablet: false, + isDesktop: false, screenSize: 'desktop' as ScreenSize, screenWidth: 0, }; export const useResponsiveStore = create((set) => ({ isMobile: initialState.isMobile, + isTablet: initialState.isTablet, isSmallMobile: initialState.isSmallMobile, screenSize: initialState.screenSize, screenWidth: initialState.screenWidth, setScreenSize: (size: ScreenSize) => set(() => ({ screenSize: size })), + isDesktop: initialState.isDesktop, initializeResizeListener: () => { const resizeHandler = () => { const width = window.innerWidth; if (width < 560) { set({ + isDesktop: false, screenSize: 'small-mobile', isMobile: true, + isTablet: false, isSmallMobile: true, }); } else if (width < 768) { - set({ screenSize: 'mobile', isMobile: true, isSmallMobile: false }); + set({ + isDesktop: false, + screenSize: 'mobile', + isTablet: false, + isMobile: true, + isSmallMobile: false, + }); } else if (width >= 768 && width < 1024) { - set({ screenSize: 'tablet', isMobile: false, isSmallMobile: false }); + set({ + isDesktop: false, + screenSize: 'tablet', + isTablet: true, + isMobile: false, + isSmallMobile: false, + }); } else { - set({ screenSize: 'desktop', isMobile: false, isSmallMobile: false }); + set({ + isDesktop: true, + screenSize: 'desktop', + isTablet: false, + isMobile: false, + isSmallMobile: false, + }); } set({ screenWidth: width });