Skip to content

Commit

Permalink
Make frontend work properly with custom context url (provectus#2363)
Browse files Browse the repository at this point in the history
* Add an ability to run app from subfolder

* linting

* Fix all the static resources URLs and manifest.json

Co-authored-by: Roman Zabaluev <[email protected]>
  • Loading branch information
workshur and Haarolean authored Aug 1, 2022
1 parent 5dbb90b commit fed08cb
Show file tree
Hide file tree
Showing 45 changed files with 487 additions and 255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,42 @@ public class StaticController {

@Value("classpath:static/index.html")
private Resource indexFile;
@Value("classpath:static/manifest.json")
private Resource manifestFile;

private final AtomicReference<String> renderedIndexFile = new AtomicReference<>();
private final AtomicReference<String> renderedManifestFile = new AtomicReference<>();

@GetMapping(value = "/index.html", produces = {"text/html"})
public Mono<ResponseEntity<String>> getIndex(ServerWebExchange exchange) {
return Mono.just(ResponseEntity.ok(getRenderedIndexFile(exchange)));
return Mono.just(ResponseEntity.ok(getRenderedFile(exchange, renderedIndexFile, indexFile)));
}

@GetMapping(value = "/manifest.json", produces = {"application/json"})
public Mono<ResponseEntity<String>> getManifest(ServerWebExchange exchange) {
return Mono.just(ResponseEntity.ok(getRenderedFile(exchange, renderedManifestFile, manifestFile)));
}

public String getRenderedIndexFile(ServerWebExchange exchange) {
String rendered = renderedIndexFile.get();
public String getRenderedFile(ServerWebExchange exchange, AtomicReference<String> renderedFile, Resource file) {
String rendered = renderedFile.get();
if (rendered == null) {
rendered = buildIndexFile(exchange.getRequest().getPath().contextPath().value());
if (renderedIndexFile.compareAndSet(null, rendered)) {
rendered = buildFile(file, exchange.getRequest().getPath().contextPath().value());
if (renderedFile.compareAndSet(null, rendered)) {
return rendered;
} else {
return renderedIndexFile.get();
return renderedFile.get();
}
} else {
return rendered;
}
}

@SneakyThrows
private String buildIndexFile(String contextPath) {
final String staticPath = contextPath + "/static";
return ResourceUtil.readAsString(indexFile)
.replace("href=\"./static", "href=\"" + staticPath)
.replace("src=\"./static", "src=\"" + staticPath)
.replace("window.basePath=\"\"", "window.basePath=\"" + contextPath + "\"");
private String buildFile(Resource file, String contextPath) {
return ResourceUtil.readAsString(file)
.replace("\"/assets/", "\"" + contextPath + "/assets/")
.replace("\"/favicon/", "\"" + contextPath + "/favicon/")
.replace("/manifest.json", contextPath + "/manifest.json")
.replace("window.basePath = ''", "window.basePath=\"" + contextPath + "\"");
}
}
4 changes: 4 additions & 0 deletions kafka-ui-react-app/.jest/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ module.exports = (path, options) => {
delete pkg['exports'];
delete pkg['module'];
}
if (pkg.name === 'jsonpath-plus') {
delete pkg['exports'];
delete pkg['module'];
}
return pkg;
},
});
Expand Down
21 changes: 16 additions & 5 deletions kafka-ui-react-app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" sizes="any"><!-- 32×32 -->
<link rel="icon" href="/favicon/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/favicon/apple-touch-icon.png"><!-- 180×180 -->
<meta name="viewport" content="width=device-width, initial-scale=1" />

<!-- Google fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&family=Roboto+Mono:wght@400;500&display=swap"
rel="stylesheet"
/>

<!-- Favicons -->
<link rel="icon" href="/favicon/favicon.ico" sizes="any" />
<link rel="icon" href="/favicon/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/favicon/apple-touch-icon.png" />
<link rel="manifest" href="/manifest.json" />

<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>UI for Apache Kafka</title>
<script type="text/javascript">
window.basePath = "";
window.basePath = '';
</script>
</head>

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
Expand Down
4 changes: 1 addition & 3 deletions kafka-ui-react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"@babel/core": "^7.16.0",
"@babel/plugin-syntax-flow": "^7.18.6",
"@babel/plugin-transform-react-jsx": "^7.18.6",
"@fortawesome/fontawesome-free": "^6.1.1",
"@hookform/error-message": "^2.0.0",
"@hookform/resolvers": "^2.7.1",
"@reduxjs/toolkit": "^1.8.3",
Expand All @@ -20,13 +19,12 @@
"ace-builds": "^1.7.1",
"ajv": "^8.6.3",
"babel-jest": "^28.1.1",
"bulma": "^0.9.3",
"classnames": "^2.2.6",
"dayjs": "^1.11.2",
"fetch-mock": "^9.11.0",
"jest": "^28.1.1",
"jest-watch-typeahead": "^2.0.0",
"json-schema-faker": "^0.5.0-rcv.39",
"json-schema-faker": "^0.5.0-rcv.44",
"lodash": "^4.17.21",
"pretty-ms": "7.0.1",
"react": "^18.1.0",
Expand Down
22 changes: 4 additions & 18 deletions kafka-ui-react-app/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
8 changes: 2 additions & 6 deletions kafka-ui-react-app/public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,5 @@
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
]
}
11 changes: 6 additions & 5 deletions kafka-ui-react-app/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import theme from 'theme/theme';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { showServerError } from 'lib/errorHandling';
import { Toaster } from 'react-hot-toast';

import * as S from './App.styled';
import Logo from './common/Logo/Logo';
import GitIcon from './common/Icons/GitIcon';
import DiscordIcon from './common/Icons/DiscordIcon';
import GlobalCSS from 'components/global.css';
import * as S from 'components/App.styled';
import Logo from 'components/common/Logo/Logo';
import GitIcon from 'components/common/Icons/GitIcon';
import DiscordIcon from 'components/common/Icons/DiscordIcon';

const queryClient = new QueryClient({
defaultOptions: {
Expand Down Expand Up @@ -44,6 +44,7 @@ const App: React.FC = () => {
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<GlobalCSS />
<S.Layout>
<S.Navbar role="navigation" aria-label="Page Header">
<S.NavbarBrand>
Expand Down
24 changes: 16 additions & 8 deletions kafka-ui-react-app/src/components/Cluster/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ import { BreadcrumbRoute } from 'components/common/Breadcrumb/Breadcrumb.route';
import { BreadcrumbProvider } from 'components/common/Breadcrumb/Breadcrumb.provider';
import PageLoader from 'components/common/PageLoader/PageLoader';
import { useClusters } from 'lib/hooks/api/clusters';
import Brokers from 'components/Brokers/Brokers';
import Topics from 'components/Topics/Topics';
import Schemas from 'components/Schemas/Schemas';
import Connect from 'components/Connect/Connect';
import KsqlDb from 'components/KsqlDb/KsqlDb';
import ConsumerGroups from 'components/ConsumerGroups/ConsumerGroups';

const Brokers = React.lazy(() => import('components/Brokers/Brokers'));
const Topics = React.lazy(() => import('components/Topics/Topics'));
const Schemas = React.lazy(() => import('components/Schemas/Schemas'));
const Connect = React.lazy(() => import('components/Connect/Connect'));
const KsqlDb = React.lazy(() => import('components/KsqlDb/KsqlDb'));
const ConsumerGroups = React.lazy(
() => import('components/ConsumerGroups/ConsumerGroups')
);
// We can't use Lazy loading till we have a better way to update publicPath in runtime
// Now java app replaces paths in builded index.html file.
// const Brokers = React.lazy(() => import('components/Brokers/Brokers'));
// const Topics = React.lazy(() => import('components/Topics/Topics'));
// const Schemas = React.lazy(() => import('components/Schemas/Schemas'));
// const Connect = React.lazy(() => import('components/Connect/Connect'));
// const KsqlDb = React.lazy(() => import('components/KsqlDb/KsqlDb'));
// const ConsumerGroups = React.lazy(
// () => import('components/ConsumerGroups/ConsumerGroups')
// );

const Cluster: React.FC = () => {
const { clusterName } = useAppParams<ClusterNameRoute>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ const Actions: React.FC = () => {
onClick={pauseConnectorHandler}
disabled={isMutating}
>
<span>
<i className="fas fa-pause" />
</span>
<span>Pause</span>
</Button>
)}
Expand All @@ -86,9 +83,6 @@ const Actions: React.FC = () => {
onClick={resumeConnectorHandler}
disabled={isMutating}
>
<span>
<i className="fas fa-play" />
</span>
<span>Resume</span>
</Button>
)}
Expand All @@ -100,9 +94,6 @@ const Actions: React.FC = () => {
onClick={restartConnectorHandler}
disabled={isMutating}
>
<span>
<i className="fas fa-sync-alt" />
</span>
<span>Restart Connector</span>
</Button>
<Button
Expand All @@ -112,9 +103,6 @@ const Actions: React.FC = () => {
onClick={restartAllTasksHandler}
disabled={isMutating}
>
<span>
<i className="fas fa-sync-alt" />
</span>
<span>Restart All Tasks</span>
</Button>
<Button
Expand All @@ -124,9 +112,6 @@ const Actions: React.FC = () => {
onClick={restartFailedTasksHandler}
disabled={isMutating}
>
<span>
<i className="fas fa-sync-alt" />
</span>
<span>Restart Failed Tasks</span>
</Button>
<Button
Expand All @@ -140,9 +125,6 @@ const Actions: React.FC = () => {
routerProps.connectorName
)}
>
<span>
<i className="fas fa-pencil-alt" />
</span>
<span>Edit Config</span>
</Button>

Expand All @@ -153,9 +135,6 @@ const Actions: React.FC = () => {
onClick={setDeleteConnectorConfirmationOpen}
disabled={isMutating}
>
<span>
<i className="far fa-trash-alt" />
</span>
<span>Delete</span>
</Button>
<ConfirmationModal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jest.mock('lib/hooks/api/kafkaConnect', () => ({
useConnectors: jest.fn(),
}));

jest.mock('components/common/Icons/SpinnerIcon', () => () => 'progressbar');

const clusterName = 'local';

describe('Connectors List Page', () => {
Expand Down Expand Up @@ -82,7 +84,7 @@ describe('Connectors List Page', () => {
await renderComponent();
const metrics = screen.getByRole('group');
expect(metrics).toBeInTheDocument();
expect(within(metrics).getAllByRole('progressbar').length).toEqual(3);
expect(within(metrics).getAllByText('progressbar').length).toEqual(3);
});

it('renders indicators for empty list of connectors', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import IconButtonWrapper from 'components/common/Icons/IconButtonWrapper';
import CloseIcon from 'components/common/Icons/CloseIcon';
import { yupResolver } from '@hookform/resolvers/yup';
import yup from 'lib/yupExtended';
import PlusIcon from 'components/common/Icons/PlusIcon';

import * as S from './QueryForm.styled';

Expand Down Expand Up @@ -165,7 +166,7 @@ const QueryForm: React.FC<Props> = ({
buttonType="secondary"
onClick={() => append({ key: '', value: '' })}
>
<i className="fas fa-plus" />
<PlusIcon />
Add Stream Property
</Button>
</S.StreamPropertiesContainer>
Expand Down
2 changes: 1 addition & 1 deletion kafka-ui-react-app/src/components/Nav/ClusterMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const ClusterMenu: React.FC<Props> = ({
const [isOpen, setIsOpen] = React.useState(!!singleMode);
return (
<S.List>
<S.Divider />
<hr />
<ClusterTab
title={name}
status={status}
Expand Down
Loading

0 comments on commit fed08cb

Please sign in to comment.