Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cloud-account): ui for deleting cloud accounts #971

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
35 changes: 35 additions & 0 deletions dashboard/components/icons/AlertCircleIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { SVGProps } from 'react';

const AlertCircleIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 49 49"
fill="none"
{...props}
>
<circle cx="24.5" cy="24.5" r="24" fill="#FFE8E8" />
<path
d="M24.5 34.5C30.0228 34.5 34.5 30.0228 34.5 24.5C34.5 18.9772 30.0228 14.5 24.5 14.5C18.9772 14.5 14.5 18.9772 14.5 24.5C14.5 30.0228 18.9772 34.5 24.5 34.5Z"
stroke="#DE5E5E"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M24.5 20.5V24.5"
stroke="#DE5E5E"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M24.5 28.5H24.51"
stroke="#DE5E5E"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);

export default AlertCircleIcon;
138 changes: 135 additions & 3 deletions dashboard/pages/cloud-accounts.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,77 @@
import Head from 'next/head';
import Image from 'next/image';
import { useEffect, useRef, useState } from 'react';

import classNames from 'classnames';

import providers from '../utils/providerHelper';

import Toast from '../components/toast/Toast';
import Modal from '../components/modal/Modal';
import Button from '../components/button/Button';
import EditIcon from '../components/icons/EditIcon';
import More2Icon from '../components/icons/More2Icon';
import DeleteIcon from '../components/icons/DeleteIcon';
import AlertCircleIcon from '../components/icons/AlertCircleIcon';
import CloudAccountsHeader from '../components/cloud-account/components/CloudAccountsHeader';
import CloudAccountsLayout from '../components/cloud-account/components/CloudAccountsLayout';

import useCloudAccount from '../components/cloud-account/hooks/useCloudAccounts/useCloudAccount';

function CloudAccounts() {
const optionsRef = useRef<HTMLDivElement | null>(null);
const [clickedItemId, setClickedItemId] = useState<string | null>(null);
const [editCloudAccount, setEditCloudAccount] = useState<boolean>(false);
const [removeCloudAccount, setRemoveCloudAccount] = useState<{
state: boolean;
accountName: string;
}>({
state: false,
accountName: ''
});

const { router, cloudAccounts, toast, dismissToast, isNotCustomView } =
useCloudAccount();

useEffect(() => {
const handleOutsideClick = (event: MouseEvent) => {
if (
optionsRef.current &&
!optionsRef.current.contains(event.target as Node)
) {
setClickedItemId(null); // Close the options if clicked outside
}
};

document.addEventListener('mousedown', handleOutsideClick);

return () => {
document.removeEventListener('mousedown', handleOutsideClick);
};
}, []);

const toggleOptions = (itemId: string) => {
setClickedItemId(prevClickedItemId => {
if (prevClickedItemId === itemId) {
return null; // Close on Clicking the same item's icon
}
return itemId;
});
};

const closeRemoveModal = () => {
setRemoveCloudAccount({
state: false,
accountName: ''
});
};

const deleteCloudAccount = () => {
const removalName = removeCloudAccount.accountName;
console.log('deleting', removalName);
// TODO: (onboarding-wizard) handle account removal API call here
};

return (
<>
<Head>
Expand All @@ -30,6 +86,7 @@ function CloudAccounts() {

{cloudAccounts.map(account => {
const { provider, name, status } = account;
const isOpen = clickedItemId === name;

return (
<div
Expand All @@ -43,15 +100,17 @@ function CloudAccounts() {
height={150}
className="h-12 w-12 rounded-full"
/>

<div className="mr-auto">
<p className="font-bold">{name}</p>
<p className="text-black-300">
{providers.providerLabel(provider)}
</p>
</div>

<div
className={classNames(
'group relative rounded-3xl py-1 px-2 text-sm',
'group relative rounded-3xl px-2 py-1 text-sm',
{
'bg-green-200 text-green-600': status.state === 'Connected',
'bg-red-200 text-red-600':
Expand All @@ -62,16 +121,89 @@ function CloudAccounts() {
)}
>
<span>{status.state}</span>
<div className="pointer-events-none invisible absolute z-10 mt-2 -ml-20 rounded-lg bg-gray-800 p-2 text-xs text-white transition-opacity duration-300 group-hover:visible">
<div className="pointer-events-none invisible absolute z-10 -ml-20 mt-2 rounded-lg bg-gray-800 p-2 text-xs text-white transition-opacity duration-300 group-hover:visible">
{status.message}
</div>
</div>
<More2Icon className="h-6 w-6" />

<More2Icon
className="h-6 w-6 cursor-pointer"
onClick={() => toggleOptions(name)}
/>

{isOpen && (
<div
ref={optionsRef}
className="absolute right-0 top-0 mr-5 mt-[70px] items-center rounded-md border border-black-130 bg-white p-4 shadow-xl"
style={{ zIndex: 1000 }}
>
<button
className="flex w-full rounded-md py-3 pl-3 pr-5 text-left text-sm text-black-400 hover:bg-black-150"
onClick={() => {
setEditCloudAccount(true);
setClickedItemId(null);
}}
>
<EditIcon className="mr-2 h-6 w-6" />
Edit cloud account
</button>
<button
className="flex w-full rounded-md py-3 pl-3 pr-5 text-left text-sm text-error-600 hover:bg-black-150"
onClick={() => {
setRemoveCloudAccount({
state: true,
accountName: name
});
setClickedItemId(null);
}}
>
<DeleteIcon className="mr-2 h-6 w-6" />
Remove account
</button>
</div>
)}
</div>
);
})}
</CloudAccountsLayout>

{/* Delete Modal */}
<Modal
isOpen={removeCloudAccount.state}
closeModal={() => closeRemoveModal()}
>
<div className="flex max-w-xl flex-col gap-y-6 p-8 text-black-400">
<div className="flex flex-col items-center gap-y-6">
<AlertCircleIcon className="h-16 w-16" />
<h1 className="text-center text-xl font-semibold text-black-800">
Are you sure you want to remove this cloud account?
</h1>
<h3 className="text-center">
All related data (like custom views and tags) will be deleted and
the {removeCloudAccount.accountName} account will be disconnected
from Komiser.
</h3>
</div>
<div className="flex flex-row place-content-end gap-x-8">
<Button style="text" onClick={() => closeRemoveModal()}>
Cancel
</Button>
<Button style="delete" onClick={() => deleteCloudAccount()}>
Delete account
</Button>
</div>
</div>
</Modal>

{/* Edit Drawer */}
<Modal
isOpen={editCloudAccount}
closeModal={() => setEditCloudAccount(false)}
>
<div>Editing</div>
<div>Replace this with the drawer</div>
</Modal>

{/* Toast component */}
{toast && <Toast {...toast} dismissToast={dismissToast} />}
</>
Expand Down