Skip to content

Commit

Permalink
[Mob navigation]: refactored Sidebar into SidebarComponent, added api…
Browse files Browse the repository at this point in the history
…RefItems into uuiApp in index.tsx
  • Loading branch information
vik753 committed Jul 26, 2024
1 parent 483e7b4 commit b7ad394
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 119 deletions.
63 changes: 63 additions & 0 deletions app/src/common/docs/SidebarComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { DocItem } from '../../documents/structure';
import { Sidebar } from '../sidebar';
import React from 'react';
import { DataRowProps } from '@epam/uui-core';
import { TreeListItem } from '@epam/uui-components';
import { useQuery } from '../../helpers';
import { TMode } from './docsConstants';
import { TTheme } from '../../data';
import { svc } from '../../services';

type DocsQuery = {
id: string,
mode?: TMode,
isSkin?: boolean,
theme?: TTheme,
category?: string
};

const redirectTo = (query: DocsQuery) =>
svc.uuiRouter.redirect({
pathname: '/documents',
query,
});

export function SidebarComponent(props: { docItems: DocItem[] }) {
const mode = useQuery<DocsQuery['mode']>('mode') || TMode.doc;
const queryParamId: string = useQuery('id');
const isSkin = useQuery<DocsQuery['isSkin']>('isSkin');
const theme = useQuery<DocsQuery['theme']>('theme');

const onChange = (row: DataRowProps<TreeListItem, string>) => {
if (row.parentId === 'components') {
redirectTo({
category: row.parentId,
mode,
id: row.id,
isSkin,
theme,
});
} else {
redirectTo({ id: row.id, category: row.parentId });
}
};

return (
<Sidebar<DocItem>
value={ queryParamId }
onValueChange={ onChange }
items={ props.docItems }
getSearchFields={ (i) => [i.name, ...(i.tags || [])] }
getItemLink={ (row) =>
!row.isFoldable && {
pathname: '/documents',
query: {
id: row.id,
mode: (row.parentId && mode),
isSkin: (row.parentId && isSkin),
category: row.parentId,
},
} }
/>
);
}
14 changes: 3 additions & 11 deletions app/src/common/docs/baseDocBlock/BaseDocsBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import { PropExplorerTab } from './tabs/propExplorerTab';
import { TabsNav } from './components/tabsNav';
import { SkinModeToggler } from './components/skinModeToggler';
import { QueryHelpers } from './utils/queryHelpers';
import { DocItem } from '../../../documents/structure';
import { Sidebar } from '../../sidebar';
import { ReactComponent as ActionAlignLeftOutlineIcon } from '@epam/assets/icons/action-align_left-outline.svg';
import { SidebarComponent } from '../SidebarComponent';
import cx from 'classnames';
//
import css from './BaseDocsBlock.module.scss';
import cx from 'classnames';

type State = {
isOpen: boolean;
Expand Down Expand Up @@ -152,7 +151,6 @@ export abstract class BaseDocsBlock extends React.Component<any, State> {
render() {
const mode = QueryHelpers.getMode();
const supportedModes = Object.values(TMode).filter((m) => this.isModeSupported(m));
const { queryParamId, onChange, items, getSearchFields, getItemLink } = this.props.sidebarProps;

return (
<div
Expand Down Expand Up @@ -182,13 +180,7 @@ export abstract class BaseDocsBlock extends React.Component<any, State> {
/>
</FlexRow>
<FlexRow borderBottom={ true } alignItems="stretch" cx={ css.sidebar }>
<Sidebar<DocItem>
value={ queryParamId }
onValueChange={ onChange }
items={ items }
getSearchFields={ getSearchFields }
getItemLink={ getItemLink }
/>
<SidebarComponent docItems={ this.props.docItems } />
</FlexRow>
</FlexCell>
) }
Expand Down
4 changes: 1 addition & 3 deletions app/src/data/apiDefinition.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { getDemoApi } from '@epam/uui-docs';
import type {
CommonContexts, UuiContexts, ITablePreset, IProcessRequest,
} from '@epam/uui-core';
import type { CommonContexts, UuiContexts, ITablePreset, IProcessRequest } from '@epam/uui-core';
import { TType, TTypeRef } from '@epam/uui-docs';
import { TDocsGenTypeSummary } from '../common/apiReference/types';
import { IUuiTokensCollection } from '../sandbox/tokens/palette/types/sharedTypes';
Expand Down
4 changes: 3 additions & 1 deletion app/src/data/appContext.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ThemeBaseParams, builtInThemes, TTheme } from './themes';
import { CustomThemeManifest, loadCustomThemes } from './customThemes';
import { DocItem } from '../documents/structure';

export interface AppContext {
themes: TTheme[],
themesById: Record<TTheme, ThemeBaseParams | CustomThemeManifest>,
apiRefItems: DocItem[],
}

export async function getAppContext() {
export async function getThemeContext() {
const customThemesArr = await loadCustomThemes();
const allThemes = [...builtInThemes, ...customThemesArr];
const themesById = allThemes.reduce<Record<TTheme, ThemeBaseParams | CustomThemeManifest>>((acc, t) => {
Expand Down
126 changes: 29 additions & 97 deletions app/src/documents/DocumentsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import React, { useEffect, useMemo, useState } from 'react';
import { DataRowProps } from '@epam/uui-core';
import { TreeListItem } from '@epam/uui-components';
import { useUuiContext } from '@epam/uui-core';
import { FlexRow } from '@epam/uui';
import { AppHeader, Page, Sidebar, TypeRefPage } from '../common';
import { svc } from '../services';
import { DocItem, items as itemsStructure } from './structure';
import { AppHeader, Page } from '../common';
import { items as itemsStructure } from './structure';
import { useQuery } from '../helpers';
import { codesandboxService } from '../data/service';
import { TMode } from '../common/docs/docsConstants';
import { TTheme } from '../data';
import { AppContext, type TApi, TTheme } from '../data';
import { SidebarComponent } from '../common/docs/SidebarComponent';

type DocsQuery = {
id: string;
Expand All @@ -18,56 +17,35 @@ type DocsQuery = {
category?: string;
};

const redirectTo = (query: DocsQuery) =>
svc.uuiRouter.redirect({
pathname: '/documents',
query,
});

async function loadApiReferenceStructure(): Promise<DocItem[]> {
if (!svc.api) {
throw new Error('svc.api not available');
}
const { content: navigation } = await svc.api.getDocsGenExports();
const root = { id: 'ApiReference', name: 'Api Reference' };
return Object.keys(navigation).reduce<DocItem[]>((acc, moduleName) => {
acc.push({ id: moduleName, name: moduleName, parentId: root.id });
navigation[moduleName].forEach((exportName) => {
acc.push({ id: `${moduleName}:${exportName}`, name: exportName, parentId: moduleName, component: TypeRefPage });
});
return acc;
}, [root]);
}

function useItems(selectedId: string) {
const [apiRefItems, setApiRefItems] = useState<DocItem[]>();

useEffect(() => {
loadApiReferenceStructure().then((res) => {
setApiRefItems(res);
});
}, []);

return useMemo(() => {
if (apiRefItems) {
const items = itemsStructure.concat(apiRefItems);
const PageComponent = items.find((item) => item.id === selectedId)?.component;
return {
items,
PageComponent,
};
}
}, [apiRefItems, selectedId]);
}

export function DocumentsPage() {
const svc = useUuiContext<TApi, AppContext>();
const queryParamId: string = useQuery('id');
const isSkin = useQuery<DocsQuery['isSkin']>('isSkin');
const theme = useQuery<DocsQuery['theme']>('theme');
const itemsInfo = useItems(queryParamId);
const mode = useQuery<DocsQuery['mode']>('mode') || TMode.doc;
const [pageWidth, setPageWidth] = useState(window.innerWidth);

const redirectTo = (query: DocsQuery) =>
svc.uuiRouter.redirect({
pathname: '/documents',
query,
});

function useItems(selectedId: string) {
const { apiRefItems } = svc.uuiApp;

return useMemo(() => {
if (apiRefItems) {
const items = itemsStructure.concat(apiRefItems);
const PageComponent = items.find((item) => item.id === selectedId)?.component;
return {
items,
PageComponent,
};
}
}, [apiRefItems, selectedId]);
}

useEffect(() => {
if (itemsInfo && !itemsInfo.PageComponent) {
redirectTo({ id: itemsInfo.items[0].id, mode: TMode.doc, isSkin: isSkin, theme: theme });
Expand All @@ -86,61 +64,15 @@ export function DocumentsPage() {
};
}, []);

const onChange = (row: DataRowProps<TreeListItem, string>) => {
if (row.parentId === 'components') {
redirectTo({
category: row.parentId,
mode,
id: row.id,
isSkin,
theme,
});
} else {
redirectTo({ id: row.id, category: row.parentId });
}
};

const PageComponent = itemsInfo?.PageComponent;

const sidebarProps = {
queryParamId,
onChange,
items: itemsInfo?.items,
getSearchFields: (i: DocItem) => [i.name, ...(i.tags || [])],
getItemLink: (row: DataRowProps<DocItem, string>) =>
!row.isFoldable && {
pathname: '/documents',
query: {
id: row.id,
mode: (row.parentId && mode),
isSkin: (row.parentId && isSkin),
category: row.parentId,
},
},
};

return (
<Page renderHeader={ () => <AppHeader /> }>
<FlexRow alignItems="stretch">
{ pageWidth > 768 && (
<Sidebar<DocItem>
value={ queryParamId }
onValueChange={ onChange }
items={ itemsInfo?.items }
getSearchFields={ (i) => [i.name, ...(i.tags || [])] }
getItemLink={ (row) =>
!row.isFoldable && {
pathname: '/documents',
query: {
id: row.id,
mode: (row.parentId && mode),
isSkin: (row.parentId && isSkin),
category: row.parentId,
},
} }
/>
<SidebarComponent docItems={ itemsInfo?.items } />
) }
{ PageComponent && <PageComponent sidebarProps={ sidebarProps } /> }
{ PageComponent && <PageComponent docItems={ itemsInfo?.items } /> }
</FlexRow>
</Page>
);
Expand Down
35 changes: 28 additions & 7 deletions app/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { createRoot } from 'react-dom/client';
import { RouterProvider } from 'react-router';
import { createBrowserRouter } from 'react-router-dom';
import { init as initApm } from '@elastic/apm-rum';
import {
Router6AdaptedRouter, useUuiServices,
UuiContext, IProcessRequest, GAListener,
} from '@epam/uui-core';
import { Router6AdaptedRouter, useUuiServices, UuiContext, IProcessRequest, GAListener } from '@epam/uui-core';
import { AmplitudeListener } from './analyticsEvents';
import { svc } from './services';
import App from './App';
import { getApi, TApi, AppContext, getAppContext } from './data';
import { getApi, TApi, AppContext, getThemeContext } from './data';
import { getAppRootNode } from './helpers/appRootUtils';
import { DocItem } from './documents/structure';
import { TypeRefPage } from './common';
import '@epam/internal/styles.css';
import '@epam/assets/theme/theme_vanilla_thunder.scss';
import '@epam/assets/theme/theme_loveship_dark.scss';
Expand Down Expand Up @@ -44,6 +43,24 @@ const apm = initApm({
});
apm.addLabels({ project: 'epm-uui', service_type: 'ui' });

const getApiRefItems = (navigation: Record<string, string[]>):DocItem[] => {
const root = { id: 'ApiReference', name: 'Api Reference' };

return Object.keys(navigation).reduce<DocItem[]>((acc, moduleName) => {
const moduleExports = navigation[moduleName];
acc.push({ id: moduleName, name: moduleName, parentId: root.id });
moduleExports.forEach((exportName) => {
acc.push({
id: `${moduleName}:${exportName}`,
name: exportName,
parentId: moduleName,
component: TypeRefPage,
});
});
return acc;
}, [root]);
};

function UuiEnhancedApp() {
const [isLoaded, setIsLoaded] = useState(false);
const { services } = useUuiServices<TApi, AppContext>({
Expand All @@ -54,9 +71,13 @@ function UuiEnhancedApp() {
});

useEffect(() => {
Object.assign(svc, services);
async function initServices() {
services.uuiApp = await getAppContext();
Object.assign(svc, services);
const docGenExports = await svc.api.getDocsGenExports();
const apiRefItems = getApiRefItems(docGenExports.content);
const themeContext = await getThemeContext();
services.uuiApp = { ...themeContext, apiRefItems };

isProduction && services.uuiAnalytics.addListener(new GAListener(GA_CODE));
services.uuiAnalytics.addListener(new AmplitudeListener(AMP_CODE));
setIsLoaded(true);
Expand Down

0 comments on commit b7ad394

Please sign in to comment.