Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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