Skip to content

Commit

Permalink
Dashboard: use Next.js app router
Browse files Browse the repository at this point in the history
  • Loading branch information
pepakriz committed Apr 8, 2024
1 parent c421173 commit 01e5f18
Show file tree
Hide file tree
Showing 11 changed files with 141 additions and 169 deletions.
14 changes: 13 additions & 1 deletion dashboard/next.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
module.exports = {
// @ts-check

/** @type {import('next').NextConfig} */
const nextConfig = {
env: {
API_URL: process.env.API_URL,
WS_URL: process.env.WS_URL,
},
output: 'export',
experimental: {
typedRoutes: true,
},
typescript: {
// We can ignore it because we have another job in the pipeline for static analysis
ignoreBuildErrors: true,
},
};

module.exports = nextConfig;
11 changes: 11 additions & 0 deletions dashboard/src/app/ApolloWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use client';

import React, { useState } from 'react';
import { initApolloClient } from '../lib/apollo';
import { ApolloProvider } from '@apollo/client';

export const ApolloWrapper = ({ children }: { children: React.ReactNode }) => {
const [client] = useState(initApolloClient);

return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
48 changes: 48 additions & 0 deletions dashboard/src/app/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ApolloClient, InMemoryCache, split } from '@apollo/client';
import { registerApolloClient } from '@apollo/experimental-nextjs-app-support/rsc';
import { getMainDefinition } from '@apollo/client/utilities';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
import { createClient } from 'graphql-ws';
import { HttpLink } from '@apollo/client/link/http';

export const { getClient } = registerApolloClient(() => {
let apiUrl = process.env.API_URL;
if (apiUrl === undefined && typeof window !== 'undefined') {
apiUrl = `${window.location.protocol}//${window.location.host}/graphql`;
}

const httpLink = new HttpLink({
uri: apiUrl,
credentials: 'same-origin',
});

let wsUrl = process.env.WS_URL;
if (wsUrl === undefined) {
wsUrl = `${window.location.protocol === 'http:' ? 'ws' : 'wss'}://${
window.location.host
}/graphql`;
}

const wsLink = new GraphQLWsLink(
createClient({
url: wsUrl,
}),
);

const link = split(
// split based on operation type
({ query }) => {
const definition = getMainDefinition(query);
return (
definition.kind === 'OperationDefinition' && definition.operation === 'subscription'
);
},
wsLink,
httpLink,
);

return new ApolloClient({
cache: new InMemoryCache(),
link,
});
});
37 changes: 37 additions & 0 deletions dashboard/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { Metadata } from 'next';
import theme from '../theme';
import { AppRouterCacheProvider } from '@mui/material-nextjs/v13-appRouter';
import { ThemeProvider } from '@mui/material/styles';
import CssBaseline from '@mui/material/CssBaseline';
import { Layout } from '../components/layout';
import { ApolloWrapper } from './ApolloWrapper';

export const metadata: Metadata = {
title: 'GitLab Merger Bot',
description: 'Welcome to Next.js',
};

export default function RootLayout({ children }: { children: React.ReactElement }) {
return (
<html lang='en'>
<head>
<meta
name='viewport'
content='minimum-scale=1, initial-scale=1, width=device-width'
/>
</head>
<body style={{ backgroundColor: '#f8f8f8' }}>
<ApolloWrapper>
<AppRouterCacheProvider>
<ThemeProvider theme={theme}>
<CssBaseline />

<Layout>{children}</Layout>
</ThemeProvider>
</AppRouterCacheProvider>
</ApolloWrapper>
</body>
</html>
);
}
13 changes: 4 additions & 9 deletions dashboard/src/pages/index.tsx → dashboard/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
'use client';

import React from 'react';
import { withApollo } from '../lib/apollo';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Layout from '../components/layout';
import { useMutation, useSubscription } from '@apollo/client';
import gql from 'graphql-tag';
import OverlayLoading from '../components/ui/overlay-loading';
Expand All @@ -25,7 +25,6 @@ import Toolbar from '@mui/material/Toolbar';
import Icon from '@mui/icons-material/Send';
import { UserAvatar } from '../components/ui/UserAvatar';
import CircularProgress from '@mui/material/CircularProgress';
import { NextPageWithLayout } from './_app';

const Row = (props: GetQueuesSubscriptionJobFragment) => {
const [unassign, { loading }] = useMutation<UnassignMutation, UnassignMutationVariables>(gql`
Expand Down Expand Up @@ -83,7 +82,7 @@ const Row = (props: GetQueuesSubscriptionJobFragment) => {
);
};

const App = () => {
export default function Page() {
const { loading, error, data } = useSubscription<GetQueuesSubscriptionSubscription>(gql`
fragment GetQueuesSubscriptionJob on Job {
status
Expand Down Expand Up @@ -151,8 +150,4 @@ const App = () => {
</Box>
</>
);
};

App.getLayout = Layout;

export default App;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client';

import React from 'react';
import { withApollo } from '../lib/apollo';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Layout from '../components/layout';
import { useSubscription } from '@apollo/client';
import gql from 'graphql-tag';
import OverlayLoading from '../components/ui/overlay-loading';
import { GetWebHookHistorySubscriptionSubscription } from '../types';
import OverlayLoading from '../../components/ui/overlay-loading';
import { GetWebHookHistorySubscriptionSubscription } from '../../types';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
Expand All @@ -15,7 +15,6 @@ import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import Button from '@mui/material/Button';
import Icon from '@mui/icons-material/Send';
import { Collapse } from '@mui/material';
import { KeyboardArrowDown, KeyboardArrowUp } from '@mui/icons-material';

Expand Down Expand Up @@ -72,7 +71,7 @@ const Row = ({
);
};

const App = () => {
export default function Page() {
const { loading, error, data } = useSubscription<GetWebHookHistorySubscriptionSubscription>(gql`
subscription GetWebHookHistorySubscription {
webHookHistory {
Expand Down Expand Up @@ -114,8 +113,4 @@ const App = () => {
</Box>
</>
);
};

App.getLayout = Layout;

export default App;
}
14 changes: 8 additions & 6 deletions dashboard/src/components/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use client';

import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
Expand All @@ -9,7 +11,8 @@ import { useQuery } from '@apollo/client';
import { MeQuery } from '../types';
import gql from 'graphql-tag';
import { Tab, Tabs } from '@mui/material';
import { useRouter } from 'next/router';
import { usePathname, useRouter } from 'next/navigation';
import { Route } from 'next';

const pages = {
'/': {
Expand All @@ -18,9 +21,10 @@ const pages = {
'/web-hook-history': {
label: 'Web Hook History',
},
};
} satisfies Record<Route, { label: string }>;

export const Layout = (children: React.ReactElement) => {
export const Layout = ({ children }: { children: React.ReactElement }) => {
const pathname = usePathname();
const router = useRouter();
const { data } = useQuery<MeQuery>(gql`
query Me {
Expand All @@ -31,7 +35,7 @@ export const Layout = (children: React.ReactElement) => {
}
`);

const tabIndex = Object.keys(pages).findIndex((path) => router.pathname === path);
const tabIndex = Object.keys(pages).findIndex((path) => pathname === path);

return (
<>
Expand Down Expand Up @@ -63,5 +67,3 @@ export const Layout = (children: React.ReactElement) => {
</>
);
};

export default Layout;
70 changes: 2 additions & 68 deletions dashboard/src/lib/apollo.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { NextPage, NextPageContext } from 'next';
import React from 'react';
import { createClient } from 'graphql-ws';
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';

import {
ApolloProvider,
ApolloClient,
InMemoryCache,
NormalizedCacheObject,
Expand All @@ -15,72 +12,9 @@ import { HttpLink } from '@apollo/client/link/http';

type TApolloClient = ApolloClient<NormalizedCacheObject>;

type InitialProps = {
apolloClient?: TApolloClient;
apolloState?: any;
} & Record<string, any>;

type WithApolloPageContext = {
apolloClient: TApolloClient;
} & NextPageContext;

let globalApolloClient: TApolloClient;

export function withApollo(PageComponent: NextPage, { ssr = true } = {}) {
const WithApollo = ({ apolloClient, apolloState, ...pageProps }: InitialProps) => {
const client = apolloClient || initApolloClient(apolloState);
return (
<ApolloProvider client={client}>
<PageComponent {...pageProps} />
</ApolloProvider>
);
};

if (ssr || PageComponent.getInitialProps) {
WithApollo.getInitialProps = async (ctx: WithApolloPageContext) => {
const { AppTree } = ctx;
const apolloClient = (ctx.apolloClient = initApolloClient());

let pageProps = {};
if (PageComponent.getInitialProps) {
pageProps = await PageComponent.getInitialProps(ctx);
}

if (typeof window === 'undefined') {
if (ctx.res && ctx.res.finished) {
return pageProps;
}

if (ssr) {
try {
const { getDataFromTree } = await import('@apollo/client/react/ssr');
await getDataFromTree(
<AppTree
pageProps={{
...pageProps,
apolloClient,
}}
/>,
);
} catch (error) {
console.error('Error while running `getDataFromTree`', error);
}
}
}

const apolloState = apolloClient.cache.extract();

return {
...pageProps,
apolloState,
};
};
}

return WithApollo;
}

function initApolloClient(initialState?: {}) {
export function initApolloClient(initialState?: {}) {
if (typeof window === 'undefined') {
return createApolloClient(initialState);
}
Expand All @@ -92,7 +26,7 @@ function initApolloClient(initialState?: {}) {
return globalApolloClient;
}

function createApolloClient(initialState = {}) {
export function createApolloClient(initialState = {}) {
const ssrMode = typeof window === 'undefined';
const cache = new InMemoryCache().restore(initialState);

Expand Down
41 changes: 0 additions & 41 deletions dashboard/src/pages/_app.tsx

This file was deleted.

Loading

0 comments on commit 01e5f18

Please sign in to comment.