Skip to content

Commit

Permalink
Explicitly use global layout for each page instead of handling relate…
Browse files Browse the repository at this point in the history
…d stuff in ApplicationArea component
  • Loading branch information
kravets-levko committed Jan 10, 2020
1 parent e4350f0 commit a65f5f5
Show file tree
Hide file tree
Showing 32 changed files with 398 additions and 213 deletions.
54 changes: 8 additions & 46 deletions client/app/components/ApplicationArea/index.jsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,23 @@
import React, { useState, useEffect } from "react";
import ApplicationHeader from "@/components/ApplicationHeader";

import routes from "@/pages";

import Router from "./Router";
import DefaultAuthenticated from "./layout/DefaultAuthenticated";
import DefaultSignedOut from "./layout/DefaultSignedOut";
import handleNavigationIntent from "./handleNavigationIntent";

const layouts = {
default: {
showHeader: true,
bodyClass: false,
},
fixed: {
showHeader: true,
bodyClass: "fixed-layout",
},
defaultSignedOut: {
showHeader: false,
},
export const Layout = {
DefaultAuthenticated,
DefaultSignedOut,
};

function selectLayout(route) {
let layout = layouts.default;
if (route.layout) {
layout = layouts[route.layout] || layouts.default;
} else if (!route.authenticated) {
layout = layouts.defaultSignedOut;
}
return layout;
}

export default function ApplicationArea() {
const [showHeader, setShowHeader] = useState(false);

// TODO: This is needed to refresh header when route changes
// Better solution is either to move header to each page or create some global state for currentUser/clientConfig/etc.
const [currentRoute, setCurrentRoute] = useState(null);

useEffect(() => {
const route = currentRoute || { authenticated: true };

if (route.title) {
document.title = route.title;
}

const layout = selectLayout(route);
setShowHeader(layout.showHeader);
if (layout.bodyClass) {
document.body.classList.toggle(layout.bodyClass, true);
return () => {
document.body.classList.toggle(layout.bodyClass, false);
};
if (currentRoute && currentRoute.title) {
document.title = currentRoute.title;
}
}, [currentRoute]);

Expand All @@ -62,10 +29,5 @@ export default function ApplicationArea() {
};
});

return (
<>
{currentRoute && showHeader && <ApplicationHeader currentRoute={currentRoute} />}
<Router routes={routes} onRouteChange={setCurrentRoute} />
</>
);
return <Router routes={routes} onRouteChange={setCurrentRoute} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { Auth } from "@/services/auth";
import organizationStatus from "@/services/organizationStatus";
import ApplicationHeader from "./ApplicationHeader";

export default function DefaultAuthenticated({ bodyClass, children }) {
const [isAuthenticated, setIsAuthenticated] = useState(!!Auth.isAuthenticated());

useEffect(() => {
let isCancelled = false;
Promise.all([Auth.requireSession(), organizationStatus.refresh()])
.then(() => {
if (!isCancelled) {
setIsAuthenticated(!!Auth.isAuthenticated());
}
})
.catch(() => {
if (!isCancelled) {
setIsAuthenticated(false);
}
});
return () => {
isCancelled = true;
};
}, []);

useEffect(() => {
if (bodyClass) {
document.body.classList.toggle(bodyClass, true);
return () => {
document.body.classList.toggle(bodyClass, false);
};
}
}, [bodyClass]);

if (!isAuthenticated) {
return null;
}

return (
<>
<ApplicationHeader />
{children}
</>
);
}

DefaultAuthenticated.propTypes = {
bodyClass: PropTypes.string,
children: PropTypes.node,
};

DefaultAuthenticated.defaultProps = {
bodyClass: null,
children: null,
};
41 changes: 41 additions & 0 deletions client/app/components/ApplicationArea/layout/DefaultSignedOut.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { Auth } from "@/services/auth";

export default function DefaultSignedOut({ apiKey, children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);

useEffect(() => {
let isCancelled = false;
Auth.setApiKey(apiKey);
Auth.loadConfig()
.then(() => {
if (!isCancelled) {
setIsAuthenticated(true);
}
})
.catch(() => {
if (!isCancelled) {
setIsAuthenticated(false);
}
});
return () => {
isCancelled = true;
};
}, [apiKey]);

if (!isAuthenticated) {
return null;
}

return children;
}

DefaultSignedOut.propTypes = {
apiKey: PropTypes.string.isRequired,
children: PropTypes.node,
};

DefaultSignedOut.defaultProps = {
children: null,
};
13 changes: 9 additions & 4 deletions client/app/pages/admin/Jobs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import React from "react";
import Alert from "antd/lib/alert";
import Tabs from "antd/lib/tabs";
import * as Grid from "antd/lib/grid";
import Layout from "@/components/admin/Layout";
import { Layout } from "@/components/ApplicationArea";
import AdminPageLayout from "@/components/admin/Layout";
import { CounterCard } from "@/components/admin/CeleryStatus";
import { WorkersTable, QueuesTable, OtherJobsTable } from "@/components/admin/RQStatus";

Expand Down Expand Up @@ -86,7 +87,7 @@ class Jobs extends React.Component {
};

return (
<Layout activeTab="jobs">
<AdminPageLayout activeTab="jobs">
<div className="p-15">
{error && <Alert type="error" message="Failed loading status. Please refresh." />}

Expand Down Expand Up @@ -115,14 +116,18 @@ class Jobs extends React.Component {
</React.Fragment>
)}
</div>
</Layout>
</AdminPageLayout>
);
}
}

export default {
path: "/admin/queries/jobs",
title: "RQ Status",
render: (routeParams, currentRoute, location) => <Jobs key={location.path} {...routeParams} />,
render: (routeParams, currentRoute, location) => (
<Layout.DefaultAuthenticated>
<Jobs key={location.path} {...routeParams} />
</Layout.DefaultAuthenticated>
),
resolve: { currentPage: "jobs" },
};
11 changes: 7 additions & 4 deletions client/app/pages/admin/OutdatedQueries.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import React from "react";

import Switch from "antd/lib/switch";
import * as Grid from "antd/lib/grid";
import { Layout } from "@/components/ApplicationArea";
import Paginator from "@/components/Paginator";
import { QueryTagsControl } from "@/components/tags-control/TagsControl";
import SchedulePhrase from "@/components/queries/SchedulePhrase";
import TimeAgo from "@/components/TimeAgo";
import Layout from "@/components/admin/Layout";
import AdminPageLayout from "@/components/admin/Layout";

import { wrap as itemsList, ControllerType } from "@/components/items-list/ItemsList";
import { ItemsSource } from "@/components/items-list/classes/ItemsSource";
Expand Down Expand Up @@ -89,7 +90,7 @@ class OutdatedQueries extends React.Component {
render() {
const { controller } = this.props;
return (
<Layout activeTab={controller.params.currentPage}>
<AdminPageLayout activeTab={controller.params.currentPage}>
<Grid.Row className="m-15">
<Grid.Col span={16}>
<div>
Expand Down Expand Up @@ -140,7 +141,7 @@ class OutdatedQueries extends React.Component {
/>
</div>
)}
</Layout>
</AdminPageLayout>
);
}
}
Expand Down Expand Up @@ -173,7 +174,9 @@ export default {
path: "/admin/queries/outdated",
title: "Outdated Queries",
render: (routeParams, currentRoute, location) => (
<OutdatedQueriesPage key={location.path} routeParams={routeParams} currentRoute={currentRoute} />
<Layout.DefaultAuthenticated>
<OutdatedQueriesPage key={location.path} routeParams={routeParams} currentRoute={currentRoute} />
</Layout.DefaultAuthenticated>
),
resolve: { currentPage: "outdated_queries" },
};
13 changes: 9 additions & 4 deletions client/app/pages/admin/SystemStatus.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { omit } from "lodash";
import React from "react";
import PropTypes from "prop-types";

import Layout from "@/components/admin/Layout";
import { Layout } from "@/components/ApplicationArea";
import AdminPageLayout from "@/components/admin/Layout";
import * as StatusBlock from "@/components/admin/StatusBlock";

import { $http } from "@/services/ng";
Expand Down Expand Up @@ -65,7 +66,7 @@ class SystemStatus extends React.Component {

render() {
return (
<Layout activeTab="system_status">
<AdminPageLayout activeTab="system_status">
<div className="system-status-page">
<div className="system-status-page-blocks">
<div className="system-status-page-block">
Expand All @@ -82,7 +83,7 @@ class SystemStatus extends React.Component {
</div>
</div>
</div>
</Layout>
</AdminPageLayout>
);
}
}
Expand All @@ -91,6 +92,10 @@ class SystemStatus extends React.Component {
export default {
path: "/admin/status",
title: "System Status",
render: (routeParams, currentRoute, location) => <SystemStatus key={location.path} {...routeParams} />,
render: (routeParams, currentRoute, location) => (
<Layout.DefaultAuthenticated>
<SystemStatus key={location.path} {...routeParams} />
</Layout.DefaultAuthenticated>
),
resolve: { currentPage: "system_status" },
};
13 changes: 9 additions & 4 deletions client/app/pages/admin/Tasks.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import React from "react";
import Alert from "antd/lib/alert";
import Tabs from "antd/lib/tabs";
import * as Grid from "antd/lib/grid";
import Layout from "@/components/admin/Layout";
import { Layout } from "@/components/ApplicationArea";
import AdminPageLayout from "@/components/admin/Layout";
import { CounterCard, QueuesTable, QueriesTable } from "@/components/admin/CeleryStatus";

import { $http } from "@/services/ng";
Expand Down Expand Up @@ -80,7 +81,7 @@ class Tasks extends React.Component {
const { isLoading, error, queues, queries, counters } = this.state;

return (
<Layout activeTab="tasks">
<AdminPageLayout activeTab="tasks">
<div className="p-15">
{error && <Alert type="error" message="Failed loading status. Please refresh." />}

Expand Down Expand Up @@ -109,14 +110,18 @@ class Tasks extends React.Component {
</React.Fragment>
)}
</div>
</Layout>
</AdminPageLayout>
);
}
}

export default {
path: "/admin/queries/tasks",
title: "Celery Status",
render: (routeParams, currentRoute, location) => <Tasks key={location.path} {...routeParams} />,
render: (routeParams, currentRoute, location) => (
<Layout.DefaultAuthenticated>
<Tasks key={location.path} {...routeParams} />
</Layout.DefaultAuthenticated>
),
resolve: { currentPage: "tasks" },
};
19 changes: 16 additions & 3 deletions client/app/pages/alert/Alert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";
import PropTypes from "prop-types";

import { currentUser } from "@/services/auth";
import { Layout } from "@/components/ApplicationArea";
import navigateTo from "@/components/ApplicationArea/navigateTo";
import notification from "@/services/notification";
import { Alert as AlertService } from "@/services/alert";
Expand Down Expand Up @@ -257,19 +258,31 @@ export default [
{
path: "/alerts/new",
title: "New Alert",
render: (routeParams, currentRoute, location) => <AlertPage key={location.path} {...routeParams} />,
render: (routeParams, currentRoute, location) => (
<Layout.DefaultAuthenticated>
<AlertPage key={location.path} {...routeParams} />
</Layout.DefaultAuthenticated>
),
resolve: { mode: MODES.NEW },
},
{
path: "/alerts/:alertId([0-9]+)",
title: "Alert",
render: (routeParams, currentRoute, location) => <AlertPage key={location.path} {...routeParams} />,
render: (routeParams, currentRoute, location) => (
<Layout.DefaultAuthenticated>
<AlertPage key={location.path} {...routeParams} />
</Layout.DefaultAuthenticated>
),
resolve: { mode: MODES.VIEW },
},
{
path: "/alerts/:alertId([0-9]+)/edit",
title: "Alert",
render: (routeParams, currentRoute, location) => <AlertPage key={location.path} {...routeParams} />,
render: (routeParams, currentRoute, location) => (
<Layout.DefaultAuthenticated>
<AlertPage key={location.path} {...routeParams} />
</Layout.DefaultAuthenticated>
),
resolve: { mode: MODES.EDIT },
},
];
5 changes: 4 additions & 1 deletion client/app/pages/alerts/AlertsList.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { toUpper } from "lodash";
import React from "react";
import { Layout } from "@/components/ApplicationArea";
import PageHeader from "@/components/PageHeader";
import Paginator from "@/components/Paginator";
import EmptyState from "@/components/empty-state/EmptyState";
Expand Down Expand Up @@ -126,7 +127,9 @@ export default {
path: "/alerts",
title: "Alerts",
render: (routeParams, currentRoute, location) => (
<AlertsListPage key={location.path} routeParams={routeParams} currentRoute={currentRoute} />
<Layout.DefaultAuthenticated>
<AlertsListPage key={location.path} routeParams={routeParams} currentRoute={currentRoute} />
</Layout.DefaultAuthenticated>
),
resolve: { currentPage: "alerts" },
};
Loading

0 comments on commit a65f5f5

Please sign in to comment.