mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-12 02:29:09 +00:00
Merge remote-tracking branch 'origin' into feature-github-signin
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { forwardRef, InputHTMLAttributes, ReactNode } from "react";
|
||||
import { ChangeEvent, forwardRef, InputHTMLAttributes, ReactNode } from "react";
|
||||
import { cva, VariantProps } from "cva";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
@@ -10,6 +10,7 @@ type Props = {
|
||||
rightIcon?: ReactNode;
|
||||
isDisabled?: boolean;
|
||||
isReadOnly?: boolean;
|
||||
autoCapitalization?: boolean;
|
||||
};
|
||||
|
||||
const inputVariants = cva(
|
||||
@@ -80,10 +81,19 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
||||
variant = "filled",
|
||||
size = "md",
|
||||
isReadOnly,
|
||||
autoCapitalization,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
): JSX.Element => {
|
||||
const handleInput = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
console.log(123, props, autoCapitalization)
|
||||
if (autoCapitalization) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
event.target.value = event.target.value.toUpperCase();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={inputParentContainerVariants({ isRounded, isError, isFullWidth, variant })}>
|
||||
{leftIcon && <span className="absolute left-0 ml-3 text-sm">{leftIcon}</span>}
|
||||
@@ -93,6 +103,7 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(
|
||||
ref={ref}
|
||||
readOnly={isReadOnly}
|
||||
disabled={isDisabled}
|
||||
onInput={handleInput}
|
||||
className={twMerge(
|
||||
leftIcon ? "pl-10" : "pl-2.5",
|
||||
rightIcon ? "pr-10" : "pr-2.5",
|
||||
|
||||
@@ -47,9 +47,10 @@ const ActivityLogsRow = ({
|
||||
const { t } = useTranslation();
|
||||
|
||||
const renderUser = () => {
|
||||
|
||||
if (row?.user) return `${row.user}`;
|
||||
if (row?.serviceAccount) return `Service Account: ${row.serviceAccount.name}`;
|
||||
if (row?.serviceTokenData.name) return `Service Token: ${row.serviceTokenData.name}`;
|
||||
if (row?.serviceTokenData?.name) return `Service Token: ${row.serviceTokenData.name}`;
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ export {
|
||||
useGetOrganization,
|
||||
useGetOrgBillingDetails,
|
||||
useGetOrgInvoices,
|
||||
useGetOrgLicenses,
|
||||
useGetOrgPlanBillingInfo,
|
||||
useGetOrgPlansTable,
|
||||
useGetOrgPlanTable,
|
||||
@@ -14,5 +15,4 @@ export {
|
||||
useGetOrgTaxIds,
|
||||
useGetOrgTrialUrl,
|
||||
useRenameOrg,
|
||||
useUpdateOrgBillingDetails
|
||||
} from "./queries";
|
||||
useUpdateOrgBillingDetails} from "./queries";
|
||||
|
||||
@@ -5,14 +5,14 @@ import { apiRequest } from "@app/config/request";
|
||||
import {
|
||||
BillingDetails,
|
||||
Invoice,
|
||||
License,
|
||||
Organization,
|
||||
OrgPlanTable,
|
||||
PlanBillingInfo,
|
||||
PmtMethod,
|
||||
ProductsTable,
|
||||
RenameOrgDTO,
|
||||
TaxID
|
||||
} from "./types";
|
||||
TaxID} from "./types";
|
||||
|
||||
const organizationKeys = {
|
||||
getUserOrganization: ["organization"] as const,
|
||||
@@ -23,6 +23,7 @@ const organizationKeys = {
|
||||
getOrgPmtMethods: (orgId: string) => [{ orgId }, "organization-pmt-methods"] as const,
|
||||
getOrgTaxIds: (orgId: string) => [{ orgId }, "organization-tax-ids"] as const,
|
||||
getOrgInvoices: (orgId: string) => [{ orgId }, "organization-invoices"] as const,
|
||||
getOrgLicenses: (orgId: string) => [{ orgId }, "organization-licenses"] as const
|
||||
};
|
||||
|
||||
export const useGetOrganization = () => {
|
||||
@@ -311,4 +312,20 @@ export const useCreateCustomerPortalSession = () => {
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export const useGetOrgLicenses = (organizationId: string) => {
|
||||
return useQuery({
|
||||
queryKey: organizationKeys.getOrgLicenses(organizationId),
|
||||
queryFn: async () => {
|
||||
if (organizationId === "") return undefined;
|
||||
|
||||
const { data } = await apiRequest.get<License[]>(
|
||||
`/api/v1/organizations/${organizationId}/licenses`
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
enabled: true
|
||||
});
|
||||
}
|
||||
@@ -49,6 +49,17 @@ export type TaxID = {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type License = {
|
||||
_id: string;
|
||||
customerId: string;
|
||||
prefix: string;
|
||||
licenseKey: string;
|
||||
isActivated: boolean;
|
||||
expiresAt: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export type OrgPlanTableHead = {
|
||||
name: string;
|
||||
}
|
||||
|
||||
@@ -971,6 +971,7 @@ export const DashboardPage = () => {
|
||||
register={register}
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
autoCapitalization={currentWorkspace?.autoCapitalization}
|
||||
/>
|
||||
))}
|
||||
{!isReadOnly && !isRollbackMode && (
|
||||
|
||||
@@ -79,6 +79,7 @@ type Props = {
|
||||
setValue: UseFormSetValue<FormData>;
|
||||
isKeyError?: boolean;
|
||||
keyError?: string;
|
||||
autoCapitalization?: boolean;
|
||||
};
|
||||
|
||||
export const SecretInputRow = memo(
|
||||
@@ -98,7 +99,8 @@ export const SecretInputRow = memo(
|
||||
setValue,
|
||||
isKeyError,
|
||||
keyError,
|
||||
secUniqId
|
||||
secUniqId,
|
||||
autoCapitalization
|
||||
}: Props): JSX.Element => {
|
||||
const isKeySubDisabled = useRef<boolean>(false);
|
||||
// comment management in a row
|
||||
@@ -243,6 +245,7 @@ export const SecretInputRow = memo(
|
||||
isKeySubDisabled.current = false;
|
||||
field.onBlur();
|
||||
}}
|
||||
autoCapitalization={autoCapitalization}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ export const CurrentPlanSection = () => {
|
||||
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<h2 className="mb-8 flex-1 text-xl font-semibold text-white">Current Usage</h2>
|
||||
<h2 className="mb-8 flex-1 text-xl font-semibold text-white">Current usage</h2>
|
||||
<TableContainer className="mt-4">
|
||||
<Table>
|
||||
<THead>
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { LicensesSection } from "./LicensesSection";
|
||||
|
||||
export const BillingSelfHostedTab = () => {
|
||||
return (
|
||||
<div>
|
||||
<LicensesSection />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
import { faFileContract } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import {
|
||||
EmptyState,
|
||||
Table,
|
||||
TableContainer,
|
||||
TableSkeleton,
|
||||
TBody,
|
||||
Td,
|
||||
Th,
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import {
|
||||
useGetOrgLicenses
|
||||
} from "@app/hooks/api";
|
||||
|
||||
export const LicensesSection = () => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { data, isLoading } = useGetOrgLicenses(currentOrg?._id ?? "");
|
||||
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<h2 className="mb-8 flex-1 text-xl font-semibold text-white">Enterprise licenses</h2>
|
||||
<TableContainer className="mt-4">
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th>License Key</Th>
|
||||
<Th>Status</Th>
|
||||
<Th>Issued Date</Th>
|
||||
<Th>Expiry Date</Th>
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
{!isLoading && data && data?.length > 0 && data.map(({
|
||||
_id,
|
||||
licenseKey,
|
||||
isActivated,
|
||||
createdAt,
|
||||
expiresAt
|
||||
}) => {
|
||||
const formattedCreatedAt = new Date(createdAt).toISOString().split("T")[0];
|
||||
const formattedExpiresAt = new Date(expiresAt).toISOString().split("T")[0];
|
||||
return (
|
||||
<Tr key={`license-${_id}`} className="h-10">
|
||||
<Td>{licenseKey}</Td>
|
||||
<Td>{isActivated ? "Active" : "Inactive"}</Td>
|
||||
<Td>{formattedCreatedAt}</Td>
|
||||
<Td>{formattedExpiresAt}</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
{isLoading && <TableSkeleton columns={4} innerKey="licenses" />}
|
||||
{!isLoading && data && data?.length === 0 && (
|
||||
<Tr>
|
||||
<Td colSpan={4}>
|
||||
<EmptyState title="No enterprise licenses on file" icon={faFileContract} />
|
||||
</Td>
|
||||
</Tr>
|
||||
)}
|
||||
</TBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export * from "./BillingSelfHostedTab";
|
||||
+5
@@ -4,9 +4,11 @@ import { Tab } from "@headlessui/react"
|
||||
import { BillingCloudTab } from "../BillingCloudTab";
|
||||
import { BillingDetailsTab } from "../BillingDetailsTab";
|
||||
import { BillingReceiptsTab } from "../BillingReceiptsTab";
|
||||
import { BillingSelfHostedTab } from "../BillingSelfHostedTab";
|
||||
|
||||
const tabs = [
|
||||
{ name: "Infisical Cloud", key: "tab-infisical-cloud" },
|
||||
{ name: "Infisical Self-Hosted", key: "tab-infisical-self-hosted" },
|
||||
{ name: "Receipts", key: "tab-receipts" },
|
||||
{ name: "Billing details", key: "tab-billing-details" }
|
||||
];
|
||||
@@ -32,6 +34,9 @@ export const BillingTabGroup = () => {
|
||||
<Tab.Panel>
|
||||
<BillingCloudTab />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<BillingSelfHostedTab />
|
||||
</Tab.Panel>
|
||||
<Tab.Panel>
|
||||
<BillingReceiptsTab />
|
||||
</Tab.Panel>
|
||||
|
||||
Reference in New Issue
Block a user