mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-09-26 04:54:36 +00:00
Merge branch 'origin/ui/TRA-4204_user_managment' of github.com:up9inc/mizu into feature/ui/TRA-4192_workspace_management
This commit is contained in:
@@ -11,6 +11,7 @@ import LoadingOverlay from "./LoadingOverlay";
|
||||
import SystemViewer from "./Pages/SystemViewer/SystemViewer";
|
||||
import Api from "../helpers/api";
|
||||
import {TrafficPage} from "./Pages/TrafficPage/TrafficPage";
|
||||
import SettingsPage from "./Pages/SettingsPage/SettingsPage";
|
||||
|
||||
const api = Api.getInstance();
|
||||
|
||||
@@ -69,8 +70,9 @@ const AppSwitchRoutes = () => {
|
||||
|
||||
return <Routes>
|
||||
<Route path={"/"} element={<SystemViewer isFirstLogin={isFirstLogin} setIsFirstLogin={setIsFirstLogin}/>}>
|
||||
<Route path={RouterRoutes.SETTINGS} element={<SettingsPage/>} /> {/*todo: set settings component*/}
|
||||
<Route path={"/"} element={<TrafficPage/>} />
|
||||
<Route path={RouterRoutes.SETTINGS} element={<></>} /> {/*todo: set settings component*/}
|
||||
|
||||
</Route>
|
||||
<Route path={RouterRoutes.LOGIN} element={<AuthPageBase><LoginPage/></AuthPageBase>}/>
|
||||
<Route path={RouterRoutes.SETUP} element={<AuthPageBase><InstallPage onFirstLogin={() => setIsFirstLogin(true)}/></AuthPageBase>}/>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import React from "react";
|
||||
import logo from '../assets/MizuEntLogo.svg';
|
||||
import './Header.sass';
|
||||
import userImg from '../assets/user-circle.svg';
|
||||
@@ -6,13 +6,12 @@ import settingImg from '../assets/settings.svg';
|
||||
import {Menu, MenuItem} from "@material-ui/core";
|
||||
import PopupState, {bindMenu, bindTrigger} from "material-ui-popup-state";
|
||||
import logoutIcon from '../assets/logout.png';
|
||||
import {SettingsModal} from "../SettingsModal/SettingModal";
|
||||
import Api from "../../helpers/api";
|
||||
import {toast} from "react-toastify";
|
||||
import {useSetRecoilState} from "recoil";
|
||||
import entPageAtom, {Page} from "../../recoil/entPage";
|
||||
import AdminSettings from "../Pages/SettingsPage/SettingsPage";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {RouterRoutes} from "../../helpers/routes";
|
||||
|
||||
const api = Api.getInstance();
|
||||
|
||||
@@ -23,18 +22,6 @@ interface EntHeaderProps {
|
||||
|
||||
export const EntHeader: React.FC<EntHeaderProps> = ({isFirstLogin, setIsFirstLogin}) => {
|
||||
const navigate = useNavigate();
|
||||
const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if(isFirstLogin) {
|
||||
setIsSettingsModalOpen(true)
|
||||
}
|
||||
}, [isFirstLogin])
|
||||
|
||||
const onSettingsModalClose = () => {
|
||||
setIsSettingsModalOpen(false);
|
||||
setIsFirstLogin(false);
|
||||
}
|
||||
|
||||
return <div className="header">
|
||||
<div>
|
||||
@@ -43,11 +30,9 @@ export const EntHeader: React.FC<EntHeaderProps> = ({isFirstLogin, setIsFirstLog
|
||||
</div>
|
||||
</div>
|
||||
<div style={{display: "flex", alignItems: "center"}}>
|
||||
<img className="headerIcon" alt="settings" src={settingImg} style={{marginRight: 25}} onClick={() => setIsSettingsModalOpen(true)}/>
|
||||
<img className="headerIcon" alt="settings" src={settingImg} style={{marginRight: 25}} onClick={() => navigate(RouterRoutes.SETTINGS)}/>
|
||||
<ProfileButton/>
|
||||
</div>
|
||||
{/* <SettingsModal isOpen={isSettingsModalOpen} onClose={onSettingsModalClose} isFirstLogin={isFirstLogin}/> */}
|
||||
{/* <AdminSettings isOpen={isSettingsModalOpen} onClose={onSettingsModalClose}/> */}
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
11
ui/src/components/Modals/AddUserModal/AddUserModal.lazy.tsx
Normal file
11
ui/src/components/Modals/AddUserModal/AddUserModal.lazy.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import React, { lazy, Suspense } from 'react';
|
||||
|
||||
const LazyAddUserModal = lazy(() => import('./AddUserModal'));
|
||||
|
||||
const AddUserModal = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode;isOpen:boolean }) => (
|
||||
<Suspense fallback={null}>
|
||||
<LazyAddUserModal {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
export default AddUserModal;
|
1
ui/src/components/Modals/AddUserModal/AddUserModal.sass
Normal file
1
ui/src/components/Modals/AddUserModal/AddUserModal.sass
Normal file
@@ -0,0 +1 @@
|
||||
.AddUserModal {}
|
28
ui/src/components/Modals/AddUserModal/AddUserModal.tsx
Normal file
28
ui/src/components/Modals/AddUserModal/AddUserModal.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React, { FC, useEffect, useState } from 'react';
|
||||
import ConfirmationModal from '../../UI/Modals/ConfirmationModal';
|
||||
import './AddUserModal.less';
|
||||
|
||||
interface AddUserModalProps {
|
||||
isOpen : boolean
|
||||
}
|
||||
|
||||
const AddUserModal: FC<AddUserModalProps> = ({isOpen}) => {
|
||||
|
||||
const [isOpenModal,setIsOpen] = useState(isOpen)
|
||||
|
||||
useEffect(() => {
|
||||
setIsOpen(isOpen)
|
||||
},[isOpen])
|
||||
|
||||
const onClose = () => {}
|
||||
|
||||
const onConfirm = () => {}
|
||||
|
||||
return (<>
|
||||
<ConfirmationModal isOpen={isOpenModal} onClose={onClose} onConfirm={onConfirm} title=''>
|
||||
|
||||
</ConfirmationModal>
|
||||
</>);
|
||||
};
|
||||
|
||||
export default AddUserModal;
|
@@ -0,0 +1,28 @@
|
||||
import React, { FC, useEffect, useState } from 'react';
|
||||
import ConfirmationModal from '../../UI/Modals/ConfirmationModal';
|
||||
// import './AddUserModal.sass';
|
||||
|
||||
interface AddUserModalProps {
|
||||
isOpen : boolean
|
||||
}
|
||||
|
||||
const AddUserModal: FC<AddUserModalProps> = ({isOpen}) => {
|
||||
|
||||
const [isOpenModal,setIsOpen] = useState(isOpen)
|
||||
|
||||
useEffect(() => {
|
||||
setIsOpen(isOpen)
|
||||
},[isOpen])
|
||||
|
||||
const onClose = () => {}
|
||||
|
||||
const onConfirm = () => {}
|
||||
|
||||
return (<>
|
||||
<ConfirmationModal isOpen={isOpenModal} onClose={onClose} onConfirm={onConfirm} title=''>
|
||||
|
||||
</ConfirmationModal>
|
||||
</>);
|
||||
};
|
||||
|
||||
export default AddUserModal;
|
@@ -1,4 +1,4 @@
|
||||
@import '../../variables.module.scss'
|
||||
@import '../../../variables.module.scss'
|
||||
|
||||
.NotSelectedMessage
|
||||
margin-left: 41%
|
@@ -1,9 +1,9 @@
|
||||
import { Box, Fade, FormControl, MenuItem, Modal } from "@material-ui/core";
|
||||
import { useEffect, useState } from "react";
|
||||
import { RedocStandalone } from "redoc";
|
||||
import Api from "../../helpers/api";
|
||||
import { Select } from "../UI/Select";
|
||||
import closeIcon from "../assets/closeIcon.svg";
|
||||
import Api from "../../../helpers/api";
|
||||
import { Select } from "../../UI/Select";
|
||||
import closeIcon from "../../assets/closeIcon.svg";
|
||||
import { toast } from 'react-toastify';
|
||||
import './OasModal.sass'
|
||||
|
@@ -1,5 +1,8 @@
|
||||
import React from "react";
|
||||
import { useState } from "react";
|
||||
import Tabs from "../../UI/Tabs"
|
||||
import { UserSettings } from "../../UserSettings/UserSettings";
|
||||
import { WorkspaceSettings } from "../../WorkspaceSettings/WorkspaceSettings";
|
||||
|
||||
const AdminSettings: React.FC<any> = ({color}) => {
|
||||
var TABS = [
|
||||
@@ -10,6 +13,12 @@ const AdminSettings: React.FC<any> = ({color}) => {
|
||||
return (
|
||||
<div style={{padding:" 0 1rem"}}>
|
||||
<Tabs tabs={TABS} currentTab={currentTab} color={color} onChange={setCurrentTab} leftAligned/>
|
||||
{currentTab === TABS[0].tab && <React.Fragment>
|
||||
<UserSettings/>
|
||||
</React.Fragment>}
|
||||
{currentTab === TABS[1].tab && <React.Fragment>
|
||||
<WorkspaceSettings/>
|
||||
</React.Fragment>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@ import entriesAtom from "../../../recoil/entries";
|
||||
import focusedEntryIdAtom from "../../../recoil/focusedEntryId";
|
||||
import websocketConnectionAtom, {WsConnectionStatus} from "../../../recoil/wsConnection";
|
||||
import queryAtom from "../../../recoil/query";
|
||||
import OasModal from "../../OasModal/OasModal";
|
||||
import OasModal from "../../Modals/OasModal/OasModal";
|
||||
import {useCommonStyles} from "../../../helpers/commonStyle"
|
||||
import {TLSWarning} from "../../TLSWarning/TLSWarning";
|
||||
import serviceMapModalOpenAtom from "../../../recoil/serviceMapModalOpen";
|
||||
|
63
ui/src/components/UI/FilterableTableAction.tsx
Normal file
63
ui/src/components/UI/FilterableTableAction.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Button } from "@material-ui/core";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { Table } from "./Table";
|
||||
import {useCommonStyles} from "../../helpers/commonStyle";
|
||||
import {ColsType} from "../UI/Table"
|
||||
import './style/FilterableTableAction.sass';
|
||||
|
||||
|
||||
export type {ColsType} from "../UI/Table"
|
||||
|
||||
type filterFuncFactory = (query:string) => (any) => boolean
|
||||
export interface Props {
|
||||
onRowEdit : (any) => void;
|
||||
onRowDelete : (any) => void;
|
||||
searchConfig : {searchPlaceholder : string;filterRows: filterFuncFactory};
|
||||
buttonConfig : {onClick : () => void, text:string}
|
||||
rows: any[];
|
||||
cols: ColsType[];
|
||||
}
|
||||
|
||||
export const FilterableTableAction: React.FC<Props> = ({onRowDelete,onRowEdit, searchConfig, buttonConfig, rows, cols}) => {
|
||||
|
||||
const classes = useCommonStyles()
|
||||
|
||||
const [tableRows,setRows] = useState(rows as any[])
|
||||
const [inputSearch, setInputSearch] = useState("")
|
||||
|
||||
useEffect(() => {
|
||||
setRows(rows);
|
||||
},[rows])
|
||||
|
||||
// useEffect(()=> {
|
||||
// if(inputSearch !== ""){
|
||||
// const searchFunc = searchConfig.filterRows(inputSearch)
|
||||
// const filtered = tableRows.filter(searchFunc)
|
||||
// setRows(filtered)
|
||||
// }
|
||||
// else{
|
||||
// setRows(allRows);
|
||||
// }
|
||||
// },[inputSearch])
|
||||
|
||||
const onChange = (e) => {
|
||||
setInputSearch(e.target.value)
|
||||
}
|
||||
|
||||
const filteredValues = useMemo(() => {
|
||||
const searchFunc = searchConfig.filterRows(inputSearch)
|
||||
return tableRows.filter(searchFunc)
|
||||
},[tableRows, inputSearch])
|
||||
|
||||
return (<>
|
||||
<div className="filterable-table">
|
||||
<div className="actions-header">
|
||||
<input type="text" className={classes.textField + " actions-header__search-box"} placeholder={searchConfig.searchPlaceholder} onChange={onChange}></input>
|
||||
<Button style={{height: '100%'}} className={classes.button + " actions-header__action-button"} size={"small"} onClick={buttonConfig.onClick}>
|
||||
{buttonConfig.text}
|
||||
</Button>
|
||||
</div>
|
||||
<Table rows={filteredValues} cols={cols} onRowEdit={onRowEdit} onRowDelete={onRowDelete}></Table>
|
||||
</div>
|
||||
</>);
|
||||
};
|
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { makeStyles, withStyles, Modal, Backdrop, Fade, Box } from '@material-ui/core';
|
||||
import { makeStyles, Modal, Backdrop, Fade, Box } from '@material-ui/core';
|
||||
import {useCommonStyles} from "../../../helpers/commonStyle";
|
||||
import { PropertiesTable } from 'redoc/typings/common-elements';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
modal: {
|
||||
|
@@ -1,22 +1,25 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import './style/Table.sass';
|
||||
import editImg from "../assets/edit.svg";
|
||||
import deleteImg from "../assets/delete.svg"
|
||||
import circleImg from "../assets/dotted-circle.svg"
|
||||
import Delete from '@material-ui/icons/Delete';
|
||||
import Edit from '@material-ui/icons/Edit';
|
||||
|
||||
export interface ColsType {
|
||||
field:string,
|
||||
cellClassName?: string,
|
||||
header:string,
|
||||
width?:number,
|
||||
getCellClassName?:(field:string,value : any) => string
|
||||
};
|
||||
|
||||
interface Props {
|
||||
interface TableProps {
|
||||
rows : any[];
|
||||
cols : {field:string, cellClassName?: string,header:string, width?:number,
|
||||
getCellClassName?:(field:string,value : any) => string}[];
|
||||
cols : ColsType[]
|
||||
onRowEdit : (any) => void;
|
||||
onRowDelete : (any) => void;
|
||||
noDataMeesage : string;
|
||||
noDataMeesage? : string;
|
||||
}
|
||||
|
||||
export const Table: React.FC<Props> = ({rows, cols, onRowDelete, onRowEdit,noDataMeesage}) => {
|
||||
export const Table: React.FC<TableProps> = ({rows, cols, onRowDelete, onRowEdit, noDataMeesage = "No Data Found"}) => {
|
||||
|
||||
const [tableRows, updateTableRows] = useState(rows);
|
||||
|
||||
@@ -31,11 +34,16 @@ export const Table: React.FC<Props> = ({rows, cols, onRowDelete, onRowEdit,noDat
|
||||
const _onRowDelete = (row) => {
|
||||
onRowDelete(row);
|
||||
}
|
||||
|
||||
// const filteredValues = useMemo(() => {
|
||||
// return tableRows.filter((listValue) => listValue.find(row));
|
||||
// },[tableRows, searchValue])
|
||||
|
||||
return <table cellPadding={5} style={{borderCollapse: "collapse"}} className="mui-table">
|
||||
<thead className="mui-table__thead">
|
||||
<tr style={{borderBottomWidth: "2px"}} className="mui-table__tr">
|
||||
{cols?.map((col)=> {
|
||||
return <th className="mui-table__th">{col.header}</th>
|
||||
return <th key={col.header} className="mui-table__th">{col.header}</th>
|
||||
})}
|
||||
<th></th>
|
||||
</tr>
|
||||
@@ -44,18 +52,19 @@ export const Table: React.FC<Props> = ({rows, cols, onRowDelete, onRowEdit,noDat
|
||||
{
|
||||
((tableRows == null) || (tableRows.length === 0)) ?
|
||||
<tr className="mui-table__no-data">
|
||||
<img src={circleImg} alt="No data Found"></img>
|
||||
<div className="mui-table__no-data-message">{noDataMeesage}</div>
|
||||
{/* <img src={circleImg} alt="No data Found"></img>
|
||||
<div className="mui-table__no-data-message">{noDataMeesage}</div> */}
|
||||
</tr>
|
||||
|
||||
:
|
||||
|
||||
tableRows?.map(rowData => {
|
||||
return <tr key={rowData?.id} className="mui-table__tr">
|
||||
{cols.map(col => {
|
||||
return <td className={`${col.getCellClassName ? col.getCellClassName(col.field, rowData[col.field]) : ""}
|
||||
${col?.cellClassName ?? ""} mui-table__td`}>
|
||||
{rowData[col.field]}
|
||||
tableRows?.map((rowData,index) => {
|
||||
return <tr key={rowData?.id ?? index} className="mui-table__tr">
|
||||
{cols.map((col,index) => {
|
||||
return <td key={`${rowData?.id} + ${index}`} className="mui-table__td">
|
||||
<span key={Math.random().toString()} className={`${col.getCellClassName ? col.getCellClassName(col.field, rowData[col.field]) : ""}${col?.cellClassName ?? ""}`}>
|
||||
{rowData[col.field]}
|
||||
</span>
|
||||
</td>
|
||||
})}
|
||||
<td className="mui-table__td mui-table__row-actions">
|
||||
|
15
ui/src/components/UI/style/FilterableTableAction.sass
Normal file
15
ui/src/components/UI/style/FilterableTableAction.sass
Normal file
@@ -0,0 +1,15 @@
|
||||
@import '../../../variables.module'
|
||||
|
||||
.filterable-table
|
||||
padding: 0 5%;
|
||||
|
||||
.actions-header
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
&__search-box
|
||||
width : 313px;
|
||||
|
||||
&__action-button
|
||||
height: 100%
|
@@ -67,26 +67,4 @@
|
||||
@mixin row-actions
|
||||
display: flex
|
||||
justify-content: flex-end
|
||||
|
||||
|
||||
@mixin status-base($bg_color, $color, $border)
|
||||
box-sizing: border-box
|
||||
border-radius: 4px
|
||||
height : 20px
|
||||
width : 63px
|
||||
display: flex
|
||||
align-content: center
|
||||
justify-content: center
|
||||
align-items: center
|
||||
background: $bg_color
|
||||
color: $color
|
||||
border: $border
|
||||
|
||||
.status
|
||||
&--active
|
||||
@include status-base(rgba(111, 207, 151, 0.5), #247E4B, 1px solid #219653)
|
||||
|
||||
&--pending
|
||||
@include status-base(rgba(242, 201, 76, 0.5), #8C7325, 1px solid #F2994A)
|
||||
|
||||
|
||||
|
21
ui/src/components/UserSettings/UserSettings.sass
Normal file
21
ui/src/components/UserSettings/UserSettings.sass
Normal file
@@ -0,0 +1,21 @@
|
||||
@import '../../variables.module'
|
||||
|
||||
@mixin status-base($bg_color, $color, $border)
|
||||
box-sizing: border-box
|
||||
border-radius: 4px
|
||||
height : 20px
|
||||
width : 63px
|
||||
display: flex
|
||||
align-content: center
|
||||
justify-content: center
|
||||
align-items: center
|
||||
background: $bg_color
|
||||
color: $color
|
||||
border: $border
|
||||
|
||||
.status
|
||||
&--active
|
||||
@include status-base(rgba(111, 207, 151, 0.5), #247E4B, 1px solid #219653)
|
||||
|
||||
&--pending
|
||||
@include status-base(rgba(242, 201, 76, 0.5), #8C7325, 1px solid #F2994A)
|
61
ui/src/components/UserSettings/UserSettings.tsx
Normal file
61
ui/src/components/UserSettings/UserSettings.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import "./UserSettings.sass"
|
||||
import {ColsType, FilterableTableAction} from "../UI/FilterableTableAction"
|
||||
// import Api from "../../helpers/api"
|
||||
import { useEffect, useState } from "react";
|
||||
import AddUserModal from "../Modals/AddUserModal/AddUserModal";
|
||||
|
||||
interface Props {
|
||||
|
||||
}
|
||||
|
||||
// const api = Api.getInstance();
|
||||
|
||||
export const UserSettings : React.FC<Props> = ({}) => {
|
||||
|
||||
const [usersRows, setUserRows] = useState([]);
|
||||
const cols : ColsType[] = [{field : "userName",header:"User"},
|
||||
{field : "role",header:"Role"},
|
||||
{field : "status",header:"Status",getCellClassName : (field, val) =>{
|
||||
return val === "Active" ? "status--active" : "status--pending"
|
||||
}}]
|
||||
const [isOpenModal,setIsOpen] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const users = [{userName:"asd",role:"Admin",status:"Active"}]//await api.getUsers()
|
||||
setUserRows(users)
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
})();
|
||||
},[])
|
||||
|
||||
const filterFuncFactory = (searchQuery: string) => {
|
||||
return (row) => {
|
||||
return row.userName.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
}
|
||||
}
|
||||
|
||||
const searchConfig = { searchPlaceholder: "Search User",filterRows: filterFuncFactory}
|
||||
|
||||
const onRowDelete = (row) => {
|
||||
const filterFunc = filterFuncFactory(row.userName)
|
||||
const newUserList = usersRows.filter(filterFunc)
|
||||
setUserRows(newUserList)
|
||||
}
|
||||
|
||||
const onRowEdit = (row) => {
|
||||
// open Edit user Modal
|
||||
}
|
||||
|
||||
const buttonConfig = {onClick: () => {setIsOpen(true)}, text:"Add User"}
|
||||
return (<>
|
||||
<FilterableTableAction onRowEdit={onRowEdit} onRowDelete={onRowDelete} searchConfig={searchConfig}
|
||||
buttonConfig={buttonConfig} rows={usersRows} cols={cols}>
|
||||
</FilterableTableAction>
|
||||
<AddUserModal isOpen={isOpenModal}>
|
||||
|
||||
</AddUserModal>
|
||||
</>);
|
||||
}
|
51
ui/src/components/WorkspaceSettings/WorkspaceSettings.tsx
Normal file
51
ui/src/components/WorkspaceSettings/WorkspaceSettings.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import "../UserSettings/UserSettings.sass"
|
||||
import {ColsType, FilterableTableAction} from "../UI/FilterableTableAction"
|
||||
// import Api from "../../helpers/api"
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
interface Props {}
|
||||
|
||||
// const api = Api.getInstance();
|
||||
|
||||
export const WorkspaceSettings : React.FC<Props> = ({}) => {
|
||||
|
||||
const [workspacesRows, setWorkspaces] = useState([]);
|
||||
const cols : ColsType[] = [{field : "id",header:"Id"},{field : "name",header:"Name"}]
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const workspacesDemo = [{id:"1", name:"Worksapce1"}]
|
||||
setWorkspaces(workspacesDemo)
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
})();
|
||||
},[])
|
||||
|
||||
const filterFuncFactory = (searchQuery: string) => {
|
||||
return (row) => {
|
||||
return row.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
}
|
||||
}
|
||||
|
||||
const searchConfig = { searchPlaceholder: "Search Workspace",filterRows: filterFuncFactory}
|
||||
|
||||
const onRowDelete = (row) => {
|
||||
const filterFunc = filterFuncFactory(row.name)
|
||||
const newWorkspaceList = workspacesRows.filter(filterFunc)
|
||||
setWorkspaces(newWorkspaceList)
|
||||
}
|
||||
|
||||
const onRowEdit = (row) => {
|
||||
|
||||
}
|
||||
|
||||
const buttonConfig = {onClick: () => {}, text:"Add Workspace"}
|
||||
return (<>
|
||||
<FilterableTableAction onRowEdit={onRowEdit} onRowDelete={onRowDelete} searchConfig={searchConfig}
|
||||
buttonConfig={buttonConfig} rows={workspacesRows} cols={cols}>
|
||||
</FilterableTableAction>
|
||||
</>);
|
||||
}
|
@@ -48,6 +48,16 @@ export default class Api {
|
||||
return response.data;
|
||||
}
|
||||
|
||||
getUsers = async(filter = "") =>{
|
||||
const response = await this.client.get(`/user/listUsers?usernameFilter=${filter}`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
getWorkspaces = async() =>{
|
||||
const response = await this.client.get(``);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
analyzeStatus = async () => {
|
||||
const response = await this.client.get("/status/analyze");
|
||||
return response.data;
|
||||
|
@@ -6,6 +6,9 @@ import 'react-toastify/dist/ReactToastify.css';
|
||||
import {RecoilRoot} from "recoil";
|
||||
import AppChooser from "./AppChooser";
|
||||
|
||||
window["isOasEnabled"]=true;
|
||||
window["isServiceMapEnabled"]=true;
|
||||
|
||||
ReactDOM.render( <>
|
||||
<RecoilRoot>
|
||||
<AppChooser/>
|
||||
|
Reference in New Issue
Block a user