Skip to content

Commit

Permalink
Frontend: New deletion modals, some UI and Logic bugfix
Browse files Browse the repository at this point in the history
Co-authored-by: Francesco Cheinasso <[email protected]>
  • Loading branch information
cannarelladev authored and kingmakerbot committed Nov 3, 2022
1 parent 2cffb2c commit 5e71b7d
Show file tree
Hide file tree
Showing 18 changed files with 336 additions and 245 deletions.
41 changes: 11 additions & 30 deletions frontend/src/components/activePage/ActiveView/ActiveView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { DeleteOutlined } from '@ant-design/icons';
import { Col, Space } from 'antd';
import Button from 'antd-button-color';
import { FC, useEffect, useState } from 'react';
import { User, WorkspaceRole } from '../../../utils';
import { User, Workspace, WorkspaceRole } from '../../../utils';
import { SessionValue, StorageKeys } from '../../../utilsStorage';
import Box from '../../common/Box';
import { ModalAlert } from '../../common/ModalAlert';
import ModalGroupDeletion from '../ModalGroupDeletion/ModalGroupDeletion';
import TableInstanceLogic from '../TableInstance/TableInstanceLogic';
import TableWorkspaceLogic from '../TableWorkspaceLogic/TableWorkspaceLogic';
import Toolbox from '../Toolbox/Toolbox';
Expand All @@ -16,12 +14,7 @@ const advanced = new SessionValue(StorageKeys.Active_Headers, 'true');

export interface IActiveViewProps {
user: User;
workspaces: Array<{
prettyName: string;
role: WorkspaceRole;
namespace: string;
id: string;
}>;
workspaces: Array<Workspace>;
managerView: boolean;
}

Expand All @@ -40,6 +33,7 @@ const ActiveView: FC<IActiveViewProps> = ({ ...props }) => {
);
const [showCheckbox, setShowCheckbox] = useState(false);
const [selectiveDestroy, setSelectiveDestroy] = useState<string[]>([]);
const [selectedPersistent, setSelectedPersistent] = useState<boolean>(false);

const selectToDestroy = (instanceId: string) => {
selectiveDestroy.includes(instanceId)
Expand Down Expand Up @@ -70,28 +64,14 @@ const ActiveView: FC<IActiveViewProps> = ({ ...props }) => {

return (
<Col span={24} lg={22} xxl={20}>
<ModalAlert
headTitle="Destroy Selected"
<ModalGroupDeletion
view={WorkspaceRole.manager}
persistent={selectedPersistent}
selective={true}
instanceList={selectiveDestroy}
show={showAlert}
message="ATTENTION"
description={`Are you sure do you want to destroy the ${selectiveDestroy.length} selected instances. This operation is dangerous and irreversible!`}
type="error"
buttons={[
<Button
type="danger"
shape="round"
size="middle"
icon={<DeleteOutlined />}
className="border-0"
onClick={() => {
setDestroySelectedTrigger(true);
setShowAlert(false);
}}
>
Destroy Selected
</Button>,
]}
setShow={setShowAlert}
destroy={() => setDestroySelectedTrigger(true)}
/>
<Box
header={{
Expand Down Expand Up @@ -149,6 +129,7 @@ const ActiveView: FC<IActiveViewProps> = ({ ...props }) => {
setDestroySelectedTrigger={setDestroySelectedTrigger}
selectiveDestroy={selectiveDestroy}
selectToDestroy={selectToDestroy}
setSelectedPersistent={setSelectedPersistent}
/>
</div>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Spin } from 'antd';
import ActiveView from '../ActiveView/ActiveView';
import { WorkspaceRole } from '../../../utils';
import { TenantContext } from '../../../graphql-components/tenantContext/TenantContext';
import { makeWorkspace } from '../../../utilsLogic';

const ActiveViewLogic: FC<{}> = ({ ...props }) => {
const {
Expand All @@ -12,17 +13,7 @@ const ActiveViewLogic: FC<{}> = ({ ...props }) => {
} = useContext(TenantContext);

const workspaces =
tenantData?.tenant?.spec?.workspaces?.map(workspace => {
const { workspaceWrapperTenantV1alpha2, name, role } = workspace!;
const { spec, status } =
workspaceWrapperTenantV1alpha2?.itPolitoCrownlabsV1alpha1Workspace!;
return {
prettyName: spec?.prettyName as string,
role: WorkspaceRole[role!],
namespace: status?.namespace?.name!,
id: name!,
};
}) || [];
tenantData?.tenant?.spec?.workspaces?.map(makeWorkspace) || [];

const managerWorkspaces = workspaces?.filter(
ws => ws.role === WorkspaceRole.manager
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { DeleteOutlined } from '@ant-design/icons';
import { Divider } from 'antd';
import Button from 'antd-button-color';
import { Dispatch, FC, SetStateAction, useState } from 'react';
import { ReactComponent as SvgInfinite } from '../../../assets/infinite.svg';
import { WorkspaceRole } from '../../../utils';
import { ModalAlert } from '../../common/ModalAlert';

export interface IModalGroupDeletionProps {
view: WorkspaceRole;
persistent: boolean;
selective: boolean;
groupName?: string;
instanceList: Array<string>;
show: boolean;
setShow: Dispatch<SetStateAction<boolean>>;
destroy: () => void;
}

const ModalGroupDeletion: FC<IModalGroupDeletionProps> = ({ ...props }) => {
const {
view,
persistent,
selective,
groupName,
instanceList,
show,
setShow,
destroy,
} = props;
const [confirmDeletion, setConfirmDeletion] = useState(false);

const title = selective ? 'Destroy Selected' : 'Destroy All';
const message = <b>ATTENTION</b>;
const description = (
<>
<div>
Are you sure that you want to destroy
{selective ? (
<>{` the ${instanceList.length} selected instances`}</>
) : groupName ? (
<>
{' all instances of '}
<b>
<i>{groupName}</i>
</b>
</>
) : (
' all instances'
)}
? <br />
This operation is <u>dangerous and irreversible</u>!
</div>

{persistent ? (
<div className="text-center text-xs">
<Divider type="horizontal" className="my-3" />
<div className="flex items-end">
<i>
(Seems you are also trying to destroy one or more Persistent
instances
<SvgInfinite
width="16px"
className="ml-1.5 success-color-fg align-bottom"
/>
.
{view === WorkspaceRole.manager
? ' You need to confirm their deletion)'
: ' They will be skipped, you need to MANUALLY destroy them)'}
</i>
</div>
</div>
) : (
''
)}
</>
);
const buttons = [
<Button
key="destroy_all"
type="danger"
shape="round"
size="middle"
disabled={!confirmDeletion}
icon={<DeleteOutlined />}
className="border-0"
onClick={() => {
destroy();
setShow(false);
}}
>
{selective ? 'Destroy Selected' : 'Destroy All'}
</Button>,
];

const checkbox = {
confirmCheckbox: confirmDeletion,
setConfirmCheckbox: setConfirmDeletion,
checkboxLabel: 'I understand the risk and I want to proceed',
};

return (
<ModalAlert
headTitle={title}
show={show}
message={message}
description={description}
type="error"
buttons={buttons}
setShow={setShow}
checkbox={checkbox}
/>
);
};

export default ModalGroupDeletion;
45 changes: 20 additions & 25 deletions frontend/src/components/activePage/TableInstance/TableInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ErrorContext } from '../../../errorHandling/ErrorContext';
import { useDeleteInstanceMutation } from '../../../generated-types';
import { TenantContext } from '../../../graphql-components/tenantContext/TenantContext';
import { Instance, WorkspaceRole } from '../../../utils';
import { ModalAlert } from '../../common/ModalAlert';
import ModalGroupDeletion from '../ModalGroupDeletion/ModalGroupDeletion';
import RowInstanceActions from './RowInstanceActions/RowInstanceActions';
import RowInstanceHeader from './RowInstanceHeader/RowInstanceHeader';
import RowInstanceTitle from './RowInstanceTitle/RowInstanceTitle';
Expand Down Expand Up @@ -54,16 +54,20 @@ const TableInstance: FC<ITableInstanceProps> = ({ ...props }) => {
});

const destroyAll = () => {
instances.forEach(instance => {
deleteInstanceMutation({
variables: {
instanceId: instance.name,
tenantNamespace: instance.tenantNamespace!,
},
instances
.filter(i => i.persistent === false)
.forEach(instance => {
deleteInstanceMutation({
variables: {
instanceId: instance.name,
tenantNamespace: instance.tenantNamespace!,
},
});
});
});
};

const disabled = !instances.find(i => i.persistent === false);

// Filtering from all instances that ones which are included in the "selectiveDestroy" IDs list
const selectedIn = instances.filter(i => selectiveDestroy?.includes(i.id));

Expand Down Expand Up @@ -101,6 +105,7 @@ const TableInstance: FC<ITableInstanceProps> = ({ ...props }) => {
showHeader={false}
pagination={false}
rowClassName=""
rowKey={i => 1}
>
<Column
title="Header"
Expand Down Expand Up @@ -188,28 +193,18 @@ const TableInstance: FC<ITableInstanceProps> = ({ ...props }) => {
e.stopPropagation();
setShowAlert(true);
}}
disabled={disabled}
>
Destroy All
</Button>
<ModalAlert
headTitle="Destroy All"
<ModalGroupDeletion
view={WorkspaceRole.user}
persistent={!!instances.find(i => i.persistent === true)}
selective={false}
instanceList={instances.map(i => i.id)}
show={showAlert}
message="Warning"
description="This operation will delete all your instances and it is not reversible. Do you want to continue?"
type="warning"
buttons={[
<Button
type="danger"
shape="round"
size="middle"
icon={<DeleteOutlined />}
className="border-0"
onClick={() => destroyAll()}
>
Destroy All
</Button>,
]}
setShow={setShowAlert}
destroy={destroyAll}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { TenantContext } from '../../../graphql-components/tenantContext/TenantC
import { matchK8sObject, replaceK8sObject } from '../../../k8sUtils';
import { Instance, User, WorkspaceRole } from '../../../utils';
import {
getSubObjType,
getSubObjTypeK8s,
makeGuiInstance,
notifyStatus,
sorter,
Expand Down Expand Up @@ -79,7 +79,7 @@ const TableInstanceLogic: FC<ITableInstanceLogicProps> = ({ ...props }) => {
if (prev.instanceList?.instances) {
let instances = [...prev.instanceList.instances];
const found = instances.find(matchK8sObject(instance, false));
objType = getSubObjType(found, instance, updateType);
objType = getSubObjTypeK8s(found, instance, updateType);
switch (objType) {
case SubObjType.Deletion:
instances = instances.filter(matchK8sObject(instance, true));
Expand Down Expand Up @@ -131,7 +131,7 @@ const TableInstanceLogic: FC<ITableInstanceLogicProps> = ({ ...props }) => {

const instances =
dataInstances?.instanceList?.instances
?.map((i, n) => makeGuiInstance(i, tenantId))
?.map(i => makeGuiInstance(i, tenantId))
.sort((a, b) =>
sorter(
a,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const TableTemplate: FC<ITableTemplateProps> = ({ ...props }) => {
} = props;
const { hasSSHKeys } = useContext(TenantContext);
const [expandedId, setExpandedId] = useState(
expandedT.get(templates[0].workspaceId).split(',')
expandedT.get(templates[0].workspaceName).split(',')
);
const { apolloErrorCatcher } = useContext(ErrorContext);

Expand Down Expand Up @@ -105,7 +105,7 @@ const TableTemplate: FC<ITableTemplateProps> = ({ ...props }) => {
];

useEffect(() => {
expandedT.set(expandedId.join(','), templates[0].workspaceId);
expandedT.set(expandedId.join(','), templates[0].workspaceName);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [expandedId]);

Expand Down
Loading

0 comments on commit 5e71b7d

Please sign in to comment.