Added create Namespace functionality to Add Tenant screen (#809)

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2021-06-14 18:00:20 -05:00
committed by GitHub
parent f208ce5382
commit e32819034a
13 changed files with 192 additions and 17 deletions

View File

@@ -1,25 +1,25 @@
{
"files": {
"main.css": "/static/css/main.8cfac526.chunk.css",
"main.js": "/static/js/main.8d2bc888.chunk.js",
"main.js.map": "/static/js/main.8d2bc888.chunk.js.map",
"main.js": "/static/js/main.f0be6105.chunk.js",
"main.js.map": "/static/js/main.f0be6105.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.43a31377.js",
"runtime-main.js.map": "/static/js/runtime-main.43a31377.js.map",
"static/css/2.c5a51b70.chunk.css": "/static/css/2.c5a51b70.chunk.css",
"static/js/2.c8e96199.chunk.js": "/static/js/2.c8e96199.chunk.js",
"static/js/2.c8e96199.chunk.js.map": "/static/js/2.c8e96199.chunk.js.map",
"static/js/2.8df217ff.chunk.js": "/static/js/2.8df217ff.chunk.js",
"static/js/2.8df217ff.chunk.js.map": "/static/js/2.8df217ff.chunk.js.map",
"index.html": "/index.html",
"static/css/2.c5a51b70.chunk.css.map": "/static/css/2.c5a51b70.chunk.css.map",
"static/css/main.8cfac526.chunk.css.map": "/static/css/main.8cfac526.chunk.css.map",
"static/js/2.c8e96199.chunk.js.LICENSE.txt": "/static/js/2.c8e96199.chunk.js.LICENSE.txt",
"static/js/2.8df217ff.chunk.js.LICENSE.txt": "/static/js/2.8df217ff.chunk.js.LICENSE.txt",
"static/media/minio_console_logo.0837460e.svg": "/static/media/minio_console_logo.0837460e.svg",
"static/media/minio_operator_logo.1312b7c9.svg": "/static/media/minio_operator_logo.1312b7c9.svg"
},
"entrypoints": [
"static/js/runtime-main.43a31377.js",
"static/css/2.c5a51b70.chunk.css",
"static/js/2.c8e96199.chunk.js",
"static/js/2.8df217ff.chunk.js",
"static/css/main.8cfac526.chunk.css",
"static/js/main.8d2bc888.chunk.js"
"static/js/main.f0be6105.chunk.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.c5a51b70.chunk.css" rel="stylesheet"><link href="/static/css/main.8cfac526.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.c8e96199.chunk.js"></script><script src="/static/js/main.8d2bc888.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="MinIO Console"/><link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;500;700;900&display=swap" rel="stylesheet"/><link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"/><link rel="manifest" href="/manifest.json"/><link rel="mask-icon" href="/safari-pinned-tab.svg" color="#3a4e54"/><title>MinIO Console</title><link href="/static/css/2.c5a51b70.chunk.css" rel="stylesheet"><link href="/static/css/main.8cfac526.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,l,i=r[0],a=r[1],p=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(f&&f(r);s.length;)s.shift()();return u.push.apply(u,p||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var a=t[i];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonpportal-ui"]=this["webpackJsonpportal-ui"]||[],a=i.push.bind(i);i.push=r,i=i.slice();for(var p=0;p<i.length;p++)r(i[p]);var f=a;t()}([])</script><script src="/static/js/2.8df217ff.chunk.js"></script><script src="/static/js/main.f0be6105.chunk.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -110,7 +110,12 @@ const DeleteServiceAccount = ({
>
Cancel
</Button>
<Button onClick={removeRecord} color="secondary" autoFocus>
<Button
onClick={removeRecord}
color="secondary"
autoFocus
disabled={deleteLoading}
>
Delete
</Button>
</DialogActions>

View File

@@ -84,6 +84,9 @@ const styles = (theme: Theme) =>
maxWidth: 15,
maxHeight: 15,
},
"&.withLabel": {
top: 27,
},
},
});
@@ -181,7 +184,11 @@ const InputBoxWrapper = ({
/>
</div>
{overlayIcon && (
<div className={classes.overlayAction}>
<div
className={`${classes.overlayAction} ${
label !== "" ? "withLabel" : ""
}`}
>
<IconButton
onClick={
overlayAction

View File

@@ -45,6 +45,8 @@ import api from "../../../../../common/api";
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper";
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
import AddIcon from "../../../../../icons/AddIcon";
import AddNamespaceModal from "./helpers/AddNamespaceModal";
const styles = (theme: Theme) =>
createStyles({
@@ -88,6 +90,8 @@ const NameTenant = ({
const [emptyNamespace, setEmptyNamespace] = useState<boolean>(true);
const [loadingNamespaceInfo, setLoadingNamespaceInfo] =
useState<boolean>(false);
const [showCreateButton, setShowCreateButton] = useState<boolean>(false);
const [openAddNSConfirm, setOpenAddNSConfirm] = useState<boolean>(false);
// Common
const updateField = useCallback(
@@ -99,6 +103,7 @@ const NameTenant = ({
// Storage classes retrieval
const getNamespaceInformation = useCallback(() => {
setShowCreateButton(false);
updateField("selectedStorageClass", "");
setStorageClassesList([]);
@@ -142,6 +147,7 @@ const NameTenant = ({
})
.catch((err: any) => {
setLoadingNamespaceInfo(false);
setShowCreateButton(true);
console.error("Namespace error: ", err);
});
})
@@ -230,8 +236,27 @@ const NameTenant = ({
setValidationErrors(clearValidationError(validationErrors, fieldName));
};
const addNamespace = () => {
setOpenAddNSConfirm(true);
};
const closeAddNamespace = (refresh: boolean) => {
setOpenAddNSConfirm(false);
if (refresh) {
debounceNamespace();
}
};
return (
<React.Fragment>
{openAddNSConfirm && (
<AddNamespaceModal
addNamespaceOpen={openAddNSConfirm}
closeAddNamespaceModalAndRefresh={closeAddNamespace}
namespace={namespace}
/>
)}
<div className={classes.headerElement}>
<h3 className={classes.h3Section}>Name Tenant</h3>
<span className={classes.descriptionText}>
@@ -263,6 +288,8 @@ const NameTenant = ({
label="Namespace"
value={namespace}
error={validationErrors["namespace"] || ""}
overlayIcon={showCreateButton ? <AddIcon /> : null}
overlayAction={addNamespace}
required
/>
</Grid>

View File

@@ -0,0 +1,136 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import {
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress,
} from "@material-ui/core";
import { createStyles, Theme, withStyles } from "@material-ui/core/styles";
import { modalBasic } from "../../../../Common/FormComponents/common/styleLibrary";
import { setErrorSnackMessage } from "../../../../../../actions";
import api from "../../../../../../common/api";
const styles = (theme: Theme) =>
createStyles({
wrapText: {
maxWidth: "200px",
whiteSpace: "normal",
wordWrap: "break-word",
},
...modalBasic,
});
interface IAddNamespace {
classes: any;
namespace: string;
addNamespaceOpen: boolean;
closeAddNamespaceModalAndRefresh: (reloadNamespaceData: boolean) => void;
setErrorSnackMessage: typeof setErrorSnackMessage;
}
const AddNamespaceModal = ({
classes,
namespace,
addNamespaceOpen,
closeAddNamespaceModalAndRefresh,
setErrorSnackMessage,
}: IAddNamespace) => {
const [addNamespaceLoading, setAddNamespaceLoading] =
useState<boolean>(false);
useEffect(() => {
if (addNamespaceLoading) {
api
.invoke("POST", "/api/v1/namespace", {
name: namespace,
})
.then((res) => {
setAddNamespaceLoading(false);
closeAddNamespaceModalAndRefresh(true);
})
.catch((err) => {
setAddNamespaceLoading(false);
setErrorSnackMessage(err);
});
}
}, [
addNamespaceLoading,
closeAddNamespaceModalAndRefresh,
namespace,
setErrorSnackMessage,
]);
const addNamespace = () => {
setAddNamespaceLoading(true);
};
return (
<Dialog
open={addNamespaceOpen}
onClose={() => {
closeAddNamespaceModalAndRefresh(false);
}}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">Create new namespace</DialogTitle>
<DialogContent>
{addNamespaceLoading && <LinearProgress />}
<DialogContentText id="alert-dialog-description">
Are you sure you want to add a namespace called{" "}
<b className={classes.wrapText}>{namespace}</b>?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button
onClick={() => {
closeAddNamespaceModalAndRefresh(false);
}}
color="primary"
disabled={addNamespaceLoading}
type="button"
className={classes.clearButton}
>
Cancel
</Button>
<Button
onClick={addNamespace}
variant="contained"
color="primary"
autoFocus
disabled={addNamespaceLoading}
>
Create Namespace
</Button>
</DialogActions>
</Dialog>
);
};
const mapDispatchToProps = {
setErrorSnackMessage,
};
const connector = connect(null, mapDispatchToProps);
export default withStyles(styles)(connector(AddNamespaceModal));