From 726db15aa8bfbeae5ce936f5a292324cb85d0eea Mon Sep 17 00:00:00 2001 From: Leon <> Date: Tue, 25 Jan 2022 11:57:18 +0200 Subject: [PATCH 1/2] Add userSettings --- .../components/UI/FilterableTableAction.tsx | 60 +++++++++++++++++++ ui/src/components/UI/Table.tsx | 18 +++--- .../UI/style/FilterableTableAction.sass | 15 +++++ .../components/UserSettings/UserSettings.sass | 2 + .../components/UserSettings/UserSettings.tsx | 53 ++++++++++++++++ ui/src/helpers/api.js | 5 ++ 6 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 ui/src/components/UI/FilterableTableAction.tsx create mode 100644 ui/src/components/UI/style/FilterableTableAction.sass create mode 100644 ui/src/components/UserSettings/UserSettings.sass create mode 100644 ui/src/components/UserSettings/UserSettings.tsx diff --git a/ui/src/components/UI/FilterableTableAction.tsx b/ui/src/components/UI/FilterableTableAction.tsx new file mode 100644 index 000000000..734b4103a --- /dev/null +++ b/ui/src/components/UI/FilterableTableAction.tsx @@ -0,0 +1,60 @@ +import { Button } from "@material-ui/core"; +import React, { useEffect, 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 = ({onRowDelete,onRowEdit, searchConfig, buttonConfig, rows, cols}) => { + + const classes = useCommonStyles() + + const [tableRows,setRows] = useState(rows as any[]) + const [inputSearch, setInputSearch] = useState("") + let allRows = rows; + + useEffect(() => { + allRows = rows; + 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) + } + + return (<> +
+
+ + +
+
+
+ ); +}; \ No newline at end of file diff --git a/ui/src/components/UI/Table.tsx b/ui/src/components/UI/Table.tsx index e8506c7f5..1ea3d7d56 100644 --- a/ui/src/components/UI/Table.tsx +++ b/ui/src/components/UI/Table.tsx @@ -1,22 +1,26 @@ 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 = ({rows, cols, onRowDelete, onRowEdit,noDataMeesage}) => { +export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, noDataMeesage = "No Data Found"}) => { const [tableRows, updateTableRows] = useState(rows); diff --git a/ui/src/components/UI/style/FilterableTableAction.sass b/ui/src/components/UI/style/FilterableTableAction.sass new file mode 100644 index 000000000..bea6b042b --- /dev/null +++ b/ui/src/components/UI/style/FilterableTableAction.sass @@ -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% \ No newline at end of file diff --git a/ui/src/components/UserSettings/UserSettings.sass b/ui/src/components/UserSettings/UserSettings.sass new file mode 100644 index 000000000..0bc06f8e3 --- /dev/null +++ b/ui/src/components/UserSettings/UserSettings.sass @@ -0,0 +1,2 @@ +@import '../../../variables.module' + diff --git a/ui/src/components/UserSettings/UserSettings.tsx b/ui/src/components/UserSettings/UserSettings.tsx new file mode 100644 index 000000000..30b28b4ff --- /dev/null +++ b/ui/src/components/UserSettings/UserSettings.tsx @@ -0,0 +1,53 @@ +import "./UserSettings" +import {useCommonStyles} from "../../helpers/commonStyle"; +import {ColsType, FilterableTableAction} from "../UI/FilterableTableAction" +import Api from "../../helpers/api" +import { useEffect, useState } from "react"; + +interface Props { + +} + +const api = Api.getInstance(); + +export const UserSettings : React.FC = ({}) => { + + const [usersRows, setUserRows] = useState([]); + const cols : ColsType[] = [{field : "userName",header:"User"},{field : "role",header:"Role"}, {field : "role",header:"Role"}] + + + useEffect(() => { + (async () => { + try { + const users = await api.getUsers() + setUserRows(usersRows) + } catch (e) { + console.error(e); + } + })(); + },[]) + + const filterFuncFactory = (searchQuery: string) => { + return (row) => { + return row.userName.toLowercase().includes(searchQuery.toLowerCase()) > -1 + } + } + + 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) => { + + } + + const buttonConfig = {onClick: () => {}, text:"Add User"} + return (<> + + + ); +} diff --git a/ui/src/helpers/api.js b/ui/src/helpers/api.js index ae85c78a6..47813e4f2 100644 --- a/ui/src/helpers/api.js +++ b/ui/src/helpers/api.js @@ -48,6 +48,11 @@ export default class Api { return response.data; } + getUsers = async(filter = "") =>{ + const response = await this.client.get(`/user/listUsers?usernameFilter=${filter}`); + return response.data; + } + analyzeStatus = async () => { const response = await this.client.get("/status/analyze"); return response.data; From 6c88b0ef4657e3cc0f3baef652db6dcbabb20783 Mon Sep 17 00:00:00 2001 From: Leon <> Date: Tue, 25 Jan 2022 17:51:07 +0200 Subject: [PATCH 2/2] workspace + user settings --- ui/src/components/AppSwitchRoutes.tsx | 4 +- ui/src/components/Header/EntHeader.tsx | 3 +- .../Modals/AddUserModal/AddUserModal.lazy.tsx | 11 ++++ .../Modals/AddUserModal/AddUserModal.less | 1 + .../Modals/AddUserModal/AddUserModal.tsx | 28 ++++++++++ .../{ => Modals}/OasModal/OasModal.sass | 2 +- .../{ => Modals}/OasModal/OasModal.tsx | 6 +-- .../Pages/SettingsPage/SettingsPage.tsx | 8 +++ .../Pages/TrafficPage/TrafficPage.tsx | 2 +- .../components/UI/FilterableTableAction.tsx | 31 ++++++----- ui/src/components/UI/Table.tsx | 24 +++++---- ui/src/components/UI/style/Table.sass | 24 +-------- .../components/UserSettings/UserSettings.sass | 21 +++++++- .../components/UserSettings/UserSettings.tsx | 27 ++++++---- .../WorkspaceSettings/WorkspaceSettings.tsx | 52 +++++++++++++++++++ ui/src/helpers/api.js | 5 ++ 16 files changed, 186 insertions(+), 63 deletions(-) create mode 100644 ui/src/components/Modals/AddUserModal/AddUserModal.lazy.tsx create mode 100644 ui/src/components/Modals/AddUserModal/AddUserModal.less create mode 100644 ui/src/components/Modals/AddUserModal/AddUserModal.tsx rename ui/src/components/{ => Modals}/OasModal/OasModal.sass (66%) rename ui/src/components/{ => Modals}/OasModal/OasModal.tsx (95%) create mode 100644 ui/src/components/WorkspaceSettings/WorkspaceSettings.tsx diff --git a/ui/src/components/AppSwitchRoutes.tsx b/ui/src/components/AppSwitchRoutes.tsx index 29f623b1a..4a27da32b 100644 --- a/ui/src/components/AppSwitchRoutes.tsx +++ b/ui/src/components/AppSwitchRoutes.tsx @@ -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 }> + } /> {/*todo: set settings component*/} } /> - } /> {/*todo: set settings component*/} + }/> setIsFirstLogin(true)}/>}/> diff --git a/ui/src/components/Header/EntHeader.tsx b/ui/src/components/Header/EntHeader.tsx index 9d0e9dc1f..77c4ca358 100644 --- a/ui/src/components/Header/EntHeader.tsx +++ b/ui/src/components/Header/EntHeader.tsx @@ -13,6 +13,7 @@ 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(); @@ -43,7 +44,7 @@ export const EntHeader: React.FC = ({isFirstLogin, setIsFirstLog
- settings setIsSettingsModalOpen(true)}/> + settings navigate(RouterRoutes.SETTINGS)}/>
{/* */} diff --git a/ui/src/components/Modals/AddUserModal/AddUserModal.lazy.tsx b/ui/src/components/Modals/AddUserModal/AddUserModal.lazy.tsx new file mode 100644 index 000000000..b661c6602 --- /dev/null +++ b/ui/src/components/Modals/AddUserModal/AddUserModal.lazy.tsx @@ -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 }) => ( + + + +); + +export default AddUserModal; diff --git a/ui/src/components/Modals/AddUserModal/AddUserModal.less b/ui/src/components/Modals/AddUserModal/AddUserModal.less new file mode 100644 index 000000000..06dfc9e98 --- /dev/null +++ b/ui/src/components/Modals/AddUserModal/AddUserModal.less @@ -0,0 +1 @@ +.AddUserModal {} \ No newline at end of file diff --git a/ui/src/components/Modals/AddUserModal/AddUserModal.tsx b/ui/src/components/Modals/AddUserModal/AddUserModal.tsx new file mode 100644 index 000000000..7223d7560 --- /dev/null +++ b/ui/src/components/Modals/AddUserModal/AddUserModal.tsx @@ -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 = ({isOpen}) => { + + const [isOpenModal,setIsOpen] = useState(isOpen) + + useEffect(() => { + setIsOpen(isOpen) + },[isOpen]) + + const onClose = () => {} + + const onConfirm = () => {} + + return (<> + + + + ); +}; + +export default AddUserModal; diff --git a/ui/src/components/OasModal/OasModal.sass b/ui/src/components/Modals/OasModal/OasModal.sass similarity index 66% rename from ui/src/components/OasModal/OasModal.sass rename to ui/src/components/Modals/OasModal/OasModal.sass index 739064c05..068a03b53 100644 --- a/ui/src/components/OasModal/OasModal.sass +++ b/ui/src/components/Modals/OasModal/OasModal.sass @@ -1,4 +1,4 @@ -@import '../../variables.module.scss' +@import '../../../variables.module.scss' .NotSelectedMessage margin-left: 41% diff --git a/ui/src/components/OasModal/OasModal.tsx b/ui/src/components/Modals/OasModal/OasModal.tsx similarity index 95% rename from ui/src/components/OasModal/OasModal.tsx rename to ui/src/components/Modals/OasModal/OasModal.tsx index 2614d9185..61250d93e 100644 --- a/ui/src/components/OasModal/OasModal.tsx +++ b/ui/src/components/Modals/OasModal/OasModal.tsx @@ -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' diff --git a/ui/src/components/Pages/SettingsPage/SettingsPage.tsx b/ui/src/components/Pages/SettingsPage/SettingsPage.tsx index 5fd55e170..cd6fdceca 100644 --- a/ui/src/components/Pages/SettingsPage/SettingsPage.tsx +++ b/ui/src/components/Pages/SettingsPage/SettingsPage.tsx @@ -1,5 +1,7 @@ +import React from "react"; import { useState } from "react"; import Tabs from "../../UI/Tabs" +import { UserSettings } from "../../UserSettings/UserSettings"; const AdminSettings: React.FC = ({color}) => { var TABS = [ @@ -10,6 +12,12 @@ const AdminSettings: React.FC = ({color}) => { return (
+ {currentTab === TABS[0].tab && + + } + {currentTab === TABS[1].tab && + + }
) } diff --git a/ui/src/components/Pages/TrafficPage/TrafficPage.tsx b/ui/src/components/Pages/TrafficPage/TrafficPage.tsx index 9ccb729c1..b350bcae9 100644 --- a/ui/src/components/Pages/TrafficPage/TrafficPage.tsx +++ b/ui/src/components/Pages/TrafficPage/TrafficPage.tsx @@ -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"; diff --git a/ui/src/components/UI/FilterableTableAction.tsx b/ui/src/components/UI/FilterableTableAction.tsx index 734b4103a..4e04d5c1c 100644 --- a/ui/src/components/UI/FilterableTableAction.tsx +++ b/ui/src/components/UI/FilterableTableAction.tsx @@ -1,5 +1,5 @@ import { Button } from "@material-ui/core"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { Table } from "./Table"; import {useCommonStyles} from "../../helpers/commonStyle"; import {ColsType} from "../UI/Table" @@ -24,28 +24,31 @@ export const FilterableTableAction: React.FC = ({onRowDelete,onRowEdit, s const [tableRows,setRows] = useState(rows as any[]) const [inputSearch, setInputSearch] = useState("") - let allRows = rows; useEffect(() => { - allRows = rows; setRows(rows); },[rows]) - useEffect(()=> { - if(inputSearch !== ""){ - const searchFunc = searchConfig.filterRows(inputSearch) - const filtered = tableRows.filter(searchFunc) - setRows(filtered) - } - else{ - setRows(allRows); - } - },[inputSearch]) + // 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 (<>
@@ -54,7 +57,7 @@ export const FilterableTableAction: React.FC = ({onRowDelete,onRowEdit, s {buttonConfig.text}
-
+
); }; \ No newline at end of file diff --git a/ui/src/components/UI/Table.tsx b/ui/src/components/UI/Table.tsx index 1ea3d7d56..6f8d41a57 100644 --- a/ui/src/components/UI/Table.tsx +++ b/ui/src/components/UI/Table.tsx @@ -35,11 +35,16 @@ export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, const _onRowDelete = (row) => { onRowDelete(row); } + + // const filteredValues = useMemo(() => { + // return tableRows.filter((listValue) => listValue.find(row)); + // },[tableRows, searchValue]) + return {cols?.map((col)=> { - return + return })} @@ -48,18 +53,19 @@ export const Table: React.FC = ({rows, cols, onRowDelete, onRowEdit, { ((tableRows == null) || (tableRows.length === 0)) ? - No data Found -
{noDataMeesage}
+ {/* No data Found +
{noDataMeesage}
*/} : - tableRows?.map(rowData => { - return - {cols.map(col => { - return + {cols.map((col,index) => { + return })}
{col.header}{col.header}
- {rowData[col.field]} + tableRows?.map((rowData,index) => { + return
+ + {rowData[col.field]} + diff --git a/ui/src/components/UI/style/Table.sass b/ui/src/components/UI/style/Table.sass index bcd4223f7..3fe00b952 100644 --- a/ui/src/components/UI/style/Table.sass +++ b/ui/src/components/UI/style/Table.sass @@ -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) - - \ No newline at end of file + \ No newline at end of file diff --git a/ui/src/components/UserSettings/UserSettings.sass b/ui/src/components/UserSettings/UserSettings.sass index 0bc06f8e3..2e25e20a7 100644 --- a/ui/src/components/UserSettings/UserSettings.sass +++ b/ui/src/components/UserSettings/UserSettings.sass @@ -1,2 +1,21 @@ -@import '../../../variables.module' +@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) \ No newline at end of file diff --git a/ui/src/components/UserSettings/UserSettings.tsx b/ui/src/components/UserSettings/UserSettings.tsx index 30b28b4ff..c25032cbc 100644 --- a/ui/src/components/UserSettings/UserSettings.tsx +++ b/ui/src/components/UserSettings/UserSettings.tsx @@ -1,8 +1,9 @@ -import "./UserSettings" +import "./UserSettings.sass" import {useCommonStyles} from "../../helpers/commonStyle"; import {ColsType, FilterableTableAction} from "../UI/FilterableTableAction" import Api from "../../helpers/api" import { useEffect, useState } from "react"; +import AddUserModal from "../Modals/AddUserModal/AddUserModal"; interface Props { @@ -13,14 +14,18 @@ const api = Api.getInstance(); export const UserSettings : React.FC = ({}) => { const [usersRows, setUserRows] = useState([]); - const cols : ColsType[] = [{field : "userName",header:"User"},{field : "role",header:"Role"}, {field : "role",header:"Role"}] - + 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 = await api.getUsers() - setUserRows(usersRows) + const users = [{userName:"asd",role:"Admin",status:"Active"}]//await api.getUsers() + setUserRows(users) } catch (e) { console.error(e); } @@ -29,7 +34,7 @@ export const UserSettings : React.FC = ({}) => { const filterFuncFactory = (searchQuery: string) => { return (row) => { - return row.userName.toLowercase().includes(searchQuery.toLowerCase()) > -1 + return row.userName.toLowerCase().includes(searchQuery.toLowerCase()) } } @@ -42,12 +47,16 @@ export const UserSettings : React.FC = ({}) => { } const onRowEdit = (row) => { - + // open Edit user Modal } - const buttonConfig = {onClick: () => {}, text:"Add User"} + const buttonConfig = {onClick: () => {setIsOpen(true)}, text:"Add User"} return (<> - + + + + ); } diff --git a/ui/src/components/WorkspaceSettings/WorkspaceSettings.tsx b/ui/src/components/WorkspaceSettings/WorkspaceSettings.tsx new file mode 100644 index 000000000..6736a8436 --- /dev/null +++ b/ui/src/components/WorkspaceSettings/WorkspaceSettings.tsx @@ -0,0 +1,52 @@ +import "./UserSettings" +import {useCommonStyles} from "../../helpers/commonStyle"; +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 = ({}) => { + + const [workspaces, setWorkspaces] = useState([]); + const cols : ColsType[] = [{field : "userName",header:"User"},{field : "role",header:"Role"}, {field : "role",header:"Role"}] + + + useEffect(() => { + (async () => { + try { + const workspaces = await api.getUsers() + setWorkspaces(workspaces) + } catch (e) { + console.error(e); + } + })(); + },[]) + + const filterFuncFactory = (searchQuery: string) => { + return (row) => { + return row.userName.toLowercase().includes(searchQuery.toLowerCase()) > -1 + } + } + + const searchConfig = { searchPlaceholder: "Search Workspace",filterRows: filterFuncFactory} + + const onRowDelete = (row) => { + const filterFunc = filterFuncFactory(row.userName) + const newUserList = workspaces.filter(filterFunc) + setWorkspaces(newUserList) + } + + const onRowEdit = (row) => { + + } + + const buttonConfig = {onClick: () => {}, text:"Add User"} + return (<> + + + ); +} diff --git a/ui/src/helpers/api.js b/ui/src/helpers/api.js index 47813e4f2..19644d0af 100644 --- a/ui/src/helpers/api.js +++ b/ui/src/helpers/api.js @@ -53,6 +53,11 @@ export default class Api { 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;