Portal V1, you have served us well.
This commit is contained in:
Amber Brown 2024-04-05 12:06:22 +11:00 коммит произвёл GitHub
Родитель 162164ea66
Коммит 27bc205e24
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
25 изменённых файлов: 24 добавлений и 9666 удалений

Просмотреть файл

@ -225,20 +225,6 @@
"expirationDate": null,
"type": null
},
"20cd31403587ea29d121d28ac3ef7d9b6a7b922baaf817f79ba4ccf0d5730b43": {
"signature": "20cd31403587ea29d121d28ac3ef7d9b6a7b922baaf817f79ba4ccf0d5730b43",
"alternativeSignatures": [],
"target": "portal/v1/build/main.js.LICENSE.txt",
"memberOf": [
"default"
],
"tool": "policheck",
"ruleId": "166862",
"justification": null,
"createdDate": "2022-07-14 16:28:44Z",
"expirationDate": null,
"type": null
},
"9c277a79f4467e0f7fc8eaeac774f9680776f80a1acfee7a0e3331dde2f7ef6d": {
"signature": "9c277a79f4467e0f7fc8eaeac774f9680776f80a1acfee7a0e3331dde2f7ef6d",
"alternativeSignatures": [],

Просмотреть файл

@ -167,7 +167,7 @@ run-portal:
go run -ldflags "-X github.com/Azure/ARO-RP/pkg/util/version.GitCommit=$(VERSION)" ./cmd/aro portal
build-portal:
cd portal/v1 && npm install && npm run build && cd ../v2 && npm install && npm run build
cd portal/v2 && npm install && npm run build
pyenv:
python3 -m venv pyenv

Просмотреть файл

@ -10,7 +10,7 @@ The front end is developed using react and typescript. The back end api is writt
The portal front end lives in the top level directory of the ARO-RP repo within the `portal` directory. The portal back end exists within `pkg/portal`
The front end code is compiled into go code using the bindata golang module. This front end code is then served through the RP.
The front end code is built into the `aro` binary (via go embed) and the static files are served by `aro portal`.
The admin portal also serves a static Prometheus web frontend. The contents are taken from a Prometheus release's web-ui artifact (e.g. [2.48](https://github.com/prometheus/prometheus/releases/download/v2.48.0/prometheus-web-ui-2.48.0.tar.gz)), and the static/react subdirectory is mirrored to this repository's pkg/portal/assets/prometheus-ui directory.

Просмотреть файл

@ -7,7 +7,6 @@ import (
"embed"
)
//go:embed v1/*
//go:embed v2/*
//go:embed prometheus-ui/*
var EmbeddedFiles embed.FS

Просмотреть файл

@ -1,92 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="styles.css">
<title>ARO SRE portal ({{ .location }})</title>
</head>
<body>
<div class="navbar bg-light shadow-sm">
<div class="container-fluid">
<div class="navbar-brand">
<strong>ARO SRE portal ({{ .location }})</strong>
</div>
<div>
<a href="/" class="btn btn-secondary" id="btnV2">Admin Portal V2</a>
<button class="btn btn-secondary" id="btnLogout">Logout</button>
</div>
</div>
</div>
<div class="container py-4">
<div class="form-group">
<label for="selResourceId" class="form-label">Cluster:</label>
<div class="mb-3">
<select id="selResourceId" autocomplete="off" placeholder="Search clusters..." disabled>
<option value=""></option>
</select>
</div>
</div>
<div class="form-group">
<label for="selMaster" class="form-label">Master:</label>
<div class="mb-3">
<select class="form-select" id="selMaster">
<option value="0" selected>master-0</option>
<option value="1">master-1</option>
<option value="2">master-2</option>
</select>
</div>
</div>
<button class="btn btn-secondary" id="btnPrometheus">Prometheus</button>
<button class="btn btn-secondary" id="btnKubeconfig">Kubeconfig</button>
<button class="btn btn-secondary" id="btnSSH">SSH</button>
<div class="py-4" id="divAlerts"></div>
</div>
<template id="tmplSSHAlert">
<div class="alert alert-primary alert-dismissible fade show" role="alert">
<div>
<button class="btn btn-secondary copy-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
<span data-copy="command">Command: <code></code></span>
</div>
<div class="py-2">
<button class="btn btn-secondary copy-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
<span data-copy="password">Password: <code></code></span>
</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</template>
<template id="tmplSSHAlertError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<span data-copy="error"></span>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</template>
{{ .csrfField }}
<script src="main.js"></script>
</body>
</html>

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,84 +0,0 @@
/*!
* Bootstrap alert.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap base-component.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap component-functions.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap config.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap data.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap dropdown.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap event-handler.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap index.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap manipulator.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Bootstrap selector-engine.js v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
/*!
* Sizzle CSS Selector Engine v2.3.6
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2021-02-16
*/
/*!
* jQuery JavaScript Library v3.6.1
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2022-08-26T17:52Z
*/

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,10 +1,10 @@
{
"files": {
"main.js": "/static/js/main.09fbc574.js",
"main.js": "/static/js/main.662aea13.js",
"index.html": "/index.html",
"main.09fbc574.js.map": "/static/js/main.09fbc574.js.map"
"main.662aea13.js.map": "/static/js/main.662aea13.js.map"
},
"entrypoints": [
"static/js/main.09fbc574.js"
"static/js/main.662aea13.js"
]
}

Просмотреть файл

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>ARO Portal</title><script defer="defer" src="/static/js/main.09fbc574.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><title>ARO Portal</title><script defer="defer" src="/static/js/main.662aea13.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -69,7 +69,6 @@ type portal struct {
dialer proxy.Dialer
templateV1 *template.Template
templateV2 *template.Template
templatePrometheus *template.Template
@ -134,11 +133,6 @@ func (p *portal) setupRouter(kconfig *kubeconfig.Kubeconfig, prom *prometheus.Pr
r := mux.NewRouter()
r.Use(middleware.Panic(p.log))
assetv1, err := assets.EmbeddedFiles.ReadFile("v1/build/index.html")
if err != nil {
return nil, err
}
assetv2, err := assets.EmbeddedFiles.ReadFile("v2/build/index.html")
if err != nil {
return nil, err
@ -149,11 +143,6 @@ func (p *portal) setupRouter(kconfig *kubeconfig.Kubeconfig, prom *prometheus.Pr
return nil, err
}
p.templateV1, err = template.New("index.html").Parse(string(assetv1))
if err != nil {
return nil, err
}
p.templateV2, err = template.New("index.html").Parse(string(assetv2))
if err != nil {
return nil, err
@ -325,39 +314,20 @@ func (p *portal) aadAuthenticatedRoutes(r *mux.Router, prom *prometheus.Promethe
r.Methods(http.MethodPost).Path("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/microsoft.redhatopenshift/openshiftclusters/{resourceName}/ssh/new").HandlerFunc(sshStruct.New)
for _, name := range names {
regexp, _ := regexp.Compile(`v[1,2]/build/.*\..*`)
regexp, _ := regexp.Compile(`v2/build/.*\..*`)
name := regexp.FindString(name)
switch name {
case "v2/build/index.html":
r.Methods(http.MethodGet).Path("/").HandlerFunc(p.indexV2)
r.Methods(http.MethodGet).PathPrefix("/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/microsoft.redhatopenshift/openshiftclusters/{resourceName}").HandlerFunc(p.indexV2)
case "v1/build/index.html":
r.Methods(http.MethodGet).Path("/v1").HandlerFunc(p.index)
case "":
default:
fmtName := strings.TrimPrefix(name, "v1/build/")
fmtName = strings.TrimPrefix(fmtName, "v2/build/")
fmtName := strings.TrimPrefix(name, "v2/build/")
r.Methods(http.MethodGet).Path("/" + fmtName).HandlerFunc(p.serve(name))
}
}
}
func (p *portal) index(w http.ResponseWriter, r *http.Request) {
buf := &bytes.Buffer{}
err := p.templateV1.ExecuteTemplate(buf, "index.html", map[string]interface{}{
"location": p.env.Location(),
csrf.TemplateTag: csrf.TemplateField(r),
})
if err != nil {
p.internalServerError(w, err)
return
}
http.ServeContent(w, r, "index.html", time.Time{}, bytes.NewReader(buf.Bytes()))
}
func (p *portal) indexV2(w http.ResponseWriter, r *http.Request) {
buf := &bytes.Buffer{}

Просмотреть файл

@ -123,15 +123,15 @@ func TestSecurity(t *testing.T) {
},
},
{
name: "/main.js",
name: "/asset-manifest.json",
request: func() (*http.Request, error) {
return http.NewRequest(http.MethodGet, "https://server/main.js", nil)
return http.NewRequest(http.MethodGet, "https://server/asset-manifest.json", nil)
},
wantAuditOperation: "GET /main.js",
wantAuditOperation: "GET /asset-manifest.json",
wantAuditTargetResources: []audit.TargetResource{
{
TargetResourceType: "",
TargetResourceName: "/main.js",
TargetResourceName: "/asset-manifest.json",
},
},
},
@ -359,7 +359,7 @@ func TestSecurity(t *testing.T) {
// the Payload will change during this access, resulting in the e2e panicking.
// `go test -race -timeout 30s -run ^TestSecurity$ ./pkg/portal` should show the race and
// where the concurrent read/write is occurring.
if tt.name == "/" || tt.name == "/main.js" {
if tt.name == "/" || tt.name == "/asset-manifest.json" {
err = testpoller.Poll(1*time.Second, 5*time.Millisecond, func() (bool, error) {
if len(auditHook.AllEntries()) == 1 {
if _, ok := auditHook.AllEntries()[0].Data[audit.MetadataPayload]; ok {

9046
portal/v1/package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,34 +0,0 @@
{
"name": "aro-rp",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "Microsoft",
"license": "Apache2",
"dependencies": {
"@popperjs/core": "^2.11.6",
"bootstrap": "^5.2.2",
"jquery": "^3.6.1",
"tom-select": "^2.2.2"
},
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^5.0.0",
"exports-loader": "^4.0.0",
"html-webpack-plugin": "^5.3.1",
"mini-css-extract-plugin": "^2.6.1",
"style-loader": "^3.3.1",
"webpack": "^5.76.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.11.0",
"webpack-merge": "^5.7.3"
},
"overrides": {
"minimatch": "^5.1.0"
}
}

Просмотреть файл

@ -1,92 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="styles.css">
<title>ARO SRE portal ({{ .location }})</title>
</head>
<body>
<div class="navbar bg-light shadow-sm">
<div class="container-fluid">
<div class="navbar-brand">
<strong>ARO SRE portal ({{ .location }})</strong>
</div>
<div>
<a href="/" class="btn btn-secondary" id="btnV2">Admin Portal V2</a>
<button class="btn btn-secondary" id="btnLogout">Logout</button>
</div>
</div>
</div>
<div class="container py-4">
<div class="form-group">
<label for="selResourceId" class="form-label">Cluster:</label>
<div class="mb-3">
<select id="selResourceId" autocomplete="off" placeholder="Search clusters..." disabled>
<option value=""></option>
</select>
</div>
</div>
<div class="form-group">
<label for="selMaster" class="form-label">Master:</label>
<div class="mb-3">
<select class="form-select" id="selMaster">
<option value="0" selected>master-0</option>
<option value="1">master-1</option>
<option value="2">master-2</option>
</select>
</div>
</div>
<button class="btn btn-secondary" id="btnPrometheus">Prometheus</button>
<button class="btn btn-secondary" id="btnKubeconfig">Kubeconfig</button>
<button class="btn btn-secondary" id="btnSSH">SSH</button>
<div class="py-4" id="divAlerts"></div>
</div>
<template id="tmplSSHAlert">
<div class="alert alert-primary alert-dismissible fade show" role="alert">
<div>
<button class="btn btn-secondary copy-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
<span data-copy="command">Command: <code></code></span>
</div>
<div class="py-2">
<button class="btn btn-secondary copy-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px">
<path d="M0 0h24v24H0z" fill="none" />
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" />
</svg>
</button>
<span data-copy="password">Password: <code></code></span>
</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</template>
<template id="tmplSSHAlertError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<span data-copy="error"></span>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</template>
{{ .csrfField }}
<script src="main.js"></script>
</body>
</html>

Просмотреть файл

@ -1,117 +0,0 @@
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/js/dist/util';
import 'bootstrap/js/dist/dropdown';
import 'bootstrap/js/dist/alert';
import "./select/select.css"
import 'tom-select/dist/css/tom-select.bootstrap5.min.css';
import TomSelect from 'tom-select/dist/js/tom-select.complete.min';
jQuery.extend({
redirect: function (location, args) {
var form = $("<form method='POST' style='display: none;'></form>");
form.attr("action", location);
$.each(args || {}, function (key, value) {
var input = $("<input name='hidden'></input>");
input.attr("name", key);
input.attr("value", value);
form.append(input);
});
form.append($("input[name='gorilla.csrf.Token']").first());
form.appendTo("body").submit();
}
});
jQuery(function () {
$.ajax({
url: "/api/clusters",
success: function (clusters) {
$.each(clusters, function (i, cluster) {
$("#selResourceId").append($("<option>").text(cluster.resourceId));
});
$("#selResourceId").prop("disabled", false);
new TomSelect("#selResourceId", {
plugins: ["dropdown_input"],
maxOptions: null,
maxItems: 1,
placeholder: "Search clusters...",
onDropdownOpen: function (value) {
$(".dropdown-input").val($(".ts-control").children("div").html());
}
});
$("#selResourceId").css("display", "none");
},
dataType: "json",
});
$("#btnLogout").click(function () {
$.redirect("/api/logout");
});
$("#btnKubeconfig").click(function () {
$.redirect($("#selResourceId").val() + "/kubeconfig/new");
});
$("#btnPrometheus").click(function () {
window.location = $("#selResourceId").val() + "/prometheus";
});
$("#btnSSH").click(function () {
$.ajax({
method: "POST",
url: $("#selResourceId").val() + "/ssh/new",
headers: {
"X-CSRF-Token": $("input[name='gorilla.csrf.Token']").val(),
},
contentType: "application/json",
data: JSON.stringify({
"master": parseInt($("#selMaster").val()),
}),
success: function (reply) {
if (reply["error"]) {
var template = $("#tmplSSHAlertError").html();
var alert = $(template);
alert.find("span[data-copy='error']").text(reply["error"]);
$("#divAlerts").html(alert);
return;
}
var template = $("#tmplSSHAlert").html();
var alert = $(template);
alert.find("span[data-copy='command'] > code").text(reply["command"]);
alert.find("span[data-copy='command']").attr("data-copy", reply["command"]);
alert.find("span[data-copy='password'] > code").text("********");
alert.find("span[data-copy='password']").attr("data-copy", reply["password"]);
$("#divAlerts").html(alert);
$('.copy-button').click(function () {
var textarea = $("<textarea class='style: hidden;' id='textarea'></textarea>");
textarea.text($(this).next().attr("data-copy"));
textarea.appendTo("body");
textarea = document.getElementById("textarea")
textarea.select();
textarea.setSelectionRange(0, textarea.value.length + 1);
document.execCommand('copy');
document.body.removeChild(textarea)
});
},
dataType: "json",
});
});
$("#btnV2").click(function () {
window.location = "/";
});
});

Просмотреть файл

@ -1,23 +0,0 @@
.ts-control .item {
white-space: nowrap;
padding-right: 10px;
}
.ts-dropdown [data-selectable].option {
width: fit-content;
}
.ts-dropdown-content {
overflow: auto !important;
white-space: nowrap;
}
#selResourceId {
position: relative;
width: 100%;
}
.ts-wrapper:not(.form-control):not(.form-select).single .ts-control {
background: none !important;
overflow-x: auto;
}

Просмотреть файл

@ -1,61 +0,0 @@
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../../pkg/portal/assets/v1/', 'build'),
clean: true,
},
plugins: [
new MiniCssExtractPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
new CopyPlugin({
patterns: [
{ from: "src/index.html", to: "index.html" },
],
}),
],
module: {
rules: [
{
test: /\.s?css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
optimization: {
minimizer: [
`...`,
new CssMinimizerPlugin(),
],
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
type: 'css/mini-extract',
chunks: 'all',
enforce: true,
},
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
}
},
},
},
};

Просмотреть файл

@ -1,8 +0,0 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
const fs = require('fs');
module.exports = merge(common, {
mode: 'development',
devtool: 'source-map',
});

Просмотреть файл

@ -1,6 +0,0 @@
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
});

Просмотреть файл

@ -22,7 +22,6 @@ import {
Icon,
mergeStyleSets,
registerIcons,
DefaultButton,
} from "@fluentui/react"
import { AxiosResponse } from "axios"
import { useBoolean } from "@fluentui/react-hooks"
@ -55,9 +54,9 @@ export interface ICluster {
export interface IClusterCoordinates {
subscription: string
resourceGroup: string,
name: string,
resourceId: string,
resourceGroup: string
name: string
resourceId: string
}
const stackStyles: IStackStyles = {
@ -99,22 +98,6 @@ const MenuButtonStyles: IButtonStyles = {
},
}
const v1ButtonStyle: IButtonStyles = {
root: {
backgroundColor: "transparent",
color: DefaultPalette.white,
minWidth: "50px",
height: "20px",
marginLeft: "10px",
padding: "0px",
borderColor: DefaultPalette.white,
},
rootHovered: {
backgroundColor: DefaultPalette.white,
color: DefaultPalette.themePrimary,
},
}
const darkTheme: PartialTheme = {
semanticColors: {
bodyBackground: DefaultPalette.themePrimary,
@ -309,11 +292,6 @@ function App() {
<Icon iconName={"Admin"}></Icon>
</TooltipHost>
</Stack.Item>
<Stack.Item>
<DefaultButton styles={v1ButtonStyle} title="Go to Admin Portal V1" href="/v1">
V1
</DefaultButton>
</Stack.Item>
<Stack.Item>
<IconButton
iconProps={{ iconName: "SignOut" }}
@ -326,24 +304,20 @@ function App() {
<Stack styles={contentStackStyles}>
<Stack.Item grow>{error && errorBar()}</Stack.Item>
<Stack.Item grow>
<ClusterList
csrfToken={csrfRef}
sshBox={sshRef}
csrfTokenAvailable={fetching}
/>
<ClusterList csrfToken={csrfRef} sshBox={sshRef} csrfTokenAvailable={fetching} />
</Stack.Item>
<Stack.Item grow>
<Routes>
<Route
path="/subscriptions/:subscriptionId/resourcegroups/:resourceGroupName/providers/microsoft.redhatopenshift/openshiftclusters/:resourceName/*?"
element={(
element={
<ClusterDetailPanel
csrfToken={csrfRef}
sshBox={sshRef}
loaded={fetching}
onClose={_onCloseDetailPanel}
/>
)}
}
/>
</Routes>
</Stack.Item>
@ -354,4 +328,4 @@ function App() {
)
}
export default App
export default App