mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 04:14:38 +00:00
Add eslint rule and fix as many issues as possible
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
const Error = ({ text }: { text: string }): JSX.Element => {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import React, { Fragment } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
faAngleDown,
|
||||
faEye,
|
||||
@@ -7,9 +7,9 @@ import {
|
||||
faShuffle,
|
||||
faTrash,
|
||||
faX
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Listbox, Transition } from '@headlessui/react';
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
|
||||
interface ListBoxProps {
|
||||
selected: string;
|
||||
@@ -18,19 +18,19 @@ interface ListBoxProps {
|
||||
|
||||
const eventOptions = [
|
||||
{
|
||||
name: 'addSecrets',
|
||||
name: "addSecrets",
|
||||
icon: faPlus
|
||||
},
|
||||
{
|
||||
name: 'readSecrets',
|
||||
name: "readSecrets",
|
||||
icon: faEye
|
||||
},
|
||||
{
|
||||
name: 'updateSecrets',
|
||||
name: "updateSecrets",
|
||||
icon: faShuffle
|
||||
},
|
||||
{
|
||||
name: 'deleteSecrets',
|
||||
name: "deleteSecrets",
|
||||
icon: faTrash
|
||||
}
|
||||
];
|
||||
@@ -48,13 +48,13 @@ const EventFilter = ({ selected, select }: ListBoxProps): JSX.Element => {
|
||||
<Listbox value={t(`activity.event.${selected}`)} onChange={select}>
|
||||
<div className="relative">
|
||||
<Listbox.Button className="flex h-10 w-52 cursor-pointer items-center justify-between rounded-md bg-mineshaft-800 pl-4 pr-2 text-sm text-bunker-200 duration-200 hover:bg-mineshaft-700">
|
||||
{selected !== '' ? (
|
||||
{selected !== "" ? (
|
||||
<p className="select-none text-bunker-100">{t(`activity.event.${selected}`)}</p>
|
||||
) : (
|
||||
<p className="select-none">{String(t('common.select-event'))}</p>
|
||||
<p className="select-none">{String(t("common.select-event"))}</p>
|
||||
)}
|
||||
{selected !== '' ? (
|
||||
<FontAwesomeIcon icon={faX} className="w-2 p-2 pl-2" onClick={() => select('')} />
|
||||
{selected !== "" ? (
|
||||
<FontAwesomeIcon icon={faX} className="w-2 p-2 pl-2" onClick={() => select("")} />
|
||||
) : (
|
||||
<FontAwesomeIcon icon={faAngleDown} className="pl-4 pr-2" />
|
||||
)}
|
||||
@@ -70,15 +70,15 @@ const EventFilter = ({ selected, select }: ListBoxProps): JSX.Element => {
|
||||
<Listbox.Option
|
||||
key={`${event.name}.${id + 1}`}
|
||||
className={`flex h-10 cursor-pointer items-center rounded-md px-4 text-sm text-bunker-200 hover:bg-mineshaft-700 ${
|
||||
selected === t(`activity.event.${event.name}`) && 'bg-mineshaft-700'
|
||||
selected === t(`activity.event.${event.name}`) && "bg-mineshaft-700"
|
||||
}`}
|
||||
value={event.name}
|
||||
>
|
||||
{({ selected: isSelected }) => (
|
||||
<span
|
||||
className={`block truncate ${isSelected ? 'font-semibold' : 'font-normal'}`}
|
||||
className={`block truncate ${isSelected ? "font-semibold" : "font-normal"}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={event.icon} className="pr-4" />{' '}
|
||||
<FontAwesomeIcon icon={event.icon} className="pr-4" />{" "}
|
||||
{t(`activity.event.${event.name}`)}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { memo, useState } from 'react';
|
||||
import { faCircle, faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { memo, useState } from "react";
|
||||
import { faCircle, faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import guidGenerator from '../utilities/randomId';
|
||||
import guidGenerator from "../utilities/randomId";
|
||||
|
||||
interface InputFieldProps {
|
||||
isStatic?: boolean;
|
||||
@@ -34,7 +34,7 @@ const InputField = ({
|
||||
placeholder,
|
||||
isStatic,
|
||||
text
|
||||
}: InputFieldProps & Pick<JSX.IntrinsicElements['input'], 'autoComplete' | 'id'>) => {
|
||||
}: InputFieldProps & Pick<JSX.IntrinsicElements["input"], "autoComplete" | "id">) => {
|
||||
const [passwordVisible, setPasswordVisible] = useState(false);
|
||||
|
||||
if (isStatic === true) {
|
||||
@@ -64,28 +64,28 @@ const InputField = ({
|
||||
</div>
|
||||
<div
|
||||
className={`group relative flex flex-col justify-center w-full max-w-2xl border ${
|
||||
error ? 'border-red' : 'border-mineshaft-500'
|
||||
error ? "border-red" : "border-mineshaft-500"
|
||||
} rounded-md`}
|
||||
>
|
||||
<input
|
||||
onChange={(e) => onChangeHandler(e.target.value)}
|
||||
type={passwordVisible === false ? type : 'text'}
|
||||
type={passwordVisible === false ? type : "text"}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
required={isRequired}
|
||||
className={`${
|
||||
blurred
|
||||
? 'text-bunker-800 group-hover:text-gray-400 focus:text-gray-400 active:text-gray-400'
|
||||
: ''
|
||||
? "text-bunker-800 group-hover:text-gray-400 focus:text-gray-400 active:text-gray-400"
|
||||
: ""
|
||||
} ${
|
||||
error ? 'focus:ring-red/50' : 'focus:ring-primary/50'
|
||||
error ? "focus:ring-red/50" : "focus:ring-primary/50"
|
||||
} relative peer bg-mineshaft-900 rounded-md text-gray-400 text-md p-2 w-full min-w-16 outline-none focus:ring-4 duration-200`}
|
||||
name={name}
|
||||
spellCheck="false"
|
||||
autoComplete={autoComplete}
|
||||
id={id}
|
||||
/>
|
||||
{label?.includes('Password') && (
|
||||
{label?.includes("Password") && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
@@ -104,7 +104,7 @@ const InputField = ({
|
||||
<div className="peer group-hover:hidden peer-hover:hidden peer-focus:hidden peer-active:invisible absolute h-10 w-fit max-w-xl rounded-md flex items-center text-gray-400/50 text-clip overflow-hidden">
|
||||
<p className="ml-2" />
|
||||
{value
|
||||
.split('')
|
||||
.split("")
|
||||
.slice(0, 54)
|
||||
.map(() => (
|
||||
<FontAwesomeIcon
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* eslint-disable no-nested-ternary */
|
||||
/* eslint-disable no-unexpected-multiline */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import crypto from 'crypto';
|
||||
import crypto from "crypto";
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import {
|
||||
faBookOpen,
|
||||
faFileLines,
|
||||
@@ -16,25 +16,25 @@ import {
|
||||
faPlug,
|
||||
faPlus,
|
||||
faUser
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import getOrganizations from '@app/pages/api/organization/getOrgs';
|
||||
import getOrganizationUserProjects from '@app/pages/api/organization/GetOrgUserProjects';
|
||||
import getOrganizationUsers from '@app/pages/api/organization/GetOrgUsers';
|
||||
import getUser from '@app/pages/api/user/getUser';
|
||||
import addUserToWorkspace from '@app/pages/api/workspace/addUserToWorkspace';
|
||||
import createWorkspace from '@app/pages/api/workspace/createWorkspace';
|
||||
import getWorkspaces from '@app/pages/api/workspace/getWorkspaces';
|
||||
import uploadKeys from '@app/pages/api/workspace/uploadKeys';
|
||||
import getOrganizations from "@app/pages/api/organization/getOrgs";
|
||||
import getOrganizationUserProjects from "@app/pages/api/organization/GetOrgUserProjects";
|
||||
import getOrganizationUsers from "@app/pages/api/organization/GetOrgUsers";
|
||||
import getUser from "@app/pages/api/user/getUser";
|
||||
import addUserToWorkspace from "@app/pages/api/workspace/addUserToWorkspace";
|
||||
import createWorkspace from "@app/pages/api/workspace/createWorkspace";
|
||||
import getWorkspaces from "@app/pages/api/workspace/getWorkspaces";
|
||||
import uploadKeys from "@app/pages/api/workspace/uploadKeys";
|
||||
|
||||
import NavBarDashboard from '../navigation/NavBarDashboard';
|
||||
import onboardingCheck from '../utilities/checks/OnboardingCheck';
|
||||
import { tempLocalStorage } from '../utilities/checks/tempLocalStorage';
|
||||
import { decryptAssymmetric, encryptAssymmetric } from '../utilities/cryptography/crypto';
|
||||
import Button from './buttons/Button';
|
||||
import AddWorkspaceDialog from './dialog/AddWorkspaceDialog';
|
||||
import Listbox from './Listbox';
|
||||
import NavBarDashboard from "../navigation/NavBarDashboard";
|
||||
import onboardingCheck from "../utilities/checks/OnboardingCheck";
|
||||
import { tempLocalStorage } from "../utilities/checks/tempLocalStorage";
|
||||
import { decryptAssymmetric, encryptAssymmetric } from "../utilities/cryptography/crypto";
|
||||
import Button from "./buttons/Button";
|
||||
import AddWorkspaceDialog from "./dialog/AddWorkspaceDialog";
|
||||
import Listbox from "./Listbox";
|
||||
|
||||
interface LayoutProps {
|
||||
children: React.ReactNode;
|
||||
@@ -43,8 +43,8 @@ interface LayoutProps {
|
||||
const Layout = ({ children }: LayoutProps) => {
|
||||
const router = useRouter();
|
||||
const [workspaceMapping, setWorkspaceMapping] = useState<Map<string, string>[]>([]);
|
||||
const [workspaceSelected, setWorkspaceSelected] = useState('∞');
|
||||
const [newWorkspaceName, setNewWorkspaceName] = useState('');
|
||||
const [workspaceSelected, setWorkspaceSelected] = useState("∞");
|
||||
const [newWorkspaceName, setNewWorkspaceName] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(false);
|
||||
@@ -77,12 +77,12 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
if (!currentWorkspaces.includes(workspaceName)) {
|
||||
const newWorkspace = await createWorkspace({
|
||||
workspaceName,
|
||||
organizationId: tempLocalStorage('orgData.id')
|
||||
organizationId: tempLocalStorage("orgData.id")
|
||||
});
|
||||
const newWorkspaceId = newWorkspace._id;
|
||||
|
||||
const randomBytes = crypto.randomBytes(16).toString('hex');
|
||||
const PRIVATE_KEY = String(localStorage.getItem('PRIVATE_KEY'));
|
||||
const randomBytes = crypto.randomBytes(16).toString("hex");
|
||||
const PRIVATE_KEY = String(localStorage.getItem("PRIVATE_KEY"));
|
||||
|
||||
const myUser = await getUser();
|
||||
|
||||
@@ -95,15 +95,15 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
await uploadKeys(newWorkspaceId, myUser._id, ciphertext, nonce);
|
||||
|
||||
if (addAllUsers) {
|
||||
console.log('adding other users');
|
||||
console.log("adding other users");
|
||||
const orgUsers = await getOrganizationUsers({
|
||||
orgId: tempLocalStorage('orgData.id')
|
||||
orgId: tempLocalStorage("orgData.id")
|
||||
});
|
||||
orgUsers.map(async (user: any) => {
|
||||
if (user.status === 'accepted' && user.email !== myUser.email) {
|
||||
if (user.status === "accepted" && user.email !== myUser.email) {
|
||||
const result = await addUserToWorkspace(user.user.email, newWorkspaceId);
|
||||
if (result?.invitee && result?.latestKey) {
|
||||
const TEMP_PRIVATE_KEY = tempLocalStorage('PRIVATE_KEY');
|
||||
const TEMP_PRIVATE_KEY = tempLocalStorage("PRIVATE_KEY");
|
||||
|
||||
// assymmetrically decrypt symmetric key with local private key
|
||||
const key = decryptAssymmetric({
|
||||
@@ -130,9 +130,9 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
}));
|
||||
setWorkspaceSelected(workspaceName);
|
||||
setIsOpen(false);
|
||||
setNewWorkspaceName('');
|
||||
setNewWorkspaceName("");
|
||||
} else {
|
||||
console.error('A project with this name already exists.');
|
||||
console.error("A project with this name already exists.");
|
||||
setError(true);
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -147,27 +147,27 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
() => [
|
||||
{
|
||||
href: `/dashboard/${workspaceMapping[workspaceSelected as any]}`,
|
||||
title: t('nav.menu.secrets'),
|
||||
title: t("nav.menu.secrets"),
|
||||
emoji: <FontAwesomeIcon icon={faKey} />
|
||||
},
|
||||
{
|
||||
href: `/users/${workspaceMapping[workspaceSelected as any]}`,
|
||||
title: t('nav.menu.members'),
|
||||
title: t("nav.menu.members"),
|
||||
emoji: <FontAwesomeIcon icon={faUser} />
|
||||
},
|
||||
{
|
||||
href: `/integrations/${workspaceMapping[workspaceSelected as any]}`,
|
||||
title: t('nav.menu.integrations'),
|
||||
title: t("nav.menu.integrations"),
|
||||
emoji: <FontAwesomeIcon icon={faPlug} />
|
||||
},
|
||||
{
|
||||
href: `/activity/${workspaceMapping[workspaceSelected as any]}`,
|
||||
title: 'Audit Logs',
|
||||
title: "Audit Logs",
|
||||
emoji: <FontAwesomeIcon icon={faFileLines} />
|
||||
},
|
||||
{
|
||||
href: `/settings/project/${workspaceMapping[workspaceSelected as any]}`,
|
||||
title: t('nav.menu.project-settings'),
|
||||
title: t("nav.menu.project-settings"),
|
||||
emoji: <FontAwesomeIcon icon={faGear} />
|
||||
}
|
||||
],
|
||||
@@ -178,35 +178,35 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
// Put a user in a workspace if they're not in one yet
|
||||
|
||||
const putUserInWorkSpace = async () => {
|
||||
if (tempLocalStorage('orgData.id') === '') {
|
||||
if (tempLocalStorage("orgData.id") === "") {
|
||||
const userOrgs = await getOrganizations();
|
||||
localStorage.setItem('orgData.id', userOrgs[0]._id);
|
||||
localStorage.setItem("orgData.id", userOrgs[0]._id);
|
||||
}
|
||||
|
||||
const orgUserProjects = await getOrganizationUserProjects({
|
||||
orgId: tempLocalStorage('orgData.id')
|
||||
orgId: tempLocalStorage("orgData.id")
|
||||
});
|
||||
const userWorkspaces = orgUserProjects;
|
||||
if (
|
||||
(userWorkspaces.length === 0 &&
|
||||
router.asPath !== '/noprojects' &&
|
||||
!router.asPath.includes('home') &&
|
||||
!router.asPath.includes('settings')) ||
|
||||
router.asPath === '/dashboard/undefined'
|
||||
router.asPath !== "/noprojects" &&
|
||||
!router.asPath.includes("home") &&
|
||||
!router.asPath.includes("settings")) ||
|
||||
router.asPath === "/dashboard/undefined"
|
||||
) {
|
||||
router.push('/noprojects');
|
||||
} else if (router.asPath !== '/noprojects') {
|
||||
router.push("/noprojects");
|
||||
} else if (router.asPath !== "/noprojects") {
|
||||
const intendedWorkspaceId = router.asPath
|
||||
.split('/')
|
||||
[router.asPath.split('/').length - 1].split('?')[0];
|
||||
.split("/")
|
||||
[router.asPath.split("/").length - 1].split("?")[0];
|
||||
|
||||
if (!['callback', 'create', 'authorize'].includes(intendedWorkspaceId)) {
|
||||
localStorage.setItem('projectData.id', intendedWorkspaceId);
|
||||
if (!["callback", "create", "authorize"].includes(intendedWorkspaceId)) {
|
||||
localStorage.setItem("projectData.id", intendedWorkspaceId);
|
||||
}
|
||||
|
||||
// If a user is not a member of a workspace they are trying to access, just push them to one of theirs
|
||||
if (
|
||||
!['callback', 'create', 'authorize'].includes(intendedWorkspaceId) &&
|
||||
!["callback", "create", "authorize"].includes(intendedWorkspaceId) &&
|
||||
!userWorkspaces
|
||||
.map((workspace: { _id: string }) => workspace._id)
|
||||
.includes(intendedWorkspaceId)
|
||||
@@ -221,7 +221,7 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
setWorkspaceSelected(
|
||||
Object.fromEntries(
|
||||
userWorkspaces.map((workspace: any) => [workspace._id, workspace.name])
|
||||
)[router.asPath.split('/')[router.asPath.split('/').length - 1].split('?')[0]]
|
||||
)[router.asPath.split("/")[router.asPath.split("/").length - 1].split("?")[0]]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -235,9 +235,9 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
if (
|
||||
workspaceMapping[workspaceSelected as any] &&
|
||||
`${workspaceMapping[workspaceSelected as any]}` !==
|
||||
router.asPath.split('/')[router.asPath.split('/').length - 1].split('?')[0]
|
||||
router.asPath.split("/")[router.asPath.split("/").length - 1].split("?")[0]
|
||||
) {
|
||||
localStorage.setItem('projectData.id', `${workspaceMapping[workspaceSelected as any]}`);
|
||||
localStorage.setItem("projectData.id", `${workspaceMapping[workspaceSelected as any]}`);
|
||||
router.push(`/dashboard/${workspaceMapping[workspaceSelected as any]}`);
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -256,7 +256,7 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
<div>
|
||||
<div className="mt-6 mb-6 flex h-20 w-full flex-col items-center justify-center bg-bunker-600 px-4">
|
||||
<div className="ml-1 mb-1 self-start text-xs font-semibold tracking-wide text-gray-400">
|
||||
{t('nav.menu.project')}
|
||||
{t("nav.menu.project")}
|
||||
</div>
|
||||
{Object.keys(workspaceMapping).length > 0 ? (
|
||||
<Listbox
|
||||
@@ -280,11 +280,11 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
{Object.keys(workspaceMapping).length > 0 &&
|
||||
menuItems.map(({ href, title, emoji }) => (
|
||||
<li className="mx-2 mt-0.5" key={title}>
|
||||
{router.asPath.split('/')[1] === href.split('/')[1] &&
|
||||
(['project', 'billing', 'org', 'personal'].includes(
|
||||
router.asPath.split('/')[2]
|
||||
{router.asPath.split("/")[1] === href.split("/")[1] &&
|
||||
(["project", "billing", "org", "personal"].includes(
|
||||
router.asPath.split("/")[2]
|
||||
)
|
||||
? router.asPath.split('/')[2] === href.split('/')[2]
|
||||
? router.asPath.split("/")[2] === href.split("/")[2]
|
||||
: true) ? (
|
||||
<div className="relative flex cursor-pointer rounded bg-primary-50/10 px-0.5 py-2.5 text-sm text-white">
|
||||
<div className="absolute inset-0 top-0 my-1 ml-1 mr-1 w-1 rounded-xl bg-primary" />
|
||||
@@ -293,7 +293,7 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
</p>
|
||||
{title}
|
||||
</div>
|
||||
) : router.asPath === '/noprojects' ? (
|
||||
) : router.asPath === "/noprojects" ? (
|
||||
<div className="flex rounded p-2.5 text-sm text-white">
|
||||
<p className="flex w-10 items-center justify-center text-lg">{emoji}</p>
|
||||
{title}
|
||||
@@ -313,7 +313,7 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
</ul>
|
||||
</div>
|
||||
<div className="mt-40 mb-4 w-full px-2">
|
||||
{router.asPath.split('/')[1] === 'home' ? (
|
||||
{router.asPath.split("/")[1] === "home" ? (
|
||||
<div className="relative flex cursor-pointer rounded bg-primary-50/10 px-0.5 py-2.5 text-sm text-white">
|
||||
<div className="absolute inset-0 top-0 my-1 ml-1 mr-1 w-1 rounded-xl bg-primary" />
|
||||
<p className="ml-4 mr-2 flex w-6 items-center justify-center text-lg">
|
||||
@@ -321,12 +321,12 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
</p>
|
||||
Infisical Guide
|
||||
<img
|
||||
src={`/images/progress-${totalOnboardingActionsDone === 0 ? '0' : ''}${
|
||||
totalOnboardingActionsDone === 1 ? '14' : ''
|
||||
}${totalOnboardingActionsDone === 2 ? '28' : ''}${
|
||||
totalOnboardingActionsDone === 3 ? '43' : ''
|
||||
}${totalOnboardingActionsDone === 4 ? '57' : ''}${
|
||||
totalOnboardingActionsDone === 5 ? '71' : ''
|
||||
src={`/images/progress-${totalOnboardingActionsDone === 0 ? "0" : ""}${
|
||||
totalOnboardingActionsDone === 1 ? "14" : ""
|
||||
}${totalOnboardingActionsDone === 2 ? "28" : ""}${
|
||||
totalOnboardingActionsDone === 3 ? "43" : ""
|
||||
}${totalOnboardingActionsDone === 4 ? "57" : ""}${
|
||||
totalOnboardingActionsDone === 5 ? "71" : ""
|
||||
}.svg`}
|
||||
height={58}
|
||||
width={58}
|
||||
@@ -342,12 +342,12 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
</p>
|
||||
Infisical Guide
|
||||
<img
|
||||
src={`/images/progress-${totalOnboardingActionsDone === 0 ? '0' : ''}${
|
||||
totalOnboardingActionsDone === 1 ? '14' : ''
|
||||
}${totalOnboardingActionsDone === 2 ? '28' : ''}${
|
||||
totalOnboardingActionsDone === 3 ? '43' : ''
|
||||
}${totalOnboardingActionsDone === 4 ? '57' : ''}${
|
||||
totalOnboardingActionsDone === 5 ? '71' : ''
|
||||
src={`/images/progress-${totalOnboardingActionsDone === 0 ? "0" : ""}${
|
||||
totalOnboardingActionsDone === 1 ? "14" : ""
|
||||
}${totalOnboardingActionsDone === 2 ? "28" : ""}${
|
||||
totalOnboardingActionsDone === 3 ? "43" : ""
|
||||
}${totalOnboardingActionsDone === 4 ? "57" : ""}${
|
||||
totalOnboardingActionsDone === 5 ? "71" : ""
|
||||
}.svg`}
|
||||
height={58}
|
||||
width={58}
|
||||
@@ -375,7 +375,7 @@ const Layout = ({ children }: LayoutProps) => {
|
||||
<div className="flex h-screen w-screen flex-col items-center justify-center bg-bunker-800 z-[200] md:hidden">
|
||||
<FontAwesomeIcon icon={faMobile} className="mb-8 text-7xl text-gray-300" />
|
||||
<p className="max-w-sm px-6 text-center text-lg text-gray-200">
|
||||
{` ${t('common.no-mobile')} `}
|
||||
{` ${t("common.no-mobile")} `}
|
||||
</p>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import { faAngleDown, faCheck, faPlus } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Listbox, Transition } from '@headlessui/react';
|
||||
import React, { Fragment } from "react";
|
||||
import { faAngleDown, faCheck, faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
|
||||
interface ListBoxProps {
|
||||
isSelected: string;
|
||||
@@ -35,13 +35,13 @@ const ListBox = ({
|
||||
<div className="relative">
|
||||
<Listbox.Button
|
||||
className={`text-gray-400 relative ${
|
||||
isFull ? 'w-full' : 'w-52'
|
||||
isFull ? "w-full" : "w-52"
|
||||
} cursor-default rounded-md bg-white/[0.07] hover:bg-white/[0.11] duration-200 py-2.5 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm`}
|
||||
>
|
||||
<div className="flex flex-row">
|
||||
{text}
|
||||
<span className="ml-1 cursor-pointer block truncate font-semibold text-gray-300">
|
||||
{' '}
|
||||
{" "}
|
||||
{isSelected}
|
||||
</span>
|
||||
</div>
|
||||
@@ -64,11 +64,11 @@ const ListBox = ({
|
||||
key={`${person}.${personIdx + 1}`}
|
||||
className={({ active, selected }) =>
|
||||
`my-0.5 relative cursor-default select-none py-2 pl-10 pr-4 rounded-md ${
|
||||
selected ? 'bg-white/10 text-gray-400 font-bold' : ''
|
||||
selected ? "bg-white/10 text-gray-400 font-bold" : ""
|
||||
} ${
|
||||
active && !selected
|
||||
? 'bg-white/5 text-mineshaft-200 cursor-pointer'
|
||||
: 'text-gray-400'
|
||||
? "bg-white/5 text-mineshaft-200 cursor-pointer"
|
||||
: "text-gray-400"
|
||||
} `
|
||||
}
|
||||
value={person}
|
||||
@@ -77,7 +77,7 @@ const ListBox = ({
|
||||
<>
|
||||
<span
|
||||
className={`block truncate text-primary${
|
||||
selected ? 'font-medium' : 'font-normal'
|
||||
selected ? "font-medium" : "font-normal"
|
||||
}`}
|
||||
>
|
||||
{person}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Switch } from '@headlessui/react';
|
||||
import { Switch } from "@headlessui/react";
|
||||
|
||||
interface ToggleProps {
|
||||
enabled: boolean;
|
||||
@@ -22,20 +22,20 @@ const Toggle = ({ enabled, setEnabled, addOverride, id }: ToggleProps): JSX.Elem
|
||||
checked={enabled}
|
||||
onChange={() => {
|
||||
if (enabled === false) {
|
||||
addOverride('', id);
|
||||
addOverride("", id);
|
||||
} else {
|
||||
addOverride(undefined, id);
|
||||
}
|
||||
setEnabled(!enabled);
|
||||
}}
|
||||
className={`${
|
||||
enabled ? 'bg-primary' : 'bg-bunker-400'
|
||||
enabled ? "bg-primary" : "bg-bunker-400"
|
||||
} relative inline-flex h-5 w-9 items-center rounded-full`}
|
||||
>
|
||||
<span className="sr-only">Enable notifications</span>
|
||||
<span
|
||||
className={`${
|
||||
enabled ? 'translate-x-[1.26rem]' : 'translate-x-0.5'
|
||||
enabled ? "translate-x-[1.26rem]" : "translate-x-0.5"
|
||||
} inline-block h-3.5 w-3.5 transform rounded-full bg-bunker-800 transition`}
|
||||
/>
|
||||
</Switch>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable react/button-has-type */
|
||||
import React, { ButtonHTMLAttributes } from 'react';
|
||||
import Image from 'next/image';
|
||||
import { IconProp } from '@fortawesome/fontawesome-svg-core';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import React, { ButtonHTMLAttributes } from "react";
|
||||
import Image from "next/image";
|
||||
import { IconProp } from "@fortawesome/fontawesome-svg-core";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
const classNames = require('classnames');
|
||||
const classNames = require("classnames");
|
||||
|
||||
type ButtonProps = {
|
||||
text?: string;
|
||||
@@ -47,49 +47,49 @@ const Button = ({
|
||||
}: ButtonProps): JSX.Element => {
|
||||
// Check if the button show always be 'active' - then true;
|
||||
// or if it should switch between 'active' and 'disabled' - then give the status
|
||||
const activityStatus = active || (text !== '' && textDisabled === undefined);
|
||||
const activityStatus = active || (text !== "" && textDisabled === undefined);
|
||||
|
||||
const styleButton = classNames(
|
||||
'group m-auto md:m-0 inline-block rounded-md duration-200',
|
||||
"group m-auto md:m-0 inline-block rounded-md duration-200",
|
||||
|
||||
// Setting background colors and hover modes
|
||||
color === 'mineshaft' && activityStatus && 'bg-mineshaft-800 border border-mineshaft-600 hover:bg-primary/[0.15] hover:border-primary/60',
|
||||
color === 'mineshaft' && !activityStatus && 'bg-mineshaft',
|
||||
(color === 'primary' || !color) && activityStatus && 'bg-primary border border-primary-400 opacity-80 hover:opacity-100',
|
||||
(color === 'primary' || !color) && !activityStatus && 'bg-primary',
|
||||
color === 'red' && 'bg-red-800 border border-red',
|
||||
color === "mineshaft" && activityStatus && "bg-mineshaft-800 border border-mineshaft-600 hover:bg-primary/[0.15] hover:border-primary/60",
|
||||
color === "mineshaft" && !activityStatus && "bg-mineshaft",
|
||||
(color === "primary" || !color) && activityStatus && "bg-primary border border-primary-400 opacity-80 hover:opacity-100",
|
||||
(color === "primary" || !color) && !activityStatus && "bg-primary",
|
||||
color === "red" && "bg-red-800 border border-red",
|
||||
|
||||
// Changing the opacity when active vs when not
|
||||
activityStatus ? 'opacity-100 cursor-pointer' : 'opacity-40',
|
||||
activityStatus ? "opacity-100 cursor-pointer" : "opacity-40",
|
||||
|
||||
// Setting the button sizes
|
||||
size === 'md' && 'h-10 w-full px-2 md:px-4',
|
||||
size === 'lg' && 'h-12 w-full px-2 md:px-8',
|
||||
!size && 'md:py-1 px-3 md:px-8',
|
||||
size === 'icon-md' && 'h-10 w-10 flex items-center justify-center',
|
||||
size === 'icon-sm' && 'h-9 w-9 flex items-center justify-center'
|
||||
size === "md" && "h-10 w-full px-2 md:px-4",
|
||||
size === "lg" && "h-12 w-full px-2 md:px-8",
|
||||
!size && "md:py-1 px-3 md:px-8",
|
||||
size === "icon-md" && "h-10 w-10 flex items-center justify-center",
|
||||
size === "icon-sm" && "h-9 w-9 flex items-center justify-center"
|
||||
);
|
||||
|
||||
const styleMainDiv = classNames(
|
||||
'relative font-medium flex items-center',
|
||||
"relative font-medium flex items-center",
|
||||
|
||||
// Setting the text color for the text and icon
|
||||
color === 'mineshaft' && 'text-bunker-200',
|
||||
color !== 'mineshaft' && color !== 'red' && color !== 'none' && 'text-black',
|
||||
color === 'red' && 'text-gray-200',
|
||||
color === 'none' && 'text-gray-200 text-xl',
|
||||
activityStatus && color !== 'red' && color !== 'mineshaft' && color !== 'none' ? 'group-hover:text-black' : '',
|
||||
color === "mineshaft" && "text-bunker-200",
|
||||
color !== "mineshaft" && color !== "red" && color !== "none" && "text-black",
|
||||
color === "red" && "text-gray-200",
|
||||
color === "none" && "text-gray-200 text-xl",
|
||||
activityStatus && color !== "red" && color !== "mineshaft" && color !== "none" ? "group-hover:text-black" : "",
|
||||
|
||||
size === 'icon' && 'flex items-center justify-center'
|
||||
size === "icon" && "flex items-center justify-center"
|
||||
);
|
||||
|
||||
const textStyle = classNames(
|
||||
'relative duration-200 text-center w-full',
|
||||
"relative duration-200 text-center w-full",
|
||||
|
||||
// Show the loading sign if the loading indicator is on
|
||||
loading ? 'opacity-0' : 'opacity-100',
|
||||
size === 'md' && 'text-sm',
|
||||
size === 'lg' && 'text-lg'
|
||||
loading ? "opacity-0" : "opacity-100",
|
||||
size === "md" && "text-sm",
|
||||
size === "lg" && "text-lg"
|
||||
);
|
||||
|
||||
const button = (
|
||||
@@ -102,7 +102,7 @@ const Button = ({
|
||||
<div className={styleMainDiv}>
|
||||
<div
|
||||
className={`${
|
||||
loading === true ? 'opacity-100' : 'opacity-0'
|
||||
loading === true ? "opacity-100" : "opacity-0"
|
||||
} absolute flex items-center px-3 bg-primary duration-200 w-full`}
|
||||
>
|
||||
<Image
|
||||
@@ -116,16 +116,16 @@ const Button = ({
|
||||
{icon && (
|
||||
<FontAwesomeIcon
|
||||
icon={icon}
|
||||
className={`flex my-auto font-extrabold ${size === 'icon-sm' ? 'text-sm' : 'text-sm'} ${
|
||||
(text || textDisabled) && 'mr-2'
|
||||
className={`flex my-auto font-extrabold ${size === "icon-sm" ? "text-sm" : "text-sm"} ${
|
||||
(text || textDisabled) && "mr-2"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
{iconDisabled && (
|
||||
<FontAwesomeIcon
|
||||
icon={iconDisabled as IconProp}
|
||||
className={`flex my-auto font-extrabold ${size === 'icon-sm' ? 'text-sm' : 'text-md'} ${
|
||||
(text || textDisabled) && 'mr-2'
|
||||
className={`flex my-auto font-extrabold ${size === "icon-sm" ? "text-sm" : "text-md"} ${
|
||||
(text || textDisabled) && "mr-2"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Fragment } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import Button from '../buttons/Button';
|
||||
import Button from "../buttons/Button";
|
||||
|
||||
interface IntegrationOption {
|
||||
clientId: string;
|
||||
@@ -72,18 +72,18 @@ const ActivateBotDialog = ({
|
||||
>
|
||||
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md border border-gray-700 bg-bunker-800 p-6 text-left align-middle shadow-xl transition-all">
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-400">
|
||||
{t('integrations.grant-access-to-secrets')}
|
||||
{t("integrations.grant-access-to-secrets")}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2 mb-2">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('integrations.why-infisical-needs-access')}
|
||||
{t("integrations.why-infisical-needs-access")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6 max-w-max">
|
||||
<Button
|
||||
onButtonPressed={submit}
|
||||
color="mineshaft"
|
||||
text={t('integrations.grant-access-button') as string}
|
||||
text={t("integrations.grant-access-button") as string}
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { Fragment, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { faCheck, faCopy } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import addAPIKey from '@app/pages/api/apiKey/addAPIKey';
|
||||
import addAPIKey from "@app/pages/api/apiKey/addAPIKey";
|
||||
|
||||
import Button from '../buttons/Button';
|
||||
import InputField from '../InputField';
|
||||
import ListBox from '../Listbox';
|
||||
import Button from "../buttons/Button";
|
||||
import InputField from "../InputField";
|
||||
import ListBox from "../Listbox";
|
||||
|
||||
const expiryMapping = {
|
||||
'1 day': 86400,
|
||||
'7 days': 604800,
|
||||
'1 month': 2592000,
|
||||
'6 months': 15552000,
|
||||
'12 months': 31104000
|
||||
"1 day": 86400,
|
||||
"7 days": 604800,
|
||||
"1 month": 2592000,
|
||||
"6 months": 15552000,
|
||||
"12 months": 31104000
|
||||
};
|
||||
|
||||
type Props = {
|
||||
@@ -28,9 +28,9 @@ type Props = {
|
||||
|
||||
// TODO: convert to TS
|
||||
const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) => {
|
||||
const [apiKey, setApiKey] = useState('');
|
||||
const [apiKeyName, setApiKeyName] = useState('');
|
||||
const [apiKeyExpiresIn, setApiKeyExpiresIn] = useState('1 day');
|
||||
const [apiKey, setApiKey] = useState("");
|
||||
const [apiKeyName, setApiKeyName] = useState("");
|
||||
const [apiKeyExpiresIn, setApiKeyExpiresIn] = useState("1 day");
|
||||
const [apiKeyCopied, setApiKeyCopied] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -46,7 +46,7 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
|
||||
function copyToClipboard() {
|
||||
// Get the text field
|
||||
const copyText = document.getElementById('apiKey') as HTMLInputElement;
|
||||
const copyText = document.getElementById("apiKey") as HTMLInputElement;
|
||||
|
||||
// Select the text field
|
||||
copyText.select();
|
||||
@@ -63,8 +63,8 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
|
||||
const closeAddApiKeyModal = () => {
|
||||
closeModal();
|
||||
setApiKeyName('');
|
||||
setApiKey('');
|
||||
setApiKeyName("");
|
||||
setApiKey("");
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -94,24 +94,24 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
leaveFrom="opacity-100 scale-100"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
{apiKey === '' ? (
|
||||
{apiKey === "" ? (
|
||||
<Dialog.Panel className="w-full max-w-md transform rounded-md border border-gray-700 bg-bunker-800 p-6 text-left align-middle shadow-xl transition-all">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="z-50 text-lg font-medium leading-6 text-gray-400"
|
||||
>
|
||||
{t('section.api-key.add-dialog.title')}
|
||||
{t("section.api-key.add-dialog.title")}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2 mb-4">
|
||||
<div className="flex flex-col">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.api-key.add-dialog.description')}
|
||||
{t("section.api-key.add-dialog.description")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-2 max-h-28">
|
||||
<InputField
|
||||
label={t('section.api-key.add-dialog.name')}
|
||||
label={t("section.api-key.add-dialog.name")}
|
||||
onChangeHandler={setApiKeyName}
|
||||
type="varName"
|
||||
value={apiKeyName}
|
||||
@@ -123,9 +123,9 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
<ListBox
|
||||
isSelected={apiKeyExpiresIn}
|
||||
onChange={setApiKeyExpiresIn}
|
||||
data={['1 day', '7 days', '1 month', '6 months', '12 months']}
|
||||
data={["1 day", "7 days", "1 month", "6 months", "12 months"]}
|
||||
isFull
|
||||
text={`${t('common.expired-in')}: `}
|
||||
text={`${t("common.expired-in")}: `}
|
||||
/>
|
||||
</div>
|
||||
<div className="max-w-max">
|
||||
@@ -133,10 +133,10 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
<Button
|
||||
onButtonPressed={() => generateAPIKey()}
|
||||
color="mineshaft"
|
||||
text={t('section.api-key.add-dialog.add') as string}
|
||||
textDisabled={t('section.api-key.add-dialog.add') as string}
|
||||
text={t("section.api-key.add-dialog.add") as string}
|
||||
textDisabled={t("section.api-key.add-dialog.add") as string}
|
||||
size="md"
|
||||
active={apiKeyName !== ''}
|
||||
active={apiKeyName !== ""}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -147,12 +147,12 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
as="h3"
|
||||
className="z-50 text-lg font-medium leading-6 text-gray-400"
|
||||
>
|
||||
{t('section.api-key.add-dialog.copy-service-token')}
|
||||
{t("section.api-key.add-dialog.copy-service-token")}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2 mb-4">
|
||||
<div className="flex flex-col">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.api-key.add-dialog.copy-service-token-description')}
|
||||
{t("section.api-key.add-dialog.copy-service-token-description")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -181,7 +181,7 @@ const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) =>
|
||||
)}
|
||||
</button>
|
||||
<span className="absolute -left-8 -top-20 hidden w-28 translate-y-full rounded-md bg-chicago-900 px-3 py-2 text-center text-sm text-gray-400 duration-300 group-hover:flex group-hover:animate-popup">
|
||||
{t('common.click-to-copy')}
|
||||
{t("common.click-to-copy")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Fragment, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import addIncidentContact from '@app/pages/api/organization/addIncidentContact';
|
||||
import addIncidentContact from "@app/pages/api/organization/addIncidentContact";
|
||||
|
||||
import Button from '../buttons/Button';
|
||||
import InputField from '../InputField';
|
||||
import Button from "../buttons/Button";
|
||||
import InputField from "../InputField";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@@ -20,7 +20,7 @@ const AddIncidentContactDialog = ({
|
||||
incidentContacts,
|
||||
setIncidentContacts
|
||||
}: Props) => {
|
||||
const [incidentContactEmail, setIncidentContactEmail] = useState('');
|
||||
const [incidentContactEmail, setIncidentContactEmail] = useState("");
|
||||
const { t } = useTranslation();
|
||||
|
||||
const submit = () => {
|
||||
@@ -29,7 +29,7 @@ const AddIncidentContactDialog = ({
|
||||
? incidentContacts.concat([incidentContactEmail])
|
||||
: [incidentContactEmail]
|
||||
);
|
||||
addIncidentContact(localStorage.getItem('orgData.id') as string, incidentContactEmail);
|
||||
addIncidentContact(localStorage.getItem("orgData.id") as string, incidentContactEmail);
|
||||
closeModal();
|
||||
};
|
||||
return (
|
||||
@@ -61,16 +61,16 @@ const AddIncidentContactDialog = ({
|
||||
>
|
||||
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md border border-gray-700 bg-bunker-800 p-6 text-left align-middle shadow-xl transition-all">
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-gray-400">
|
||||
{t('section.incident.add-dialog.title')}
|
||||
{t("section.incident.add-dialog.title")}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2 mb-2">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.incident.add-dialog.description')}
|
||||
{t("section.incident.add-dialog.description")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="max-h-28">
|
||||
<InputField
|
||||
label={t('common.email')}
|
||||
label={t("common.email")}
|
||||
onChangeHandler={setIncidentContactEmail}
|
||||
type="varName"
|
||||
value={incidentContactEmail}
|
||||
@@ -82,7 +82,7 @@ const AddIncidentContactDialog = ({
|
||||
<Button
|
||||
onButtonPressed={submit}
|
||||
color="mineshaft"
|
||||
text={t('section.incident.add-dialog.add-incident') as string}
|
||||
text={t("section.incident.add-dialog.add-incident") as string}
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Fragment } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { useRouter } from "next/router";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import Button from '../buttons/Button';
|
||||
import ListBox from '../Listbox';
|
||||
import Button from "../buttons/Button";
|
||||
import ListBox from "../Listbox";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
@@ -59,21 +59,21 @@ const AddProjectMemberDialog = ({
|
||||
as="h3"
|
||||
className="z-50 text-lg font-medium leading-6 text-gray-400"
|
||||
>
|
||||
{t('section.members.add-dialog.add-member-to-project')}
|
||||
{t("section.members.add-dialog.add-member-to-project")}
|
||||
</Dialog.Title>
|
||||
) : (
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="z-50 text-lg font-medium text-mineshaft-300 mb-4"
|
||||
>
|
||||
{t('section.members.add-dialog.already-all-invited')}
|
||||
{t("section.members.add-dialog.already-all-invited")}
|
||||
</Dialog.Title>
|
||||
)}
|
||||
<div className="mt-2 mb-4">
|
||||
{data?.length > 0 ? (
|
||||
<div className="flex flex-col">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.members.add-dialog.user-will-email')}
|
||||
{t("section.members.add-dialog.user-will-email")}
|
||||
</p>
|
||||
<div className="">
|
||||
<Trans
|
||||
@@ -101,7 +101,7 @@ const AddProjectMemberDialog = ({
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.members.add-dialog.add-user-org-first')}
|
||||
{t("section.members.add-dialog.add-user-org-first")}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
@@ -121,7 +121,7 @@ const AddProjectMemberDialog = ({
|
||||
<Button
|
||||
onButtonPressed={submitModal}
|
||||
color="mineshaft"
|
||||
text={t('section.members.add-member') as string}
|
||||
text={t("section.members.add-member") as string}
|
||||
size="md"
|
||||
/>
|
||||
</div>
|
||||
@@ -129,7 +129,7 @@ const AddProjectMemberDialog = ({
|
||||
<Button
|
||||
onButtonPressed={() => router.push(`/settings/org/${router.query.id}`)}
|
||||
color="mineshaft"
|
||||
text={t('section.members.add-dialog.add-user-to-org') as string}
|
||||
text={t("section.members.add-dialog.add-user-to-org") as string}
|
||||
size="md"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import crypto from 'crypto';
|
||||
import crypto from "crypto";
|
||||
|
||||
import { Fragment, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { faCheck, faCopy } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { faCheck, faCopy } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import addServiceToken from '@app/pages/api/serviceToken/addServiceToken';
|
||||
import getLatestFileKey from '@app/pages/api/workspace/getLatestFileKey';
|
||||
import addServiceToken from "@app/pages/api/serviceToken/addServiceToken";
|
||||
import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey";
|
||||
|
||||
import { decryptAssymmetric, encryptSymmetric } from '../../utilities/cryptography/crypto';
|
||||
import Button from '../buttons/Button';
|
||||
import InputField from '../InputField';
|
||||
import ListBox from '../Listbox';
|
||||
import { decryptAssymmetric, encryptSymmetric } from "../../utilities/cryptography/crypto";
|
||||
import Button from "../buttons/Button";
|
||||
import InputField from "../InputField";
|
||||
import ListBox from "../Listbox";
|
||||
|
||||
const expiryMapping = {
|
||||
'1 day': 86400,
|
||||
'7 days': 604800,
|
||||
'1 month': 2592000,
|
||||
'6 months': 15552000,
|
||||
'12 months': 31104000
|
||||
"1 day": 86400,
|
||||
"7 days": 604800,
|
||||
"1 month": 2592000,
|
||||
"6 months": 15552000,
|
||||
"12 months": 31104000
|
||||
};
|
||||
|
||||
type Props = {
|
||||
@@ -41,10 +41,10 @@ const AddServiceTokenDialog = ({
|
||||
environments,
|
||||
setServiceTokens
|
||||
}: Props) => {
|
||||
const [serviceToken, setServiceToken] = useState('');
|
||||
const [serviceTokenName, setServiceTokenName] = useState('');
|
||||
const [serviceToken, setServiceToken] = useState("");
|
||||
const [serviceTokenName, setServiceTokenName] = useState("");
|
||||
const [selectedServiceTokenEnv, setSelectedServiceTokenEnv] = useState(environments?.[0]);
|
||||
const [serviceTokenExpiresIn, setServiceTokenExpiresIn] = useState('1 day');
|
||||
const [serviceTokenExpiresIn, setServiceTokenExpiresIn] = useState("1 day");
|
||||
const [serviceTokenCopied, setServiceTokenCopied] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -55,10 +55,10 @@ const AddServiceTokenDialog = ({
|
||||
ciphertext: latestFileKey.latestKey.encryptedKey,
|
||||
nonce: latestFileKey.latestKey.nonce,
|
||||
publicKey: latestFileKey.latestKey.sender.publicKey,
|
||||
privateKey: localStorage.getItem('PRIVATE_KEY') as string
|
||||
privateKey: localStorage.getItem("PRIVATE_KEY") as string
|
||||
});
|
||||
|
||||
const randomBytes = crypto.randomBytes(16).toString('hex');
|
||||
const randomBytes = crypto.randomBytes(16).toString("hex");
|
||||
const { ciphertext, iv, tag } = encryptSymmetric({
|
||||
plaintext: key,
|
||||
key: randomBytes
|
||||
@@ -88,7 +88,7 @@ const AddServiceTokenDialog = ({
|
||||
|
||||
function copyToClipboard() {
|
||||
// Get the text field
|
||||
const copyText = document.getElementById('serviceToken') as HTMLInputElement;
|
||||
const copyText = document.getElementById("serviceToken") as HTMLInputElement;
|
||||
|
||||
// Select the text field
|
||||
copyText.select();
|
||||
@@ -105,8 +105,8 @@ const AddServiceTokenDialog = ({
|
||||
|
||||
const closeAddServiceTokenModal = () => {
|
||||
closeModal();
|
||||
setServiceTokenName('');
|
||||
setServiceToken('');
|
||||
setServiceTokenName("");
|
||||
setServiceToken("");
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -136,26 +136,26 @@ const AddServiceTokenDialog = ({
|
||||
leaveFrom="opacity-100 scale-100"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
{serviceToken === '' ? (
|
||||
{serviceToken === "" ? (
|
||||
<Dialog.Panel className="w-full max-w-md transform rounded-md border border-gray-700 bg-bunker-800 p-6 text-left align-middle shadow-xl transition-all">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="z-50 text-lg font-medium leading-6 text-gray-400"
|
||||
>
|
||||
{t('section.token.add-dialog.title', {
|
||||
{t("section.token.add-dialog.title", {
|
||||
target: workspaceName
|
||||
})}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2 mb-4">
|
||||
<div className="flex flex-col">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.token.add-dialog.description')}
|
||||
{t("section.token.add-dialog.description")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mb-2 max-h-28">
|
||||
<InputField
|
||||
label={t('section.token.add-dialog.name')}
|
||||
label={t("section.token.add-dialog.name")}
|
||||
onChangeHandler={setServiceTokenName}
|
||||
type="varName"
|
||||
value={serviceTokenName}
|
||||
@@ -174,22 +174,22 @@ const AddServiceTokenDialog = ({
|
||||
onChange={(envName) =>
|
||||
setSelectedServiceTokenEnv(
|
||||
environments.find(({ name }) => envName === name) || {
|
||||
name: 'unknown',
|
||||
slug: 'unknown'
|
||||
name: "unknown",
|
||||
slug: "unknown"
|
||||
}
|
||||
)
|
||||
}
|
||||
isFull
|
||||
text={`${t('common.environment')}: `}
|
||||
text={`${t("common.environment")}: `}
|
||||
/>
|
||||
</div>
|
||||
<div className="max-h-28">
|
||||
<ListBox
|
||||
isSelected={serviceTokenExpiresIn}
|
||||
onChange={setServiceTokenExpiresIn}
|
||||
data={['1 day', '7 days', '1 month', '6 months', '12 months']}
|
||||
data={["1 day", "7 days", "1 month", "6 months", "12 months"]}
|
||||
isFull
|
||||
text={`${t('common.expired-in')}: `}
|
||||
text={`${t("common.expired-in")}: `}
|
||||
/>
|
||||
</div>
|
||||
<div className="max-w-max">
|
||||
@@ -197,10 +197,10 @@ const AddServiceTokenDialog = ({
|
||||
<Button
|
||||
onButtonPressed={() => generateServiceToken()}
|
||||
color="mineshaft"
|
||||
text={t('section.token.add-dialog.add') as string}
|
||||
textDisabled={t('section.token.add-dialog.add') as string}
|
||||
text={t("section.token.add-dialog.add") as string}
|
||||
textDisabled={t("section.token.add-dialog.add") as string}
|
||||
size="md"
|
||||
active={serviceTokenName !== ''}
|
||||
active={serviceTokenName !== ""}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -211,12 +211,12 @@ const AddServiceTokenDialog = ({
|
||||
as="h3"
|
||||
className="z-50 text-lg font-medium leading-6 text-gray-400"
|
||||
>
|
||||
{t('section.token.add-dialog.copy-service-token')}
|
||||
{t("section.token.add-dialog.copy-service-token")}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2 mb-4">
|
||||
<div className="flex flex-col">
|
||||
<p className="text-sm text-gray-500">
|
||||
{t('section.token.add-dialog.copy-service-token-description')}
|
||||
{t("section.token.add-dialog.copy-service-token-description")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -244,7 +244,7 @@ const AddServiceTokenDialog = ({
|
||||
)}
|
||||
</button>
|
||||
<span className="absolute -left-8 -top-20 hidden w-28 translate-y-full rounded-md bg-chicago-900 px-3 py-2 text-center text-sm text-gray-400 duration-300 group-hover:flex group-hover:animate-popup">
|
||||
{t('common.click-to-copy')}
|
||||
{t("common.click-to-copy")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FormEventHandler, Fragment, useEffect, useState } from 'react';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { FormEventHandler, Fragment, useEffect, useState } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import Button from '../buttons/Button';
|
||||
import InputField from '../InputField';
|
||||
import Button from "../buttons/Button";
|
||||
import InputField from "../InputField";
|
||||
|
||||
type FormFields = { name: string; slug: string };
|
||||
|
||||
@@ -31,14 +31,14 @@ export const AddUpdateEnvironmentDialog = ({
|
||||
isEditMode,
|
||||
}: Props) => {
|
||||
const [formInput, setFormInput] = useState<FormFields>({
|
||||
name: '',
|
||||
slug: '',
|
||||
name: "",
|
||||
slug: "",
|
||||
});
|
||||
|
||||
// This use effect can be removed when the unmount is happening from outside the component
|
||||
// When unmount happens outside state gets unmounted also
|
||||
useEffect(() => {
|
||||
setFormInput(initialValues || { name: '', slug: '' });
|
||||
setFormInput(initialValues || { name: "", slug: "" });
|
||||
}, [isOpen]);
|
||||
|
||||
// REFACTOR: Move to react-hook-form with yup for better form management
|
||||
@@ -92,14 +92,14 @@ export const AddUpdateEnvironmentDialog = ({
|
||||
className='text-lg font-medium leading-6 text-gray-400'
|
||||
>
|
||||
{isEditMode
|
||||
? 'Update environment'
|
||||
: 'Create a new environment'}
|
||||
? "Update environment"
|
||||
: "Create a new environment"}
|
||||
</Dialog.Title>
|
||||
<form onSubmit={onFormSubmit}>
|
||||
<div className='max-h-28 mt-4'>
|
||||
<InputField
|
||||
label='Environment Name'
|
||||
onChangeHandler={(val) => onInputChange('name', val)}
|
||||
onChangeHandler={(val) => onInputChange("name", val)}
|
||||
type='varName'
|
||||
value={formInput.name}
|
||||
placeholder=''
|
||||
@@ -111,7 +111,7 @@ export const AddUpdateEnvironmentDialog = ({
|
||||
<div className='max-h-28 mt-4'>
|
||||
<InputField
|
||||
label='Environment Slug'
|
||||
onChangeHandler={(val) => onInputChange('slug', val)}
|
||||
onChangeHandler={(val) => onInputChange("slug", val)}
|
||||
type='varName'
|
||||
value={formInput.slug}
|
||||
placeholder=''
|
||||
@@ -128,8 +128,8 @@ export const AddUpdateEnvironmentDialog = ({
|
||||
onButtonPressed={() => null}
|
||||
type='submit'
|
||||
color='mineshaft'
|
||||
text={isEditMode ? 'Update' : 'Create'}
|
||||
active={formInput.name !== '' && formInput.slug !== ''}
|
||||
text={isEditMode ? "Update" : "Create"}
|
||||
active={formInput.name !== "" && formInput.slug !== ""}
|
||||
size='md'
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Fragment } from 'react';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import Button from '../buttons/Button';
|
||||
import InputField from '../InputField';
|
||||
import Button from "../buttons/Button";
|
||||
import InputField from "../InputField";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Fragment, useEffect, useState } from 'react';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment, useEffect, useState } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
import InputField from '../InputField';
|
||||
import InputField from "../InputField";
|
||||
|
||||
// REFACTOR: Move all these modals into one reusable one
|
||||
type Props = {
|
||||
|
||||
@@ -47,11 +47,11 @@ export const DeleteEnvVar = ({ isOpen, onClose, onSubmit }: Props) => {
|
||||
>
|
||||
<Dialog.Panel className="w-full max-w-md transform overflow-hidden rounded-md bg-bunker border border-mineshaft-600 p-6 text-left align-middle shadow-xl transition-all">
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-bunker-200">
|
||||
{t('dashboard:sidebar.delete-key-dialog.title')}
|
||||
{t("dashboard:sidebar.delete-key-dialog.title")}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2">
|
||||
<p className="text-sm text-bunker-300">
|
||||
{t('dashboard:sidebar.delete-key-dialog.confirm-delete-message')}
|
||||
{t("dashboard:sidebar.delete-key-dialog.confirm-delete-message")}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-6 flex justify-start">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Fragment } from 'react';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment } from "react";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
// #TODO: USE THIS. Currently it's not. Kinda complicated to set up because of state.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Fragment } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import { Fragment } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
// REFACTOR: Move all these modals into one reusable one
|
||||
type Props = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { faXmark } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faXmark } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
interface PopupProps {
|
||||
buttonText: string;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { faX } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faX } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import { useNotificationContext } from '@app/components/context/Notifications/NotificationProvider';
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
|
||||
import deleteAPIKey from '../../../pages/api/apiKey/deleteAPIKey';
|
||||
import guidGenerator from '../../utilities/randomId';
|
||||
import Button from '../buttons/Button';
|
||||
import deleteAPIKey from "../../../pages/api/apiKey/deleteAPIKey";
|
||||
import guidGenerator from "../../utilities/randomId";
|
||||
import Button from "../buttons/Button";
|
||||
|
||||
interface TokenProps {
|
||||
_id: string;
|
||||
@@ -58,7 +58,7 @@ const ApiKeyTable = ({ data, setApiKeys }: ServiceTokensProps) => {
|
||||
setApiKeys(data.filter((token) => token._id !== row._id));
|
||||
createNotification({
|
||||
text: `'${row.name}' API key has been revoked.`,
|
||||
type: 'error'
|
||||
type: "error"
|
||||
});
|
||||
}}
|
||||
color="red"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { faPencil, faPlus, faX } from '@fortawesome/free-solid-svg-icons';
|
||||
import { plans } from 'public/data/frequentConstants';
|
||||
import { useEffect, useState } from "react";
|
||||
import { faPencil, faPlus, faX } from "@fortawesome/free-solid-svg-icons";
|
||||
import { plans } from "public/data/frequentConstants";
|
||||
|
||||
import { usePopUp } from '../../../hooks/usePopUp';
|
||||
import getOrganizationSubscriptions from '../../../pages/api/organization/GetOrgSubscription';
|
||||
import Button from '../buttons/Button';
|
||||
import { AddUpdateEnvironmentDialog } from '../dialog/AddUpdateEnvironmentDialog';
|
||||
import DeleteActionModal from '../dialog/DeleteActionModal';
|
||||
import UpgradePlanModal from '../dialog/UpgradePlan';
|
||||
import { usePopUp } from "../../../hooks/usePopUp";
|
||||
import getOrganizationSubscriptions from "../../../pages/api/organization/GetOrgSubscription";
|
||||
import Button from "../buttons/Button";
|
||||
import { AddUpdateEnvironmentDialog } from "../dialog/AddUpdateEnvironmentDialog";
|
||||
import DeleteActionModal from "../dialog/DeleteActionModal";
|
||||
import UpgradePlanModal from "../dialog/UpgradePlan";
|
||||
|
||||
type Env = { name: string; slug: string };
|
||||
|
||||
@@ -20,17 +20,17 @@ type Props = {
|
||||
|
||||
const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }: Props) => {
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([
|
||||
'createUpdateEnv',
|
||||
'deleteEnv',
|
||||
'upgradePlan'
|
||||
"createUpdateEnv",
|
||||
"deleteEnv",
|
||||
"upgradePlan"
|
||||
] as const);
|
||||
const [plan, setPlan] = useState('');
|
||||
const [plan, setPlan] = useState("");
|
||||
const host = window.location.origin;
|
||||
|
||||
useEffect(() => {
|
||||
// on initial load - run auth check
|
||||
(async () => {
|
||||
const orgId = localStorage.getItem('orgData.id') as string;
|
||||
const orgId = localStorage.getItem("orgData.id") as string;
|
||||
const subscriptions = await getOrganizationSubscriptions({
|
||||
orgId
|
||||
});
|
||||
@@ -44,7 +44,7 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
const onEnvCreateCB = async (env: Env) => {
|
||||
try {
|
||||
await onCreateEnv(env);
|
||||
handlePopUpClose('createUpdateEnv');
|
||||
handlePopUpClose("createUpdateEnv");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@@ -52,8 +52,8 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
|
||||
const onEnvUpdateCB = async (env: Env) => {
|
||||
try {
|
||||
await onUpdateEnv((popUp.createUpdateEnv?.data as Pick<Env, 'slug'>)?.slug, env);
|
||||
handlePopUpClose('createUpdateEnv');
|
||||
await onUpdateEnv((popUp.createUpdateEnv?.data as Pick<Env, "slug">)?.slug, env);
|
||||
handlePopUpClose("createUpdateEnv");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@@ -61,8 +61,8 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
|
||||
const onEnvDeleteCB = async () => {
|
||||
try {
|
||||
await onDeleteEnv((popUp.deleteEnv?.data as Pick<Env, 'slug'>)?.slug);
|
||||
handlePopUpClose('deleteEnv');
|
||||
await onDeleteEnv((popUp.deleteEnv?.data as Pick<Env, "slug">)?.slug);
|
||||
handlePopUpClose("deleteEnv");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
@@ -85,10 +85,10 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
<Button
|
||||
text="Add New Environment"
|
||||
onButtonPressed={() => {
|
||||
if (plan !== plans.starter || host !== 'https://app.infisical.com' || localStorage.getItem('projectData.id') === '63ea8121b6e2b0543ba79616') {
|
||||
handlePopUpOpen('createUpdateEnv');
|
||||
if (plan !== plans.starter || host !== "https://app.infisical.com" || localStorage.getItem("projectData.id") === "63ea8121b6e2b0543ba79616") {
|
||||
handlePopUpOpen("createUpdateEnv");
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan');
|
||||
handlePopUpOpen("upgradePlan");
|
||||
}
|
||||
}}
|
||||
color="mineshaft"
|
||||
@@ -117,10 +117,10 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
<div className="mr-2 flex items-center duration-200 hover:opacity-100">
|
||||
<Button
|
||||
onButtonPressed={() => {
|
||||
if (plan !== plans.starter || host !== 'https://app.infisical.com') {
|
||||
handlePopUpOpen('createUpdateEnv', { name, slug });
|
||||
if (plan !== plans.starter || host !== "https://app.infisical.com") {
|
||||
handlePopUpOpen("createUpdateEnv", { name, slug });
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan');
|
||||
handlePopUpOpen("upgradePlan");
|
||||
}
|
||||
}}
|
||||
color="mineshaft"
|
||||
@@ -131,10 +131,10 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
<div className="mr-6 flex items-center opacity-50 duration-200 hover:opacity-100">
|
||||
<Button
|
||||
onButtonPressed={() => {
|
||||
if (plan !== plans.starter || host !== 'https://app.infisical.com') {
|
||||
handlePopUpOpen('deleteEnv', { name, slug });
|
||||
if (plan !== plans.starter || host !== "https://app.infisical.com") {
|
||||
handlePopUpOpen("deleteEnv", { name, slug });
|
||||
} else {
|
||||
handlePopUpOpen('upgradePlan');
|
||||
handlePopUpOpen("upgradePlan");
|
||||
}
|
||||
}}
|
||||
color="red"
|
||||
@@ -157,23 +157,23 @@ const EnvironmentTable = ({ data = [], onCreateEnv, onDeleteEnv, onUpdateEnv }:
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.deleteEnv.isOpen}
|
||||
title={`Are you sure want to delete ${
|
||||
(popUp?.deleteEnv?.data as { name: string })?.name || ' '
|
||||
(popUp?.deleteEnv?.data as { name: string })?.name || " "
|
||||
}?`}
|
||||
deleteKey={(popUp?.deleteEnv?.data as { slug: string })?.slug || ''}
|
||||
onClose={() => handlePopUpClose('deleteEnv')}
|
||||
deleteKey={(popUp?.deleteEnv?.data as { slug: string })?.slug || ""}
|
||||
onClose={() => handlePopUpClose("deleteEnv")}
|
||||
onSubmit={onEnvDeleteCB}
|
||||
/>
|
||||
<AddUpdateEnvironmentDialog
|
||||
isOpen={popUp.createUpdateEnv.isOpen}
|
||||
isEditMode={Boolean(popUp.createUpdateEnv?.data)}
|
||||
initialValues={popUp?.createUpdateEnv?.data as any}
|
||||
onClose={() => handlePopUpClose('createUpdateEnv')}
|
||||
onClose={() => handlePopUpClose("createUpdateEnv")}
|
||||
onCreateSubmit={onEnvCreateCB}
|
||||
onEditSubmit={onEnvUpdateCB}
|
||||
/>
|
||||
<UpgradePlanModal
|
||||
isOpen={popUp.upgradePlan.isOpen}
|
||||
onClose={() => handlePopUpClose('upgradePlan')}
|
||||
onClose={() => handlePopUpClose("upgradePlan")}
|
||||
text="You can add custom environments if you switch to Infisical's Team plan."
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { faEye, faEyeSlash, faPenToSquare, faPlus, faX } from '@fortawesome/free-solid-svg-icons';
|
||||
import { plans } from 'public/data/frequentConstants';
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { faEye, faEyeSlash, faPenToSquare, faPlus, faX } from "@fortawesome/free-solid-svg-icons";
|
||||
import { plans } from "public/data/frequentConstants";
|
||||
|
||||
import { useNotificationContext } from '@app/components/context/Notifications/NotificationProvider';
|
||||
import { Select, SelectItem } from '@app/components/v2';
|
||||
import updateUserProjectPermission from '@app/ee/api/memberships/UpdateUserProjectPermission';
|
||||
import getOrganizationSubscriptions from '@app/pages/api/organization/GetOrgSubscription';
|
||||
import changeUserRoleInWorkspace from '@app/pages/api/workspace/changeUserRoleInWorkspace';
|
||||
import deleteUserFromWorkspace from '@app/pages/api/workspace/deleteUserFromWorkspace';
|
||||
import getLatestFileKey from '@app/pages/api/workspace/getLatestFileKey';
|
||||
import getProjectInfo from '@app/pages/api/workspace/getProjectInfo';
|
||||
import uploadKeys from '@app/pages/api/workspace/uploadKeys';
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import { Select, SelectItem } from "@app/components/v2";
|
||||
import updateUserProjectPermission from "@app/ee/api/memberships/UpdateUserProjectPermission";
|
||||
import getOrganizationSubscriptions from "@app/pages/api/organization/GetOrgSubscription";
|
||||
import changeUserRoleInWorkspace from "@app/pages/api/workspace/changeUserRoleInWorkspace";
|
||||
import deleteUserFromWorkspace from "@app/pages/api/workspace/deleteUserFromWorkspace";
|
||||
import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey";
|
||||
import getProjectInfo from "@app/pages/api/workspace/getProjectInfo";
|
||||
import uploadKeys from "@app/pages/api/workspace/uploadKeys";
|
||||
|
||||
import { decryptAssymmetric, encryptAssymmetric } from '../../utilities/cryptography/crypto';
|
||||
import guidGenerator from '../../utilities/randomId';
|
||||
import Button from '../buttons/Button';
|
||||
import UpgradePlanModal from '../dialog/UpgradePlan';
|
||||
import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto";
|
||||
import guidGenerator from "../../utilities/randomId";
|
||||
import Button from "../buttons/Button";
|
||||
import UpgradePlanModal from "../dialog/UpgradePlan";
|
||||
|
||||
// const roles = ['admin', 'user'];
|
||||
// TODO: Set type for this
|
||||
@@ -45,8 +45,8 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
);
|
||||
const host = window.location.origin;
|
||||
const router = useRouter();
|
||||
const [myRole, setMyRole] = useState('member');
|
||||
const [currentPlan, setCurrentPlan] = useState('');
|
||||
const [myRole, setMyRole] = useState("member");
|
||||
const [currentPlan, setCurrentPlan] = useState("");
|
||||
const [workspaceEnvs, setWorkspaceEnvs] = useState<EnvironmentProps[]>([]);
|
||||
const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);
|
||||
const { createNotification } = useNotificationContext();
|
||||
@@ -87,8 +87,8 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
...userData.slice(index + 1, userData?.length)
|
||||
]);
|
||||
createNotification({
|
||||
text: `Successfully changed user role.`,
|
||||
type: 'success'
|
||||
text: "Successfully changed user role.",
|
||||
type: "success"
|
||||
});
|
||||
};
|
||||
|
||||
@@ -99,28 +99,28 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
slug: string
|
||||
) => {
|
||||
let denials: { ability: string; environmentSlug: string }[];
|
||||
if (val === 'Read Only') {
|
||||
if (val === "Read Only") {
|
||||
denials = [
|
||||
{
|
||||
ability: 'write',
|
||||
ability: "write",
|
||||
environmentSlug: slug
|
||||
}
|
||||
];
|
||||
} else if (val === 'No Access') {
|
||||
} else if (val === "No Access") {
|
||||
denials = [
|
||||
{
|
||||
ability: 'write',
|
||||
ability: "write",
|
||||
environmentSlug: slug
|
||||
},
|
||||
{
|
||||
ability: 'read',
|
||||
ability: "read",
|
||||
environmentSlug: slug
|
||||
}
|
||||
];
|
||||
} else if (val === 'Add Only') {
|
||||
} else if (val === "Add Only") {
|
||||
denials = [
|
||||
{
|
||||
ability: 'read',
|
||||
ability: "read",
|
||||
environmentSlug: slug
|
||||
}
|
||||
];
|
||||
@@ -128,7 +128,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
denials = [];
|
||||
}
|
||||
|
||||
if (currentPlan !== plans.professional && host === 'https://app.infisical.com' && workspaceId !== '63ea8121b6e2b0543ba79616') {
|
||||
if (currentPlan !== plans.professional && host === "https://app.infisical.com" && workspaceId !== "63ea8121b6e2b0543ba79616") {
|
||||
setIsUpgradeModalOpen(true);
|
||||
} else {
|
||||
const allDenials = userData[index].deniedPermissions
|
||||
@@ -156,8 +156,8 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
...userData.slice(index + 1, userData?.length)
|
||||
]);
|
||||
createNotification({
|
||||
text: `Successfully changed user permissions.`,
|
||||
type: 'success'
|
||||
text: "Successfully changed user permissions.",
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -168,7 +168,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
const result = await getProjectInfo({ projectId: workspaceId });
|
||||
setWorkspaceEnvs(result.environments);
|
||||
|
||||
const orgId = localStorage.getItem('orgData.id') as string;
|
||||
const orgId = localStorage.getItem("orgData.id") as string;
|
||||
const subscriptions = await getOrganizationSubscriptions({
|
||||
orgId
|
||||
});
|
||||
@@ -181,7 +181,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
const grantAccess = async (id: string, publicKey: string) => {
|
||||
const result = await getLatestFileKey({ workspaceId });
|
||||
|
||||
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY') as string;
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
|
||||
// assymmetrically decrypt symmetric key with local private key
|
||||
const key = decryptAssymmetric({
|
||||
@@ -261,13 +261,13 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
// open={isOpen}
|
||||
onValueChange={(e) => handleRoleUpdate(index, e)}
|
||||
value={row.role}
|
||||
isDisabled={myRole !== 'admin' || myUser === row.email}
|
||||
isDisabled={myRole !== "admin" || myUser === row.email}
|
||||
// onOpenChange={(open) => setIsOpen(open)}
|
||||
>
|
||||
<SelectItem value="admin">Admin</SelectItem>
|
||||
<SelectItem value="member">Member</SelectItem>
|
||||
</Select>
|
||||
{row.status === 'completed' && myUser !== row.email && (
|
||||
{row.status === "completed" && myUser !== row.email && (
|
||||
<div className="rounded-md border border-mineshaft-700 bg-white/5 text-white duration-200 hover:bg-primary hover:text-black">
|
||||
<Button
|
||||
onButtonPressed={() => grantAccess(row.userId, row.publicKey)}
|
||||
@@ -297,66 +297,66 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('write') &&
|
||||
.includes("write") &&
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('read')
|
||||
? 'No Access'
|
||||
.includes("read")
|
||||
? "No Access"
|
||||
: // eslint-disable-next-line no-nested-ternary
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('write') &&
|
||||
.includes("write") &&
|
||||
!row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('read')
|
||||
? 'Read Only'
|
||||
.includes("read")
|
||||
? "Read Only"
|
||||
: !row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('write') &&
|
||||
.includes("write") &&
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('read')
|
||||
? 'Add Only'
|
||||
: 'Read & Write'
|
||||
.includes("read")
|
||||
? "Add Only"
|
||||
: "Read & Write"
|
||||
}
|
||||
icon={
|
||||
// eslint-disable-next-line no-nested-ternary
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('write') &&
|
||||
.includes("write") &&
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('read')
|
||||
.includes("read")
|
||||
? faEyeSlash
|
||||
: // eslint-disable-next-line no-nested-ternary
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('write') &&
|
||||
.includes("write") &&
|
||||
!row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('read')
|
||||
.includes("read")
|
||||
? faEye
|
||||
: !row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('write') &&
|
||||
.includes("write") &&
|
||||
row.deniedPermissions
|
||||
.filter((perm: any) => perm.environmentSlug === env.slug)
|
||||
.map((perm: { ability: string }) => perm.ability)
|
||||
.includes('read')
|
||||
.includes("read")
|
||||
? faPlus
|
||||
: faPenToSquare
|
||||
}
|
||||
isDisabled={myRole !== 'admin'}
|
||||
isDisabled={myRole !== "admin"}
|
||||
// onOpenChange={(open) => setIsOpen(open)}
|
||||
>
|
||||
<SelectItem value="No Access" customIcon={faEyeSlash}>
|
||||
@@ -377,7 +377,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoa
|
||||
<td className="border-0.5 flex flex-row justify-end border-t border-mineshaft-700 py-2 pl-8 pr-8">
|
||||
{myUser !== row.email &&
|
||||
// row.role !== "admin" &&
|
||||
myRole !== 'member' ? (
|
||||
myRole !== "member" ? (
|
||||
<div className="mt-0.5 flex items-center opacity-50 hover:opacity-100">
|
||||
<Button
|
||||
onButtonPressed={() => handleDelete(row.membershipId, index)}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { faX } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faX } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import { useNotificationContext } from '@app/components/context/Notifications/NotificationProvider';
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
|
||||
import deleteServiceToken from '../../../pages/api/serviceToken/deleteServiceToken';
|
||||
import guidGenerator from '../../utilities/randomId';
|
||||
import Button from '../buttons/Button';
|
||||
import deleteServiceToken from "../../../pages/api/serviceToken/deleteServiceToken";
|
||||
import guidGenerator from "../../utilities/randomId";
|
||||
import Button from "../buttons/Button";
|
||||
|
||||
interface TokenProps {
|
||||
_id: string;
|
||||
@@ -71,7 +71,7 @@ const ServiceTokenTable = ({ data, workspaceName, setServiceTokens }: ServiceTok
|
||||
setServiceTokens(data.filter((token) => token._id !== row._id));
|
||||
createNotification({
|
||||
text: `'${row.name}' token has been revoked.`,
|
||||
type: 'error'
|
||||
type: "error"
|
||||
});
|
||||
}}
|
||||
color="red"
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { faX } from '@fortawesome/free-solid-svg-icons';
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { faX } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
import changeUserRoleInOrganization from '@app/pages/api/organization/changeUserRoleInOrganization';
|
||||
import deleteUserFromOrganization from '@app/pages/api/organization/deleteUserFromOrganization';
|
||||
import getOrganizationProjectMemberships from '@app/pages/api/organization/GetOrgProjectMemberships';
|
||||
import deleteUserFromWorkspace from '@app/pages/api/workspace/deleteUserFromWorkspace';
|
||||
import getLatestFileKey from '@app/pages/api/workspace/getLatestFileKey';
|
||||
import uploadKeys from '@app/pages/api/workspace/uploadKeys';
|
||||
import changeUserRoleInOrganization from "@app/pages/api/organization/changeUserRoleInOrganization";
|
||||
import deleteUserFromOrganization from "@app/pages/api/organization/deleteUserFromOrganization";
|
||||
import getOrganizationProjectMemberships from "@app/pages/api/organization/GetOrgProjectMemberships";
|
||||
import deleteUserFromWorkspace from "@app/pages/api/workspace/deleteUserFromWorkspace";
|
||||
import getLatestFileKey from "@app/pages/api/workspace/getLatestFileKey";
|
||||
import uploadKeys from "@app/pages/api/workspace/uploadKeys";
|
||||
|
||||
import { decryptAssymmetric, encryptAssymmetric } from '../../utilities/cryptography/crypto';
|
||||
import guidGenerator from '../../utilities/randomId';
|
||||
import Button from '../buttons/Button';
|
||||
import Listbox from '../Listbox';
|
||||
import { decryptAssymmetric, encryptAssymmetric } from "../../utilities/cryptography/crypto";
|
||||
import guidGenerator from "../../utilities/randomId";
|
||||
import Button from "../buttons/Button";
|
||||
import Listbox from "../Listbox";
|
||||
|
||||
// const roles = ['admin', 'user'];
|
||||
// TODO: Set type for this
|
||||
@@ -36,7 +36,7 @@ const UserTable = ({ userData, changeData, myUser, filter, resendInvite, isOrg }
|
||||
Array(userData?.length).fill(userData.map((user) => user.role))
|
||||
);
|
||||
const router = useRouter();
|
||||
const [myRole, setMyRole] = useState('member');
|
||||
const [myRole, setMyRole] = useState("member");
|
||||
const [userProjectMemberships, setUserProjectMemberships] = useState<any[]>([]);
|
||||
|
||||
const workspaceId = router.query.id as string;
|
||||
@@ -90,7 +90,7 @@ const UserTable = ({ userData, changeData, myUser, filter, resendInvite, isOrg }
|
||||
const grantAccess = async (id: string, publicKey: string) => {
|
||||
const result = await getLatestFileKey({ workspaceId });
|
||||
|
||||
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY') as string;
|
||||
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
|
||||
|
||||
// assymmetrically decrypt symmetric key with local private key
|
||||
const key = decryptAssymmetric({
|
||||
@@ -152,29 +152,29 @@ const UserTable = ({ userData, changeData, myUser, filter, resendInvite, isOrg }
|
||||
</td>
|
||||
<td className="pl-6 pr-10 py-2 border-mineshaft-700 border-t text-gray-300">
|
||||
<div className="justify-start h-full flex flex-row items-center">
|
||||
{row.status === 'accepted' &&
|
||||
((myRole === 'admin' && row.role !== 'owner') || myRole === 'owner') &&
|
||||
{row.status === "accepted" &&
|
||||
((myRole === "admin" && row.role !== "owner") || myRole === "owner") &&
|
||||
(myUser !== row.email) ? (
|
||||
<Listbox
|
||||
isSelected={row.role}
|
||||
onChange={(e) => handleRoleUpdate(index, e)}
|
||||
data={
|
||||
myRole === 'owner' ? ['owner', 'admin', 'member'] : ['admin', 'member']
|
||||
myRole === "owner" ? ["owner", "admin", "member"] : ["admin", "member"]
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
row.status !== 'invited' &&
|
||||
row.status !== 'verified' && (
|
||||
row.status !== "invited" &&
|
||||
row.status !== "verified" && (
|
||||
<Listbox
|
||||
isSelected={row.role}
|
||||
onChange={() => {
|
||||
throw new Error('Function not implemented.');
|
||||
throw new Error("Function not implemented.");
|
||||
}}
|
||||
data={null}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{(row.status === 'invited' || row.status === 'verified') && (
|
||||
{(row.status === "invited" || row.status === "verified") && (
|
||||
<div className="w-full pr-20">
|
||||
<Button
|
||||
onButtonPressed={() => deleteMembershipAndResendInvite(row.email)}
|
||||
@@ -184,7 +184,7 @@ const UserTable = ({ userData, changeData, myUser, filter, resendInvite, isOrg }
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{row.status === 'completed' && myUser !== row.email && (
|
||||
{row.status === "completed" && myUser !== row.email && (
|
||||
<div className="border border-mineshaft-700 rounded-md bg-white/5 hover:bg-primary text-white hover:text-black duration-200">
|
||||
<Button
|
||||
onButtonPressed={() => grantAccess(row.userId, row.publicKey)}
|
||||
@@ -210,7 +210,7 @@ const UserTable = ({ userData, changeData, myUser, filter, resendInvite, isOrg }
|
||||
<td className="flex flex-row justify-end pl-8 pr-8 py-2 border-t border-0.5 border-mineshaft-700">
|
||||
{myUser !== row.email &&
|
||||
// row.role !== "admin" &&
|
||||
myRole !== 'member' ? (
|
||||
myRole !== "member" ? (
|
||||
<div className="opacity-50 hover:opacity-100 flex items-center mt-0.5">
|
||||
<Button
|
||||
onButtonPressed={() => handleDelete(row.membershipId, index)}
|
||||
|
||||
Reference in New Issue
Block a user