Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/vmui/packages/vmui/src/api/accountId.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const getAccountIds = (server: string) =>
`${server.replace(/^(.+)(\/select.+)/, "$1")}/admin/tenants`;
`${server}/select/tenant_ids`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { FC, useRef } from "preact/compat";
import { useSearchParams } from "react-router-dom";
import { useTimeDispatch } from "../../../../state/time/TimeStateContext";
import { useFetchAccountIds } from "./hooks/useFetchAccountIds";
import TenantsSelect from "./TenantsSelect";
import TenantsFields from "./TenantsFields";
import Button from "../../../Main/Button/Button";
import classNames from "classnames";
import Tooltip from "../../../Main/Tooltip/Tooltip";
import useDeviceDetect from "../../../../hooks/useDeviceDetect";
import useBoolean from "../../../../hooks/useBoolean";
import Popper from "../../../Main/Popper/Popper";
import { ArrowDownIcon, StorageIcon } from "../../../Main/Icons";
import "./style.scss";
import "../../TimeRangeSettings/ExecutionControls/style.scss";

export type TenantType = {
accountId: string;
projectId: string;
}

const Tenants: FC = () => {
const { accountIds } = useFetchAccountIds();
const { isMobile } = useDeviceDetect();
const timeDispatch = useTimeDispatch();

const [searchParams, setSearchParams] = useSearchParams();
const accountId = searchParams.get("accountID") || "0";
const projectId = searchParams.get("projectID") || "0";
const tenantId = `${accountId}:${projectId}`;

const buttonRef = useRef<HTMLDivElement>(null);

const {
value: openPopup,
toggle: toggleOpenPopup,
setFalse: handleClosePopup,
} = useBoolean(false);

const onChange = ({ accountId, projectId }: Partial<TenantType>) => {
if (accountId) searchParams.set("accountID", accountId);
if (projectId) searchParams.set("projectID", projectId);
setSearchParams(searchParams);
timeDispatch({ type: "RUN_QUERY" });
handleClosePopup();
};

const childrenProps = {
tenantId,
accountIds,
accountId,
projectId,
onChange,
};

return (
<div className="vm-tenant-input">
<Tooltip title="Define Tenant ID if you need request to another storage">
<div ref={buttonRef}>
{isMobile ? (
<div
className="vm-mobile-option"
onClick={toggleOpenPopup}
>
<span className="vm-mobile-option__icon"><StorageIcon/></span>
<div className="vm-mobile-option-text">
<span className="vm-mobile-option-text__label">Tenant ID</span>
<span className="vm-mobile-option-text__value">{tenantId}</span>
</div>
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
</div>
) : (
<Button
className="vm-header-button"
variant="contained"
color="primary"
fullWidth
startIcon={<StorageIcon/>}
endIcon={(
<div
className={classNames({
"vm-execution-controls-buttons__arrow": true,
"vm-execution-controls-buttons__arrow_open": openPopup,
})}
>
<ArrowDownIcon/>
</div>
)}
onClick={toggleOpenPopup}
>
{tenantId}
</Button>
)}
</div>
</Tooltip>
<Popper
open={openPopup}
placement="bottom-right"
onClose={handleClosePopup}
buttonRef={buttonRef}
title={isMobile ? "Define Tenant ID" : undefined}
>
{accountIds.length ? <TenantsSelect {...childrenProps}/> : <TenantsFields {...childrenProps}/>}
</Popper>
</div>
);
};

export default Tenants;
Original file line number Diff line number Diff line change
@@ -1,147 +1,78 @@
import { FC, useRef, useEffect } from "preact/compat";
import { useTimeDispatch } from "../../../../state/time/TimeStateContext";
import { ArrowDownIcon, QuestionIcon, StorageIcon } from "../../../Main/Icons";
import { FC, useCallback, useEffect, useState } from "preact/compat";
import Button from "../../../Main/Button/Button";
import "./style.scss";
import "../../TimeRangeSettings/ExecutionControls/style.scss";
import classNames from "classnames";
import Popper from "../../../Main/Popper/Popper";
import { getAppModeEnable } from "../../../../utils/app-mode";
import Tooltip from "../../../Main/Tooltip/Tooltip";
import useDeviceDetect from "../../../../hooks/useDeviceDetect";
import TextField from "../../../Main/TextField/TextField";
import useBoolean from "../../../../hooks/useBoolean";
import useStateSearchParams from "../../../../hooks/useStateSearchParams";
import { useSearchParams } from "react-router-dom";
import { TenantType } from "./Tenants";

const TenantsFields: FC = () => {
const appModeEnable = getAppModeEnable();
const { isMobile } = useDeviceDetect();
const timeDispatch = useTimeDispatch();

const [searchParams, setSearchParams] = useSearchParams();
const [accountID, setAccountID] = useStateSearchParams("0", "accountID");
const [projectID, setProjectID] = useStateSearchParams("0", "projectID");
const formattedTenant = `${accountID}:${projectID}`;

const buttonRef = useRef<HTMLDivElement>(null);
interface Props extends TenantType {
accountId: string;
projectId: string;
onChange: (tenant: Partial<TenantType>) => void;
}

const {
value: openPopup,
toggle: toggleOpenPopup,
setFalse: handleClosePopup,
} = useBoolean(false);
const TenantsFields: FC<Props> = ({ accountId, projectId, onChange }) => {
const { isMobile } = useDeviceDetect();

const applyChanges = () => {
searchParams.set("accountID", accountID);
searchParams.set("projectID", projectID);
setSearchParams(searchParams);
handleClosePopup();
timeDispatch({ type: "RUN_QUERY" });
};
const [accountTmp, setAccountTmp] = useState(accountId);
const [projectTmp, setProjectTmp] = useState(projectId);

const handleReset = () => {
setAccountID(searchParams.get("accountID") || "0");
setProjectID(searchParams.get("projectID") || "0");
};
const applyChanges = useCallback(() => {
onChange({
accountId: accountTmp || accountId,
projectId: projectTmp || projectId
});
}, [accountTmp, accountId, projectTmp, projectId]);

useEffect(() => {
if (openPopup) return;
handleReset();
}, [openPopup]);
setAccountTmp(accountId);
setProjectTmp(projectId);
}, [accountId, projectId]);

return (
<div className="vm-tenant-input">
<Tooltip title="Define Tenant ID if you need request to another storage">
<div ref={buttonRef}>
{isMobile ? (
<div
className="vm-mobile-option"
onClick={toggleOpenPopup}
>
<span className="vm-mobile-option__icon"><StorageIcon/></span>
<div className="vm-mobile-option-text">
<span className="vm-mobile-option-text__label">Tenant ID</span>
<span className="vm-mobile-option-text__value">{formattedTenant}</span>
</div>
<span className="vm-mobile-option__arrow"><ArrowDownIcon/></span>
</div>
) : (
<Button
className={appModeEnable ? "" : "vm-header-button"}
variant="contained"
color="primary"
fullWidth
startIcon={<StorageIcon/>}
endIcon={(
<div
className={classNames({
"vm-execution-controls-buttons__arrow": true,
"vm-execution-controls-buttons__arrow_open": openPopup,
})}
>
<ArrowDownIcon/>
</div>
)}
onClick={toggleOpenPopup}
>
{formattedTenant}
</Button>
)}
</div>
</Tooltip>
<Popper
open={openPopup}
placement="bottom-right"
onClose={handleClosePopup}
buttonRef={buttonRef}
title={isMobile ? "Define Tenant ID" : undefined}
>
<div
className={classNames({
"vm-list vm-tenant-input-list": true,
"vm-list vm-tenant-input-list_mobile": isMobile,
"vm-tenant-input-list_inline": true,
})}
<div
className={classNames({
"vm-list vm-tenant-input-list": true,
"vm-list vm-tenant-input-list_mobile": isMobile,
})}
>
<div className="vm-tenant-input-list__fields">
<TextField
autofocus
label="accountID"
value={accountTmp}
onChange={setAccountTmp}
type="number"
/>
<TextField
autofocus
label="projectID"
value={projectTmp}
onChange={setProjectTmp}
type="number"
/>
</div>
<div className="vm-tenant-input-list__buttons">
<a
href="https://docs.victoriametrics.com/victorialogs/#multitenancy"
target="_blank"
rel="help noreferrer"
>
<Button
variant="text"
color="primary"
>
Read more
</Button>
</a>
<Button
variant="contained"
color="primary"
onClick={applyChanges}
>
<TextField
autofocus
label="accountID"
value={accountID}
onChange={setAccountID}
type="number"
/>
<TextField
autofocus
label="projectID"
value={projectID}
onChange={setProjectID}
type="number"
/>
<div className="vm-tenant-input-list__buttons">
<Tooltip title="Multitenancy in VictoriaLogs documentation">
<a
href="https://docs.victoriametrics.com/victorialogs/#multitenancy"
target="_blank"
rel="help noreferrer"
>
<Button
variant="text"
color="gray"
startIcon={<QuestionIcon/>}
/>
</a>
</Tooltip>
<Button
variant="contained"
color="primary"
onClick={applyChanges}
>
Apply
</Button>
</div>
</div>
</Popper>
Apply
</Button>
</div>
</div>
);
};
Expand Down
Loading