([
- {
- target: '.kray',
- content: 'My awesome first step',
- disableBeacon: true,
- },
- {
- target: '.other',
- content: 'My awesome second step',
- disableBeacon: true,
- },
- {
- target: '#button',
- content: 'check out this button',
- disableBeacon: true,
- spotlightPadding: 20,
- },
- ]);
-
- return (
-
-
-
- {
- closeModal();
- setStartTour(true);
- }}
- styleOverrides={{ width: '500px', padding: 0 }}
- />
-
- );
-};
-
-export const Default: StoryObj = {
- render: () => ,
-};
diff --git a/components/TourModal/TourModal.styled.tsx b/components/TourModal/TourModal.styled.tsx
deleted file mode 100644
index 8c2df666..00000000
--- a/components/TourModal/TourModal.styled.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import styled from 'styled-components';
-import Image from 'next/image';
-
-import Column from '../Column/Column';
-import Row from '../Row/Row';
-
-export const CardContent = styled(Column)`
- align-items: center;
- padding: 32px 24px;
-`;
-
-export const CardFooter = styled(Row)`
- justify-content: center;
- gap: 16px;
- padding: 16px 0;
- border-top: 1px solid #e6e8f0;
-`;
-
-export const Content = styled(Column)`
- width: 100%;
-`;
-
-export const K1Ray = styled(Image)`
- height: 162px;
- width: 192px;
- margin: 24px 0;
-`;
diff --git a/components/TourModal/TourModal.tsx b/components/TourModal/TourModal.tsx
deleted file mode 100644
index 397534d9..00000000
--- a/components/TourModal/TourModal.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React, { FunctionComponent } from 'react';
-
-import Modal, { IModalProps } from '../Modal/Modal';
-import Typography from '../Typography/Typography';
-import Button from '../Button/Button';
-
-import { CardContent, CardFooter, Content, K1Ray } from './TourModal.styled';
-
-import kubefirstRay from '@/assets/ray.svg';
-import { BISCAY, VOLCANIC_SAND } from '@/constants/colors';
-
-interface TourModalProps extends Omit {
- onSkip: () => void;
- onTakeTour: () => void;
-}
-
-const TourCard: FunctionComponent = ({ onSkip, onTakeTour, ...modalProps }) => {
- return (
-
-
-
-
- Welcome to kubefirst!
-
-
-
- We’d like to show you a couple of the features we’ve included to get you started.
-
-
-
-
-
-
-
-
- );
-};
-
-export default TourCard;
diff --git a/components/UninstallApplication/UninstallApplication.stories.tsx b/components/UninstallApplication/UninstallApplication.stories.tsx
deleted file mode 100644
index 535e309a..00000000
--- a/components/UninstallApplication/UninstallApplication.stories.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Meta, StoryObj } from '@storybook/react';
-
-import UninstallApplication from './UninstallApplication';
-
-const meta: Meta = {
- title: 'Components/UninstallApplication',
- component: UninstallApplication,
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- application: 'flappy',
- cluster: 'development',
- isOpen: true,
- },
-};
diff --git a/components/UninstallApplication/UninstallApplication.styled.ts b/components/UninstallApplication/UninstallApplication.styled.ts
deleted file mode 100644
index 4587b2a3..00000000
--- a/components/UninstallApplication/UninstallApplication.styled.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-'use client';
-import styled from 'styled-components';
-
-import Column from '../Column/Column';
-import NextLinkComp from '../NextLink/NextLink';
-import Row from '../Row/Row';
-
-export const Content = styled(Column)`
- gap: 8px;
- margin-left: 38px;
-`;
-
-export const CopyTextContainer = styled(Row)`
- flex-wrap: wrap;
- align-items: baseline;
- gap: 3px;
- margin-bottom: 24px;
-`;
-
-export const Footer = styled.div`
- display: flex;
- gap: 8px;
- justify-content: flex-end;
- margin-top: 34px;
-`;
-
-export const Header = styled.div`
- display: flex;
- gap: 12px;
- margin-bottom: 8px;
-`;
-
-export const NextLink = styled(NextLinkComp)`
- display: inline;
-`;
diff --git a/components/UninstallApplication/UninstallApplication.tsx b/components/UninstallApplication/UninstallApplication.tsx
deleted file mode 100644
index f33bda1c..00000000
--- a/components/UninstallApplication/UninstallApplication.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import React, { FunctionComponent, PropsWithChildren } from 'react';
-import Box from '@mui/material/Box';
-import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';
-
-import Typography from '../Typography/Typography';
-import Modal from '../Modal/Modal';
-import Button from '../Button/Button';
-
-import { Content, Footer, Header } from './UninstallApplication.styled';
-
-import { LAUGHING_ORANGE, VOLCANIC_SAND } from '@/constants/colors';
-
-export interface UninstallApplicationProps extends PropsWithChildren {
- application: string;
- canDeleteSelectedApp: boolean;
- cluster: string;
- isOpen: boolean;
- isLoading: boolean;
- onDelete: () => void;
- onCloseModal?: () => void;
-}
-
-const UninstallApplication: FunctionComponent = ({
- application,
- canDeleteSelectedApp,
- cluster,
- isOpen,
- onDelete,
- onCloseModal,
-}) => {
- return (
-
-
-
-
-
- {canDeleteSelectedApp ? 'Uninstall application' : 'Application not found'}
-
-
-
- <>
- {canDeleteSelectedApp ? (
-
- Are you sure you want to uninstall {application} from cluster{' '}
- {cluster}?
-
- ) : (
- <>
-
- It appears that this application has been manually removed from your repository.
-
- Do you want to remove the application tile from this view?
- >
- )}
- >
-
-
-
-
- );
-};
-
-export default UninstallApplication;
diff --git a/components/UpgradeModal/UpgradeModal.stories.tsx b/components/UpgradeModal/UpgradeModal.stories.tsx
deleted file mode 100644
index e186353e..00000000
--- a/components/UpgradeModal/UpgradeModal.stories.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import { Meta, StoryObj } from '@storybook/react';
-
-import Button from '../Button/Button';
-
-import UpgradeModalComponent from './UpgradeModal';
-
-import useModal from '@/hooks/useModal';
-
-const meta: Meta = {
- component: UpgradeModalComponent,
-};
-
-export default meta;
-
-const UpgradeModal = () => {
- const { isOpen, openModal, closeModal } = useModal(true);
- return (
-
-
-
-
- );
-};
-
-export const Default: StoryObj = {
- render: () => ,
-};
diff --git a/components/UpgradeModal/UpgradeModal.styled.ts b/components/UpgradeModal/UpgradeModal.styled.ts
deleted file mode 100644
index efff4230..00000000
--- a/components/UpgradeModal/UpgradeModal.styled.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-'use client';
-import styled from 'styled-components';
-import CloseIcon from '@mui/icons-material/Close';
-
-import Column from '../Column/Column';
-import Row from '../Row/Row';
-
-import { MIDNIGHT_EXPRESS } from '@/constants/colors';
-
-export const Container = styled(Column)`
- background-color: ${MIDNIGHT_EXPRESS};
- border-radius: 8px;
- box-shadow: 0px 2px 4px rgba(100, 116, 139, 0.1);
- padding: 16px 24px;
- height: 408px;
- width: 400px;
-`;
-
-export const Content = styled(Column)`
- align-items: center;
- margin: 24px;
-`;
-
-export const Close = styled(CloseIcon)`
- cursor: pointer;
- position: fixed;
- top: 25px;
- right: 25px;
-`;
-
-export const Footer = styled(Row)`
- gap: 16px;
- justify-content: center;
- padding: 16px 24px;
-`;
-
-export const Header = styled(Row)`
- gap: 16px;
- padding-top: 24px;
- text-transform: capitalize;
-`;
diff --git a/components/UpgradeModal/UpgradeModal.tsx b/components/UpgradeModal/UpgradeModal.tsx
deleted file mode 100644
index 41e0338a..00000000
--- a/components/UpgradeModal/UpgradeModal.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React, { FunctionComponent } from 'react';
-import Image from 'next/image';
-import StarBorderOutlinedIcon from '@mui/icons-material/StarBorderOutlined';
-
-import Modal from '../Modal/Modal';
-import Button from '../Button/Button';
-import Typography from '../Typography/Typography';
-
-import { Container, Content, Close, Footer, Header } from './UpgradeModal.styled';
-
-import { ASMANI_SKY, ECHO_BLUE, MIDNIGHT_EXPRESS, WHITE } from '@/constants/colors';
-import RocketIcon from '@/assets/rocket.svg';
-
-export interface UpgradeModalProps {
- isOpen: boolean;
- clusterLimitText: string;
- clusterLimitDescription: string;
- ctaText: string;
- closeModal: () => void;
-}
-
-const UpgradeModal: FunctionComponent = ({
- ctaText,
- closeModal,
- clusterLimitText,
- clusterLimitDescription,
- isOpen,
-}) => {
- const handleRedirect = () => {
- return window.open(`${location.origin}/settings/subscription/plans`, '_blank');
- };
-
- return (
-
-
-
-
-
-
- {clusterLimitText}
-
-
- {clusterLimitDescription}
-
-
-
-
-
- );
-};
-
-export default UpgradeModal;
diff --git a/components/controlledFields/ControlledAutoComplete/ControlledTagsAutoComplete.tsx b/components/controlledFields/ControlledAutoComplete/ControlledTagsAutoComplete.tsx
deleted file mode 100644
index 6a470523..00000000
--- a/components/controlledFields/ControlledAutoComplete/ControlledTagsAutoComplete.tsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import React from 'react';
-import { Control, Controller, FieldValues, UseControllerProps } from 'react-hook-form';
-
-import { AutocompleteTags } from '../../Autocomplete/Autocomplete';
-
-import { ClusterEnvironment } from '@/types/provision';
-
-export interface ControlledTagsAutoCompleteProps
- extends UseControllerProps {
- label: string;
- required?: boolean;
- control: Control;
- onChange: (value?: ClusterEnvironment) => void;
- onTagDelete: () => void;
- onAddNewEnvironment?: () => void;
- options: ClusterEnvironment[];
- createEnvironment?: boolean;
-}
-
-function ControlledTagsAutocomplete({
- label,
- onChange,
- onTagDelete,
- options,
- createEnvironment,
- onAddNewEnvironment,
- ...rest
-}: ControlledTagsAutoCompleteProps) {
- return (
- (
-
- )}
- />
- );
-}
-
-export default ControlledTagsAutocomplete;
diff --git a/containers/Application/Application.tsx b/containers/Application/Application.tsx
deleted file mode 100644
index f2c43920..00000000
--- a/containers/Application/Application.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import React, { FunctionComponent, useCallback, useEffect, useState } from 'react';
-
-import ApplicationComponent, {
- ApplicationProps as AppCompProps,
-} from '@/components/Application/Application';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { checkSiteReadiness } from '@/redux/thunks/readiness.thunk';
-
-export interface ApplicationProps extends Omit {
- links?: Array;
- onUninstall: () => void;
-}
-
-const isGitLink = (url: string) => url.includes('github') || url.includes('gitlab');
-
-const Application: FunctionComponent = ({
- links: applicationLinks,
- onUninstall,
- ...props
-}) => {
- const [firstLoad, setFirstLoad] = useState(false);
-
- const [links, setLinks] = useState<{ [url: string]: boolean } | undefined>(
- applicationLinks?.reduce((previous, current) => {
- return { ...previous, [current]: isGitLink(current) };
- }, {}),
- );
-
- const dispatch = useAppDispatch();
- const availableSites = useAppSelector(({ readiness }) => readiness.availableSites);
-
- const isSiteAvailable = useCallback(
- (url: string) => {
- return availableSites.includes(url) || isGitLink(url);
- },
- [availableSites],
- );
-
- const checkSiteAvailability = useCallback(
- (url: string) => {
- const isAvailable = isSiteAvailable(url);
-
- if (!isAvailable) {
- return dispatch(checkSiteReadiness({ url }));
- }
- },
- [dispatch, isSiteAvailable],
- );
-
- useEffect(() => {
- if (availableSites.length) {
- setLinks(
- links &&
- Object.keys(links).reduce(
- (previous, current) => ({ ...previous, [current]: isSiteAvailable(current) }),
- {},
- ),
- );
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [availableSites]);
-
- useEffect(() => {
- const interval = setInterval(
- () =>
- links &&
- Object.keys(links).map((url) => {
- const isAvailable = links[url];
- !isAvailable && checkSiteAvailability(url);
- }),
- 20000,
- );
- return () => clearInterval(interval);
- });
-
- useEffect(() => {
- if (!firstLoad) {
- setFirstLoad(true);
- links &&
- Object.keys(links).map(async (url) => {
- await checkSiteAvailability(url);
- });
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- return ;
-};
-
-export default Application;
diff --git a/containers/Applications/Applications.styled.ts b/containers/Applications/Applications.styled.ts
deleted file mode 100644
index 541fd9d2..00000000
--- a/containers/Applications/Applications.styled.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-'use client';
-import Link from 'next/link';
-import styled from 'styled-components';
-
-import Row from '@/components/Row/Row';
-import ApplicationsFilterComp from '@/components/ApplicationsFilter/ApplicationsFilter';
-import { media } from '@/utils/media';
-
-export const Container = styled.div`
- height: calc(100vh - 64px);
- margin: 0 auto;
- overflow: auto;
- padding: 40px 0 0 40px;
- width: calc(100% - 40px);
-`;
-
-export const Content = styled.div``;
-
-export const Header = styled.div`
- color: ${({ theme }) => theme.colors.volcanicSand};
- display: flex;
- flex-direction: column;
- gap: 8px;
- margin-bottom: 24px;
-`;
-
-export const LearnMoreLink = styled(Link)`
- color: ${({ theme }) => theme.colors.primary};
- text-decoration: none;
-`;
-
-export const ApplicationsContainer = styled(Row)`
- gap: 16px;
- flex-wrap: wrap;
- margin-bottom: 16px;
-`;
-
-export const ApplicationsFilter = styled(ApplicationsFilterComp)`
- width: fit-content;
- min-width: 310px;
- margin-bottom: 16px;
-
- ${media.greaterThan('sm')`
- width: calc(100% - 70px);
- `}
-`;
diff --git a/containers/Applications/Applications.tsx b/containers/Applications/Applications.tsx
deleted file mode 100644
index 9b64ec0f..00000000
--- a/containers/Applications/Applications.tsx
+++ /dev/null
@@ -1,314 +0,0 @@
-'use client';
-import React, { FunctionComponent, useEffect, useCallback, useState, useMemo } from 'react';
-import Box from '@mui/material/Box';
-import Tabs from '@mui/material/Tabs';
-import sortBy from 'lodash/sortBy';
-import { useSession } from 'next-auth/react';
-
-import Application from '../Application/Application';
-import GitOpsCatalog from '../GitOpsCatalog/GitOpsCatalog';
-
-import {
- Container,
- Content,
- Header,
- LearnMoreLink,
- ApplicationsContainer,
- ApplicationsFilter,
-} from './Applications.styled';
-
-import TabPanel, { Tab, a11yProps } from '@/components/Tab/Tab';
-import Typography from '@/components/Typography/Typography';
-import {
- getClusterApplications,
- getGitOpsCatalogApps,
- uninstallGitOpsApp,
- validateGitOpsApplication,
-} from '@/redux/thunks/applications.thunk';
-import { sendTelemetryEvent } from '@/redux/thunks/api.thunk';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { DOCS_LINK } from '@/constants';
-import { BISCAY, SALTBOX_BLUE, VOLCANIC_SAND } from '@/constants/colors';
-import {
- addAppToQueue,
- removeAppFromQueue,
- setFilterState,
- setSelectedClusterApplication,
-} from '@/redux/slices/applications.slice';
-import { ClusterStatus, WORKLOAD_CLUSTER_TYPES } from '@/types/provision';
-import { ClusterApplication, GitOpsCatalogApp } from '@/types/applications';
-import useModal from '@/hooks/useModal';
-import UninstallApplication from '@/components/UninstallApplication/UninstallApplication';
-
-enum APPLICATION_TAB {
- PROVISIONED,
- GITOPS_CATALOG,
-}
-
-enum Target {
- TEMPLATE = 'Template',
- CLUSTER = 'Cluster',
-}
-
-const TARGET_OPTIONS = Object.values(Target);
-
-const Applications: FunctionComponent = () => {
- const [searchTerm, setSearchTerm] = useState('');
- const [activeTab, setActiveTab] = useState(0);
- const { isOpen, openModal: openDeleteModal, closeModal: closeDeleteModal } = useModal();
- const { data: session } = useSession();
-
- const {
- clusterApplications,
- isTelemetryDisabled,
- clusterMap,
- filter,
- selectedCategories,
- gitOpsCatalogApps,
- installedClusterAppNames,
- isLoading,
- managementCluster,
- selectedClusterApplication,
- canDeleteSelectedApp,
- appsQueue,
- } = useAppSelector(({ config, applications, api }) => ({
- isTelemetryDisabled: config.isTelemetryDisabled,
- clusterMap: api.clusterMap,
- managementCluster: api.managementCluster,
- ...applications,
- }));
-
- const dispatch = useAppDispatch();
-
- const handleLinkClick = useCallback(
- (url: string, name: string) => {
- if (!isTelemetryDisabled) {
- const event = `console.${name.toLowerCase()}.link`.replace(/ /g, '');
- dispatch(sendTelemetryEvent({ event }));
- }
- },
- [dispatch, isTelemetryDisabled],
- );
-
- const handleChange = (_: React.SyntheticEvent, newValue: number) => {
- setActiveTab(newValue);
- };
- const catalogApps = useMemo(
- () =>
- filter.target === Target.TEMPLATE
- ? gitOpsCatalogApps.filter((app) => !app.secret_keys?.length)
- : gitOpsCatalogApps,
- [filter.target, gitOpsCatalogApps],
- );
-
- const clusterSelectOptions = useMemo((): { label: string; value: string }[] => {
- if (!filter.target) {
- return [];
- }
-
- if (filter.target === Target.TEMPLATE) {
- return WORKLOAD_CLUSTER_TYPES.map((type) => ({ label: type, value: type }));
- }
-
- return Object.keys(clusterMap)
- .filter((key) => {
- const cluster = clusterMap[key];
- return cluster.status === ClusterStatus.PROVISIONED;
- })
- .map((clusterName) => ({
- label: clusterName,
- value: clusterName,
- }));
- }, [filter.target, clusterMap]);
-
- const filteredApps = useMemo(() => {
- return clusterApplications.filter((app) =>
- app.name.toLowerCase().includes(searchTerm?.toLowerCase() as string),
- );
- }, [clusterApplications, searchTerm]);
-
- const uninstalledCatalogApps = useMemo(
- () => catalogApps.filter((app) => !clusterApplications.map((s) => s.name).includes(app.name)),
- [clusterApplications, catalogApps],
- );
-
- const targetOptions = useMemo(() => {
- const options = TARGET_OPTIONS.map((target) => ({ label: target, value: target }));
- if (managementCluster?.cloudProvider === 'k3d') {
- return options.filter(({ value }) => value !== Target.TEMPLATE);
- }
-
- return options;
- }, [managementCluster?.cloudProvider]);
-
- const filteredCatalogApps = useMemo(() => {
- let apps: GitOpsCatalogApp[] = [];
- if (!selectedCategories.length) {
- apps = uninstalledCatalogApps;
- } else {
- apps = uninstalledCatalogApps.filter(
- ({ category, name }) =>
- category &&
- selectedCategories.includes(category) &&
- !installedClusterAppNames.includes(name),
- );
- }
-
- return sortBy(apps, (app) => app.display_name).filter((app) =>
- app.name.toLowerCase().includes(searchTerm?.toLowerCase() as string),
- );
- }, [selectedCategories, uninstalledCatalogApps, installedClusterAppNames, searchTerm]);
-
- const handleOpenUninstallModalConfirmation = useCallback(() => {
- openDeleteModal();
- }, [openDeleteModal]);
-
- const handleCloseUninstallModalConfirmation = useCallback(() => {
- if (!isLoading) {
- dispatch(removeAppFromQueue(selectedClusterApplication?.name as string));
- }
- closeDeleteModal();
- }, [closeDeleteModal, dispatch, isLoading, selectedClusterApplication?.name]);
-
- const validateUninstallApplication = useCallback(
- (application: ClusterApplication) => {
- dispatch(addAppToQueue(application?.name as string));
- dispatch(setSelectedClusterApplication(application));
-
- dispatch(
- validateGitOpsApplication({
- application,
- }),
- ).then(() => {
- dispatch(removeAppFromQueue(selectedClusterApplication?.name as string));
- handleOpenUninstallModalConfirmation();
- });
- },
- [dispatch, handleOpenUninstallModalConfirmation, selectedClusterApplication?.name],
- );
-
- const handleUninstallApplication = useCallback(() => {
- dispatch(addAppToQueue(selectedClusterApplication?.name as string));
- closeDeleteModal();
- dispatch(
- uninstallGitOpsApp({
- application: selectedClusterApplication as ClusterApplication,
- user: (session?.user?.email as string) || 'kbot',
- }),
- );
- }, [closeDeleteModal, dispatch, selectedClusterApplication, session?.user?.email]);
-
- useEffect(() => {
- if (managementCluster?.cloudProvider) {
- dispatch(getGitOpsCatalogApps(managementCluster?.cloudProvider));
- }
- }, [dispatch, managementCluster?.cloudProvider]);
-
- useEffect(() => {
- const { cluster } = filter;
- if (cluster) {
- dispatch(getClusterApplications({ clusterName: cluster }));
- }
- }, [dispatch, filter]);
-
- const Apps = useMemo(
- () => (
- <>
-
- {filteredApps.map((application: ClusterApplication) => (
- validateUninstallApplication(application)}
- />
- ))}
-
- >
- ),
- [appsQueue, filteredApps, handleLinkClick, validateUninstallApplication],
- );
-
- return (
-
-
- Applications Overview
-
- <>
-
-
- Installed applications}
- {...a11yProps(APPLICATION_TAB.PROVISIONED)}
- sx={{ textTransform: 'initial', mr: 3 }}
- />
-
- GitOps catalog}
- {...a11yProps(APPLICATION_TAB.GITOPS_CATALOG)}
- sx={{ textTransform: 'initial' }}
- />
-
-
-
- {activeTab === APPLICATION_TAB.PROVISIONED ? (
-
- Click on a link to access the service Kubefirst has provisioned for you.{' '}
- handleLinkClick(DOCS_LINK, 'docs')}
- >
- Learn more
-
-
- ) : (
-
- Add the latest version of your favourite application to your cluster.{' '}
- handleLinkClick(DOCS_LINK, 'docs')}
- >
- Learn more
-
-
- )}
-
- {managementCluster?.clusterName && (
- ({ label: app.name, value: app.name }))}
- onFilterChange={(filter) => dispatch(setFilterState(filter))}
- onSearchChange={setSearchTerm}
- defaultCluster={managementCluster?.clusterName as string}
- />
- )}
-
- {Apps}
-
-
-
-
-
- >
- {isOpen && (
-
- )}
-
- );
-};
-
-export default Applications;
diff --git a/containers/Billing/Billing.styled.ts b/containers/Billing/Billing.styled.ts
deleted file mode 100644
index 70d88767..00000000
--- a/containers/Billing/Billing.styled.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import styled from 'styled-components';
-
-import { WHITE } from '@/constants/colors';
-
-export const Container = styled.div`
- width: 100%;
-`;
-
-export const Header = styled.div`
- background-color: ${WHITE};
- border-radius: 8px 8px 0px 0px;
- display: flex;
- justify-content: space-between;
- padding: 16px 24px;
- margin-top: 24px;
-`;
-
-export const NoLicenseContainer = styled.div`
- display: flex;
- align-items: center;
- flex-direction: column;
- margin-top: 100px;
-`;
diff --git a/containers/Billing/Billing.tsx b/containers/Billing/Billing.tsx
deleted file mode 100644
index a62d3e90..00000000
--- a/containers/Billing/Billing.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import React, { FunctionComponent, useEffect, useMemo } from 'react';
-import Image from 'next/image';
-
-import { Container, Header, NoLicenseContainer } from './Billing.styled';
-
-import Typography from '@/components/Typography/Typography';
-import NextLink from '@/components/NextLink/NextLink';
-import Loading from '@/components/Loading/Loading';
-import { ClusterUsageTable } from '@/components/ClusterUsageTable/ClusterUsageTable';
-import { ASWAD_BLACK, BISCAY, VOLCANIC_SAND } from '@/constants/colors';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { getClusterUsage } from '@/redux/thunks/subscription.thunk';
-import MagnifyGlass from '@/assets/magnify-glass.svg';
-import { selectHasLicenseKey } from '@/redux/selectors/subscription.selector';
-
-const Billing: FunctionComponent = () => {
- const dispatch = useAppDispatch();
-
- const { isLoading, license, clusterUsageList } = useAppSelector(
- ({ subscription }) => subscription,
- );
-
- const hasLicenseKey = useAppSelector(selectHasLicenseKey());
-
- const total = useMemo(
- () =>
- clusterUsageList.length &&
- clusterUsageList.reduce(
- (previousValue, currentValue) => previousValue + currentValue.total,
- 0,
- ),
- [clusterUsageList],
- );
-
- useEffect(() => {
- if (license?.licenseKey) {
- dispatch(getClusterUsage(license?.licenseKey));
- }
- }, [dispatch, license?.licenseKey]);
-
- return (
-
- {hasLicenseKey ? (
- <>
-
- If at any time you need to update your billing card you can do so
- by changing your card via Stripe.
-
-
-
- Cluster usage for current month
-
-
- ${total && total.toFixed(2)}
-
-
- {isLoading ? : }
- >
- ) : (
-
-
-
- You haven’t exceeded the Free Plan cluster usage yet
-
-
- Once you do, you will be able to see your cluster usage and billing here.
-
-
- )}
-
- );
-};
-
-export default Billing;
diff --git a/containers/CancelSubscription/CancelSubscription.tsx b/containers/CancelSubscription/CancelSubscription.tsx
deleted file mode 100644
index a9d5466e..00000000
--- a/containers/CancelSubscription/CancelSubscription.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import React, { FunctionComponent, ReactNode, useCallback, useMemo } from 'react';
-import { FormProvider, useForm } from 'react-hook-form';
-
-import CancelSubscriptionForm from './CancelSubscriptionForm/CancelSubscriptionForm';
-import CancelSubscriptionConfirmation from './CancelSubscriptionConfirmation/CancelSubscriptionConfirmation';
-
-import useStep from '@/hooks/useStep';
-import { CancelSubscriptionFields, UserRequest } from '@/types/subscription';
-import Modal from '@/components/Modal/Modal';
-import { useAppDispatch } from '@/redux/store';
-import { createUserRequest, validateLicenseKey } from '@/redux/thunks/subscription.thunk';
-
-export enum MODAL_STEP {
- FORM = 0,
- CONFIRMATION = 1,
-}
-
-export interface CancelSubscriptionProps {
- isOpen: boolean;
- closeModal: () => void;
-}
-
-const CancelSubscription: FunctionComponent = ({ isOpen, closeModal }) => {
- const { currentStep, goToNext, goTo } = useStep();
- const dispatch = useAppDispatch();
-
- const methods = useForm({
- mode: 'onChange',
- });
-
- const handleCancelSubscription = useCallback(
- (userRequest: UserRequest) => {
- dispatch(createUserRequest(userRequest)).then(() => {
- goToNext();
- dispatch(validateLicenseKey());
- });
- },
- [dispatch, goToNext],
- );
-
- const handleClose = useCallback(() => {
- closeModal();
- goTo(0);
- }, [closeModal, goTo]);
-
- const modalComponents = useMemo(
- () =>
- ({
- [MODAL_STEP.FORM]: (
-
-
-
- ),
- [MODAL_STEP.CONFIRMATION]: ,
- } as { [key: string]: ReactNode }),
- [closeModal, handleCancelSubscription, handleClose, methods],
- );
-
- const modalComponent = useMemo(
- () => modalComponents && modalComponents[currentStep as unknown as string],
- [currentStep, modalComponents],
- );
-
- return (
-
- <>{modalComponent}>
-
- );
-};
-
-export default CancelSubscription;
diff --git a/containers/CancelSubscription/CancelSubscriptionConfirmation/CancelSubscriptionConfirmation.styled.ts b/containers/CancelSubscription/CancelSubscriptionConfirmation/CancelSubscriptionConfirmation.styled.ts
deleted file mode 100644
index 8e8a08cd..00000000
--- a/containers/CancelSubscription/CancelSubscriptionConfirmation/CancelSubscriptionConfirmation.styled.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import styled from 'styled-components';
-import { Box } from '@mui/material';
-
-export const Container = styled(Box)`
- align-items: center;
- display: flex;
- flex-direction: column;
- padding: 32px 24px;
- width: 452px;
-`;
-
-export const Footer = styled.div`
- display: flex;
- justify-content: center;
- padding: 16px;
-`;
diff --git a/containers/CancelSubscription/CancelSubscriptionConfirmation/CancelSubscriptionConfirmation.tsx b/containers/CancelSubscription/CancelSubscriptionConfirmation/CancelSubscriptionConfirmation.tsx
deleted file mode 100644
index cbb20d95..00000000
--- a/containers/CancelSubscription/CancelSubscriptionConfirmation/CancelSubscriptionConfirmation.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import React, { FunctionComponent } from 'react';
-import { Divider } from '@mui/material';
-import Image from 'next/image';
-
-import { Container, Footer } from './CancelSubscriptionConfirmation.styled';
-
-import Cancel from '@/assets/cancel.svg';
-import Typography from '@/components/Typography/Typography';
-import { BISCAY, VOLCANIC_SAND } from '@/constants/colors';
-import Button from '@/components/Button/Button';
-
-export interface CancelSubscriptionConfirmationProps {
- closeModal: () => void;
-}
-
-const CancelSubscriptionConfirmation: FunctionComponent = ({
- closeModal,
-}) => {
- return (
- <>
-
-
- We’re sorry to see you go!
-
-
-
- You will receive an email within 24 hours confirming that your subscription has been
- cancelled and your plan has been downgraded.
-
-
-
-
- >
- );
-};
-
-export default CancelSubscriptionConfirmation;
diff --git a/containers/CancelSubscription/CancelSubscriptionForm/CancelSubscriptionForm.styled.ts b/containers/CancelSubscription/CancelSubscriptionForm/CancelSubscriptionForm.styled.ts
deleted file mode 100644
index 4795c7d5..00000000
--- a/containers/CancelSubscription/CancelSubscriptionForm/CancelSubscriptionForm.styled.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import styled from 'styled-components';
-import { Box } from '@mui/material';
-
-export const Container = styled(Box)`
- width: 582px;
-`;
-
-export const SubscriptionOptions = styled.div`
- display: flex;
- flex-direction: column;
- gap: 16px;
- padding: 0 24px;
- margin-bottom: 24px;
-`;
-
-export const Header = styled.div`
- align-items: center;
- display: flex;
- justify-content: space-between;
- padding: 24px;
-
- & > svg {
- cursor: pointer;
- }
-`;
-
-export const Footer = styled.div`
- display: flex;
- justify-content: flex-end;
- gap: 16px;
- padding: 16px 24px;
-`;
-
-export const Description = styled.div`
- padding: 0 24px;
- margin-bottom: 32px;
-`;
diff --git a/containers/CancelSubscription/CancelSubscriptionForm/CancelSubscriptionForm.tsx b/containers/CancelSubscription/CancelSubscriptionForm/CancelSubscriptionForm.tsx
deleted file mode 100644
index 1de97fdc..00000000
--- a/containers/CancelSubscription/CancelSubscriptionForm/CancelSubscriptionForm.tsx
+++ /dev/null
@@ -1,141 +0,0 @@
-import React, { FunctionComponent, useEffect, useState } from 'react';
-import { useFormContext } from 'react-hook-form';
-import { Divider } from '@mui/material';
-import CloseIcon from '@mui/icons-material/Close';
-
-import {
- Container,
- Description,
- Footer,
- Header,
- SubscriptionOptions,
-} from './CancelSubscriptionForm.styled';
-
-import Typography from '@/components/Typography/Typography';
-import { BISCAY, SALTBOX_BLUE, VOLCANIC_SAND } from '@/constants/colors';
-import ControlledCheckbox from '@/components/controlledFields/ControlledCheckbox/ControlledCheckbox';
-import Button from '@/components/Button/Button';
-import { CancelSubscriptionFields, UserRequest } from '@/types/subscription';
-import ControlledTextArea from '@/components/controlledFields/ControlledTextArea/ControlledTextArea';
-import { Required } from '@/components/TextField/TextField.styled';
-
-export const CANCEL_SUBSCRIPTION_OPTIONS = [
- {
- name: 'projectIsComplete',
- label: 'The project I was working on is now complete',
- },
- {
- name: 'kubefirstIsTooExpensive',
- label: 'kubefirst is too expensive',
- },
- {
- name: 'kubefirstIsDifficult',
- label: 'kubefirst is too difficult to use',
- },
- {
- name: 'didnotUsePaidPlan',
- label: 'I didn’t use the paid plan features',
- },
- {
- name: 'didnotProvideFunctionality',
- label: 'kubefirst didn’t provide the functionality I needed',
- },
- {
- name: 'other',
- label: 'Other',
- },
-];
-
-export interface CancelSubscriptionFormProps {
- closeModal: () => void;
- handleCancelSubscription: (userRequest: UserRequest) => void;
-}
-
-const CancelSubscriptionForm: FunctionComponent = ({
- closeModal,
- handleCancelSubscription,
-}) => {
- const [hasSelectedOption, setHasSelectedOption] = useState(false);
- const { control, handleSubmit, watch, reset } = useFormContext();
-
- const onSubmit = async ({ description, ...rest }: CancelSubscriptionFields) => {
- const reasons = Object.keys(rest)
- .filter((key) => rest && !!rest[key as never])
- .map((reason) => {
- return CANCEL_SUBSCRIPTION_OPTIONS.find(({ name }) => name === reason)?.label;
- })
- .join(', ');
-
- const requestData: UserRequest = {
- requestData: JSON.stringify({ message: description, reason: reasons }),
- type: 'cancel',
- };
-
- handleCancelSubscription(requestData);
- reset();
- };
-
- useEffect(() => {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- const subscription = watch(({ description, ...rest }) => {
- setHasSelectedOption([...Object.values(rest)].includes(true));
- });
-
- return () => subscription.unsubscribe();
- }, [watch]);
-
- return (
-
-
-
- Cancel my subscription
-
-
-
-
-
- Before you go would you mind letting us know why? *
-
-
- {CANCEL_SUBSCRIPTION_OPTIONS.map(({ name, label }) => (
-
- ))}
-
-
-
-
-
-
-
- );
-};
-
-export default CancelSubscriptionForm;
diff --git a/containers/ClusterForms/ClusterCreationForm/AdvancedOptions/AdvancedOptions.styled.ts b/containers/ClusterForms/ClusterCreationForm/AdvancedOptions/AdvancedOptions.styled.ts
deleted file mode 100644
index 0e904dc3..00000000
--- a/containers/ClusterForms/ClusterCreationForm/AdvancedOptions/AdvancedOptions.styled.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-'use client';
-import styled from 'styled-components';
-
-import Column from '@/components/Column/Column';
-import LearnMore from '@/components/LearnMore/LearnMore';
-import { EXCLUSIVE_PLUM } from '@/constants/colors';
-
-export const InputContainer = styled(Column)`
- .MuiFormGroup-root {
- margin-left: 8px;
- }
-
- & ${LearnMore} {
- margin-left: 40px;
- color: ${EXCLUSIVE_PLUM};
-
- span,
- a {
- color: ${EXCLUSIVE_PLUM};
- }
- }
-`;
diff --git a/containers/ClusterForms/ClusterCreationForm/AdvancedOptions/AdvancedOptions.tsx b/containers/ClusterForms/ClusterCreationForm/AdvancedOptions/AdvancedOptions.tsx
deleted file mode 100644
index 2b28baf9..00000000
--- a/containers/ClusterForms/ClusterCreationForm/AdvancedOptions/AdvancedOptions.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import React, { FunctionComponent, useState } from 'react';
-import { useFormContext } from 'react-hook-form';
-
-import { InputContainer } from './AdvancedOptions.styled';
-
-import LearnMore from '@/components/LearnMore/LearnMore';
-import Typography from '@/components/Typography/Typography';
-import Checkbox from '@/components/controlledFields/ControlledCheckbox/ControlledCheckbox';
-import ControlledTextField from '@/components/controlledFields/ControlledTextField/ControlledTextField';
-import ControlledAutocomplete from '@/components/controlledFields/ControlledAutoComplete/ControlledAutoComplete';
-import ControlledRadioGroup from '@/components/controlledFields/ControlledRadioGroup/ControlledRadioGroup';
-import { useAppSelector } from '@/redux/store';
-import { ImageRepository, NewWorkloadClusterConfig } from '@/types/provision';
-import { EXCLUSIVE_PLUM } from '@/constants/colors';
-
-const AdvancedOptions: FunctionComponent = () => {
- const [isCloudFlareSelected, setIsCloudFlareSelected] = useState(false);
-
- const { installType } = useAppSelector(({ installation }) => installation);
-
- const { control, getValues } = useFormContext();
-
- const { gitopsTemplateUrl, gitopsTemplateBranch, imageRepository } = getValues();
-
- return (
- <>
-
-
-
-
-
- By default kubefirst uses ssh to create your cluster check the below to use https instead{' '}
-
-
-
- setIsCloudFlareSelected(value === 'cloudflare')}
- rules={{
- required: false,
- }}
- />
- {isCloudFlareSelected && (
-
- )}
-
-
- Manage image repositories with
-
-
-
- >
- );
-};
-
-export default AdvancedOptions;
diff --git a/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.stories.tsx b/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.stories.tsx
deleted file mode 100644
index be9881ac..00000000
--- a/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.stories.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import { Meta, StoryObj } from '@storybook/react';
-import { action } from '@storybook/addon-actions';
-import { FormProvider, useForm } from 'react-hook-form';
-
-import { NewWorkloadClusterConfig } from '../../../types/provision';
-
-import ClusterCreationForm from './ClusterCreationForm';
-
-const meta: Meta = {
- title: 'Forms/ClusterCreationForm',
- component: ClusterCreationForm,
-};
-
-export default meta;
-
-const ClusterCreationFormWithHooks = () => {
- const methods = useForm();
-
- return (
-
-
-
- );
-};
-
-export const Default: StoryObj = {
- render: () => ,
-};
diff --git a/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.styled.ts b/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.styled.ts
deleted file mode 100644
index 5e693621..00000000
--- a/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.styled.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import Column from '@/components/Column/Column';
-import Button from '@/components/Button/Button';
-import styled, { css } from '@/app/lib/styled-components';
-
-export const AdvancedOptionsButton = styled('button')
- .withConfig({
- shouldForwardProp: (prop) => prop !== 'expanded',
- })
- .attrs({ type: 'button' })<{
- expanded?: boolean;
-}>`
- border: none;
- background-color: transparent;
- display: flex;
- cursor: pointer;
-
- svg {
- transition: transform 0.4s ease;
- }
-
- ${({ expanded }) =>
- expanded &&
- css`
- svg {
- transform: rotate(180deg);
- }
- `}
-`;
-
-export const Container = styled(Column)`
- gap: 32px;
- width: 100%;
-`;
-
-export const StyledButton = styled(Button)`
- width: 163px;
- margin-top: -8px;
- display: flex;
- gap: 8px;
-
- svg {
- height: 20px;
- width: 20px;
- }
-`;
diff --git a/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.tsx b/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.tsx
deleted file mode 100644
index 1f212714..00000000
--- a/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm.tsx
+++ /dev/null
@@ -1,332 +0,0 @@
-import React, { ComponentProps, FC, useCallback, useEffect, useMemo } from 'react';
-import { useFormContext } from 'react-hook-form';
-import Box from '@mui/material/Box';
-
-import { usePhysicalClustersPermissions } from '../../../hooks/usePhysicalClustersPermission';
-
-import { Container } from './ClusterCreationForm.styled';
-import { InputContainer } from './AdvancedOptions/AdvancedOptions.styled';
-
-import ControlledAutocomplete from '@/components/controlledFields/ControlledAutoComplete/ControlledAutoComplete';
-import ControlledTextField from '@/components/controlledFields/ControlledTextField/ControlledTextField';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import Typography from '@/components/Typography/Typography';
-import { ClusterType, NewWorkloadClusterConfig, ClusterEnvironment } from '@/types/provision';
-import { BISCAY, EXCLUSIVE_PLUM } from '@/constants/colors';
-import ControlledNumberInput from '@/components/controlledFields/ControlledNumberInput/ControlledNumberInput';
-import ControlledRadioGroup from '@/components/controlledFields/ControlledRadioGroup/ControlledRadioGroup';
-import {
- LOWER_KEBAB_CASE_REGEX,
- MIN_NODE_COUNT,
- RESERVED_DRAFT_CLUSTER_NAME,
- WORKLOAD_CLUSTER_OPTIONS,
-} from '@/constants';
-import { updateDraftCluster } from '@/redux/slices/api.slice';
-import Modal from '@/components/Modal/Modal';
-import useModal from '@/hooks/useModal';
-import { CreateEnvironmentMenu } from '@/components/CreateEnvironmentMenu/CreateEnvironmentMenu';
-import { createEnvironment, getAllEnvironments } from '@/redux/thunks/environments.thunk';
-import { noop } from '@/utils/noop';
-import { clearEnvironmentError } from '@/redux/slices/environments.slice';
-import { InstallationType } from '@/types/redux';
-import {
- getCloudDomains,
- getCloudRegions,
- getInstanceSizes,
- getRegionZones,
-} from '@/redux/thunks/api.thunk';
-import ControlledTagsAutocomplete from '@/components/controlledFields/ControlledAutoComplete/ControlledTagsAutoComplete';
-import { getCloudProviderAuth } from '@/utils/getCloudProviderAuth';
-import { selectApiState } from '@/redux/selectors/api.selector';
-import { selectEnvironmentsState } from '@/redux/selectors/environments.selector';
-
-const ClusterCreationForm: FC> = (props) => {
- const { isOpen, openModal, closeModal } = useModal(false);
- const { managementCluster, cloudRegions, cloudZones, clusterMap, instanceSizes } = useAppSelector(
- selectApiState(),
- );
- const { environments, error } = useAppSelector(selectEnvironmentsState());
-
- const dispatch = useAppDispatch();
-
- const {
- control,
- getValues,
- setValue,
- watch,
- formState: { errors },
- } = useFormContext();
-
- const { type, nodeCount, instanceSize, cloudRegion, clusterName } = getValues();
-
- const handleAddEnvironment = useCallback(
- (environment: ClusterEnvironment) => {
- setValue('environment', environment);
- dispatch(createEnvironment(environment))
- .unwrap()
- .then(() => {
- closeModal();
- })
- .catch(noop);
- },
- [dispatch, setValue, closeModal],
- );
-
- const clearEnvError = useCallback(() => {
- dispatch(clearEnvironmentError());
- }, [dispatch]);
-
- const handleModalClose = useCallback(() => {
- clearEnvError();
- closeModal();
- }, [clearEnvError, closeModal]);
-
- const handleRegionOnSelect = useCallback(
- (region: string) => {
- // if using google hold off on grabbing instances
- // since it requires the zone as well
- if (managementCluster) {
- const { key, value } = getCloudProviderAuth(managementCluster);
- if (managementCluster?.cloudProvider === InstallationType.GOOGLE) {
- dispatch(
- getRegionZones({
- region,
- values: { [`${key}_auth`]: value },
- }),
- );
- } else {
- dispatch(
- getInstanceSizes({
- installType: managementCluster?.cloudProvider,
- region,
- values: { [`${key}_auth`]: value },
- }),
- );
- dispatch(
- getCloudDomains({
- installType: managementCluster?.cloudProvider,
- region,
- }),
- );
- }
- }
- },
- [dispatch, managementCluster],
- );
-
- const handleZoneSelect = (zone: string) => {
- const { cloudRegion } = getValues();
- if (managementCluster && cloudRegion) {
- const { key, value } = getCloudProviderAuth(managementCluster);
- dispatch(
- getInstanceSizes({
- installType: managementCluster?.cloudProvider,
- region: cloudRegion,
- zone,
- values: { [`${key}_auth`]: value },
- }),
- );
- }
- };
-
- const handleEnvChange = useCallback(
- (env?: ClusterEnvironment) => {
- setValue('environment', env);
- },
- [setValue],
- );
-
- const handleTagDelete = useCallback(() => {
- setValue('environment', undefined);
- }, [setValue]);
-
- const { hasPermissions } = usePhysicalClustersPermissions(managementCluster?.cloudProvider);
- const draftCluster = clusterMap[RESERVED_DRAFT_CLUSTER_NAME];
- const isVCluster = type === ClusterType.WORKLOAD_V_CLUSTER;
-
- const clusterOptions = useMemo(() => {
- let clusterTypes;
-
- if (hasPermissions) {
- clusterTypes = WORKLOAD_CLUSTER_OPTIONS;
- } else {
- clusterTypes = WORKLOAD_CLUSTER_OPTIONS.filter(
- (option) => option.value !== ClusterType.WORKLOAD,
- );
- }
-
- return clusterTypes;
- }, [hasPermissions]);
-
- useEffect(() => {
- const subscription = watch((values) => {
- if (draftCluster) {
- dispatch(updateDraftCluster({ ...draftCluster, ...values }));
- }
- });
-
- return () => subscription.unsubscribe();
- }, [watch, dispatch, draftCluster]);
-
- useEffect(() => {
- if (managementCluster) {
- dispatch(
- getCloudRegions({
- values: managementCluster,
- installType: managementCluster.cloudProvider,
- }),
- );
- dispatch(getAllEnvironments());
- }
- // i do not want to get cloud regions every time management cluster updates
- // initial load and hard refresh is sufficient.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [dispatch]);
-
- useEffect(() => {
- if (cloudRegion && managementCluster) {
- const { key, value } = getCloudProviderAuth(managementCluster);
- dispatch(
- getInstanceSizes({
- installType: managementCluster?.cloudProvider,
- region: cloudRegion,
- values: { [`${key}_auth`]: value },
- }),
- );
- }
- // i do not want to get instance sizes every time management cluster updates
- // initial load/hard refresh/cloudRegion update is sufficient.
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [cloudRegion]);
-
- return (
-
-
- Create workload cluster
-
-
-
-
- Cluster type
-
- setValue('type', clusterType)}
- />
-
-
-
-
-
-
-
-
-
- (typeof value === 'string' && !clusterMap[value]) ||
- 'Please use a unique name that has not been previously provisioned',
- reservedClusterName: (value) =>
- (typeof value === 'string' && value !== RESERVED_DRAFT_CLUSTER_NAME) ||
- 'Please use a cluster name that is not reserved',
- },
- }}
- onErrorText={errors.clusterName?.message}
- />
-
- {!isVCluster && (
- <>
- ({ label: region, value: region }))}
- onChange={handleRegionOnSelect}
- />
-
- {managementCluster?.cloudProvider === InstallationType.GOOGLE && (
- ({
- label: zone,
- value: zone,
- }))}
- onChange={handleZoneSelect}
- />
- )}
-
- ({
- label: instanceSize,
- value: instanceSize,
- }))}
- defaultValue={instanceSize}
- />
-
-
-
-
- >
- )}
-
- );
-};
-
-export default ClusterCreationForm;
diff --git a/containers/ClusterForms/shared/AuthForm/AuthForm.tsx b/containers/ClusterForms/shared/AuthForm/AuthForm.tsx
index 278b4b59..4a6a34d0 100644
--- a/containers/ClusterForms/shared/AuthForm/AuthForm.tsx
+++ b/containers/ClusterForms/shared/AuthForm/AuthForm.tsx
@@ -330,7 +330,7 @@ const AuthForm: FunctionComponent = () => {
/>
>
)}
- {apiKeyInfo?.fieldKeys.map(({ label, name, helperText }) =>
+ {apiKeyInfo?.fieldKeys.map(({ label, name, helperText, defaultValue }) =>
isDigitalOcean && name === 'token' ? (
{
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
name={`${apiKeyInfo.authKey}.${name}`}
+ defaultValue={defaultValue}
label={label}
helperText={helperText}
required
diff --git a/containers/ClusterForms/shared/ClusterRunning.tsx b/containers/ClusterForms/shared/ClusterRunning.tsx
index e397c877..31ad5d17 100644
--- a/containers/ClusterForms/shared/ClusterRunning.tsx
+++ b/containers/ClusterForms/shared/ClusterRunning.tsx
@@ -1,25 +1,25 @@
-import React, { FunctionComponent, useCallback } from 'react';
+import React, { FunctionComponent, useEffect } from 'react';
+import { noop } from 'lodash';
import ClusterReady from '@/components/ClusterReady/ClusterReady';
import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { setSelectedCluster } from '@/redux/slices/applications.slice';
+import { getClusters } from '@/redux/thunks/api.thunk';
const ClusterRunning: FunctionComponent = () => {
- const dispatch = useAppDispatch();
-
const { managementCluster } = useAppSelector(({ api }) => api);
+ const dispatch = useAppDispatch();
const { clusterName, domainName, subDomainName, vaultAuth } = managementCluster ?? {};
const fullDomainName = `${subDomainName ? `${subDomainName}.${domainName}` : domainName}`;
- const onOpenConsole = useCallback(() => {
- dispatch(setSelectedCluster(managementCluster));
- }, [dispatch, managementCluster]);
+ useEffect(() => {
+ dispatch(getClusters());
+ }, [dispatch]);
return (
{
installationStep,
installType,
values,
- clusterMap,
showCloudflareCaIssuerField,
} = useAppSelector(({ api, installation, featureFlags }) => ({
...api,
@@ -176,7 +175,7 @@ const SetupForm: FunctionComponent = () => {
useEffect(() => {
checkAuth();
if (installType && values) {
- dispatch(getCloudRegions({ installType, values }));
+ dispatch(getCloudRegions({ installType, values, validate: false }));
}
}, [checkAuth, dispatch, installType, values, trigger]);
@@ -318,7 +317,7 @@ const SetupForm: FunctionComponent = () => {
},
validate: {
previouslyUsedClusterNames: (value) =>
- (typeof value === 'string' && !clusterMap[value]) ||
+ typeof value === 'string' ||
'Please use a unique name that has not been previously provisioned',
civoClusterName: (value) => {
if (installType === InstallationType.CIVO) {
diff --git a/containers/ClusterManagement/ClusterManagement.styled.ts b/containers/ClusterManagement/ClusterManagement.styled.ts
deleted file mode 100644
index 248b260a..00000000
--- a/containers/ClusterManagement/ClusterManagement.styled.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-'use client';
-import Link from 'next/link';
-import styled from 'styled-components';
-import { styled as muiStyled } from '@mui/material/styles';
-
-import Typography from '@/components/Typography/Typography';
-import Column from '@/components/Column/Column';
-import Row from '@/components/Row/Row';
-import Drawer from '@/components/Drawer/Drawer';
-import { VOLCANIC_SAND } from '@/constants/colors';
-
-export const Content = styled(Column)`
- flex: 1;
- width: 100%;
-`;
-
-export const Description = styled(Typography)`
- color: ${VOLCANIC_SAND};
- margin-top: 8px;
-`;
-
-export const Header = styled(Row)`
- color: ${({ theme }) => theme.colors.volcanicSand};
- height: 70px;
- align-items: center;
- justify-content: space-between;
- background-color: white;
- border-top: 1px solid #e2e8f0;
-`;
-
-export const LearnMoreLink = styled(Link)`
- color: ${({ theme }) => theme.colors.primary};
- text-decoration: none;
-`;
-
-export const LeftContainer = styled(Row)`
- align-items: center;
- margin-left: 24px;
- gap: 42px;
-`;
-
-export const StyledDrawer = muiStyled(Drawer, {
- shouldForwardProp: (prop) => prop !== 'isBannerOpen',
-})(({ isBannerOpen }: { isBannerOpen: boolean }) => ({
- '&.MuiDrawer-root': {
- '.MuiBackdrop-root': {
- backgroundColor: 'transparent',
- },
- },
- '.MuiDrawer-paper': {
- top: isBannerOpen ? '72px' : '65px',
- boxShadow: '0px 2px 4px rgba(100, 116, 139, 0.16)',
- width: '684px',
- height: 'calc(100% - 65px)',
- },
-}));
diff --git a/containers/ClusterManagement/ClusterManagement.tsx b/containers/ClusterManagement/ClusterManagement.tsx
deleted file mode 100644
index 5e583e3a..00000000
--- a/containers/ClusterManagement/ClusterManagement.tsx
+++ /dev/null
@@ -1,353 +0,0 @@
-'use client';
-import React, { FunctionComponent, useCallback, useEffect, useMemo } from 'react';
-import Box from '@mui/material/Box';
-import Tabs from '@mui/material/Tabs';
-
-import { CreateClusterFlow } from './CreateClusterFlow/CreateClusterFlow';
-import { Content, Header, LeftContainer, StyledDrawer } from './ClusterManagement.styled';
-
-import Button from '@/components/Button/Button';
-import Typography from '@/components/Typography/Typography';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { createWorkloadCluster, deleteCluster, downloadKubeconfig } from '@/redux/thunks/api.thunk';
-import {
- ClusterCreationStep,
- ClusterStatus,
- ClusterType,
- WorkloadCluster,
-} from '@/types/provision';
-import useToggle from '@/hooks/useToggle';
-import useModal from '@/hooks/useModal';
-import DeleteCluster from '@/components/DeleteCluster/DeleteCluster';
-import TabPanel, { Tab, a11yProps } from '@/components/Tab/Tab';
-import { BISCAY, SALTBOX_BLUE } from '@/constants/colors';
-import { Flow } from '@/components/Flow/Flow';
-import ClusterTable from '@/components/ClusterTable/ClusterTable';
-import {
- createDraftCluster,
- removeDraftCluster,
- setClusterCreationStep,
-} from '@/redux/slices/api.slice';
-import { setPresentedClusterName } from '@/redux/slices/api.slice';
-import { InstallationType } from '@/types/redux';
-import { setClusterManagamentTab } from '@/redux/slices/config.slice';
-import { ClusterManagementTab, FeatureFlag } from '@/types/config';
-import {
- DEFAULT_CLOUD_INSTANCE_SIZES,
- KUBECONFIG_CLI_DETAILS,
- RESERVED_DRAFT_CLUSTER_NAME,
- SUGGESTED_WORKLOAD_NODE_COUNT,
-} from '@/constants';
-import { getClusterTourStatus } from '@/redux/thunks/settings.thunk';
-import usePaywall from '@/hooks/usePaywall';
-import UpgradeModal from '@/components/UpgradeModal/UpgradeModal';
-import { selectUpgradeLicenseDefinition } from '@/redux/selectors/subscription.selector';
-import KubeConfigModal from '@/components/KubeConfigModal/KubeConfigModal';
-import { createNotification } from '@/redux/slices/notifications.slice';
-import useFeatureFlag from '@/hooks/useFeatureFlag';
-import Column from '@/components/Column/Column';
-import { SaasFeatures } from '@/types/subscription';
-
-const ClusterManagement: FunctionComponent = () => {
- const {
- clusterCreationStep,
- clusterManagementTab,
- clusterMap,
- isBannerOpen,
- managementCluster,
- presentedClusterName,
- loading,
- } = useAppSelector(({ api, queue, config, featureFlags, settings }) => ({
- clusterQueue: queue.clusterQueue,
- clusterManagementTab: config.clusterManagementTab,
- ...api,
- ...featureFlags.flags,
- ...settings,
- }));
-
- const dispatch = useAppDispatch();
- const upgradeLicenseDefinition = useAppSelector(selectUpgradeLicenseDefinition());
- const { isEnabled: isSassSubscriptionEnabled } = useFeatureFlag(FeatureFlag.SAAS_SUBSCRIPTION);
-
- const {
- isOpen: isUpgradeModalOpen,
- openModal: openUpgradeModal,
- closeModal: closeUpgradeModal,
- } = useModal();
- const { canUseFeature } = usePaywall();
- const { instanceSize } =
- DEFAULT_CLOUD_INSTANCE_SIZES[managementCluster?.cloudProvider ?? InstallationType.LOCAL];
-
- const presentedCluster = useMemo(
- () => clusterMap[presentedClusterName ?? ''],
- [clusterMap, presentedClusterName],
- );
-
- const {
- isOpen: createClusterFlowOpen,
- open: openCreateClusterFlow,
- close: closeCreateClusterFlow,
- } = useToggle();
-
- const {
- isOpen: isDeleteModalOpen,
- openModal: openDeleteModal,
- closeModal: closeDeleteModal,
- } = useModal();
-
- const {
- isOpen: isKubeconfigModalOpen,
- openModal: openKubeconfigModal,
- closeModal: closeKubeconfigModal,
- } = useModal();
-
- const handleMenuClose = useCallback(() => {
- if (clusterCreationStep === ClusterCreationStep.CONFIG) {
- dispatch(removeDraftCluster());
- } else {
- dispatch(setClusterCreationStep(ClusterCreationStep.CONFIG));
- }
- dispatch(setPresentedClusterName(undefined));
- closeCreateClusterFlow();
- }, [clusterCreationStep, dispatch, closeCreateClusterFlow]);
-
- const handleDeleteCluster = useCallback(() => {
- if (presentedClusterName) {
- dispatch(deleteCluster(presentedClusterName))
- .unwrap()
- .then(() => {
- closeDeleteModal();
- handleMenuClose();
- });
- }
- }, [dispatch, presentedClusterName, closeDeleteModal, handleMenuClose]);
-
- const handleChange = useCallback(
- (_: React.SyntheticEvent, tabIndex: number) => {
- dispatch(setClusterManagamentTab(tabIndex));
- if (presentedClusterName) {
- dispatch(setPresentedClusterName(undefined));
- }
- },
- [dispatch, presentedClusterName],
- );
-
- const handleClusterSelect = useCallback(
- (clusterName: string) => {
- dispatch(setPresentedClusterName(clusterName));
- dispatch(setClusterCreationStep(ClusterCreationStep.DETAILS));
- openCreateClusterFlow();
- },
- [dispatch, openCreateClusterFlow],
- );
-
- const handleAddWorkloadCluster = useCallback(() => {
- if (clusterCreationStep === ClusterCreationStep.CONFIG && managementCluster) {
- const {
- gitProvider,
- cloudProvider,
- domainName,
- adminEmail,
- gitAuth,
- dnsProvider,
- cloudRegion,
- } = managementCluster;
-
- const draftCluster: WorkloadCluster = {
- clusterId: RESERVED_DRAFT_CLUSTER_NAME,
- clusterName: RESERVED_DRAFT_CLUSTER_NAME,
- status: ClusterStatus.PROVISIONING,
- type: ClusterType.WORKLOAD,
- nodeCount: SUGGESTED_WORKLOAD_NODE_COUNT,
- cloudProvider,
- cloudRegion,
- gitProvider,
- domainName,
- gitAuth,
- adminEmail,
- dnsProvider,
- };
-
- dispatch(createDraftCluster(draftCluster));
- }
- openCreateClusterFlow();
- }, [clusterCreationStep, managementCluster, dispatch, openCreateClusterFlow]);
-
- const handleCreateCluster = () => {
- if (clusterCreationStep !== ClusterCreationStep.DETAILS) {
- const canCreateWorkloadClusters = canUseFeature(SaasFeatures.WorkloadClustersLimit);
-
- if (isSassSubscriptionEnabled && !canCreateWorkloadClusters) {
- return openUpgradeModal();
- }
- }
-
- if (clusterCreationStep !== ClusterCreationStep.DETAILS) {
- dispatch(createWorkloadCluster());
- }
- };
-
- const handleDeleteMenuClick = useCallback(
- (clusterName: string) => {
- dispatch(setPresentedClusterName(clusterName));
- openDeleteModal();
- },
- [dispatch, openDeleteModal],
- );
-
- const handleDownloadKubeconfig = useCallback(async () => {
- if ([InstallationType.AWS, InstallationType.GOOGLE].includes(presentedCluster.cloudProvider)) {
- openKubeconfigModal();
- } else if (presentedCluster) {
- const { clusterName } = presentedCluster;
- dispatch(downloadKubeconfig({ presentedCluster }))
- .unwrap()
- .then((encodedString) => {
- const downloadLink = document.createElement('a');
- downloadLink.href = encodedString;
- downloadLink.download = `${clusterName}-kubeconfig`;
-
- document.body.appendChild(downloadLink);
-
- downloadLink.click();
-
- document.body.removeChild(downloadLink);
- })
- .catch((error) => {
- dispatch(
- createNotification({
- message: `Unable to download kubeconfig: ${error.message}`,
- type: 'error',
- snackBarOrigin: { vertical: 'top', horizontal: 'center' },
- }),
- );
- });
- }
- }, [dispatch, presentedCluster, openKubeconfigModal]);
-
- const { command, commandDocLink } =
- KUBECONFIG_CLI_DETAILS[managementCluster?.cloudProvider ?? InstallationType.AWS];
-
- useEffect(() => {
- if (managementCluster) {
- dispatch(getClusterTourStatus(managementCluster.clusterName));
- }
- }, [dispatch, managementCluster]);
-
- return (
- <>
-
-
- Clusters
-
-
- Graph view}
- {...a11yProps(ClusterManagementTab.GRAPH_VIEW)}
- sx={{ textTransform: 'initial', marginRight: '24px' }}
- />
- List view}
- {...a11yProps(ClusterManagementTab.LIST_VIEW)}
- sx={{ textTransform: 'initial', marginRight: 0 }}
- />
-
-
-
-
-
-
-
-
-
- {managementCluster && (
-
- )}
-
-
-
-
-
-
-
-
-
- {!!presentedCluster && (
-
- )}
- {isUpgradeModalOpen && (
-
- )}
- {isKubeconfigModalOpen && (
-
- )}
- >
- );
-};
-
-export default ClusterManagement;
diff --git a/containers/ClusterManagement/CreateClusterFlow/CreateClusterFlow.styled.ts b/containers/ClusterManagement/CreateClusterFlow/CreateClusterFlow.styled.ts
deleted file mode 100644
index 0e6b3247..00000000
--- a/containers/ClusterManagement/CreateClusterFlow/CreateClusterFlow.styled.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-'use client';
-import styled from 'styled-components';
-import { styled as muiStyled, Box } from '@mui/material';
-
-import Row from '@/components/Row/Row';
-import Column from '@/components/Column/Column';
-import HeadsUpNotification from '@/components/HeadsUpNotification/HeadsUpNotification';
-import { CHEFS_HAT } from '@/constants/colors';
-
-export const CloseButton = styled.button`
- display: flex;
- align-items: center;
- border: none;
- background-color: transparent;
- cursor: pointer;
-`;
-
-export const Form = styled.form`
- display: flex;
- flex-direction: column;
- height: 100%;
-`;
-
-export const FormContent = styled(Column)`
- flex: 1;
- padding: 0 24px;
- overflow-y: auto;
-
- ${HeadsUpNotification} {
- margin-top: 20px;
- }
-`;
-
-export const Menu = muiStyled(Box)(
- () => `
- min-width: 210px;
- position: absolute;
- bottom: -90px;
- left: -148px;
- width: 160px;
- background-color: white;
- border: 1px solid ${CHEFS_HAT};
- border-radius: 8px;
- box-shadow: 0px 2px 4px 0px rgba(100, 116, 139, 0.25);
- z-index: 1;
-`,
-);
-
-export const MenuHeader = styled(Row)`
- flex-shrink: 0;
- color: ${({ theme }) => theme.colors.volcanicSand};
- height: 70px;
- justify-content: space-between;
- align-items: center;
- background-color: white;
- padding: 0 24px;
- border-bottom: 1px solid #e2e8f0;
-`;
diff --git a/containers/ClusterManagement/CreateClusterFlow/CreateClusterFlow.tsx b/containers/ClusterManagement/CreateClusterFlow/CreateClusterFlow.tsx
deleted file mode 100644
index 886d76f5..00000000
--- a/containers/ClusterManagement/CreateClusterFlow/CreateClusterFlow.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-import React, { FC, useCallback } from 'react';
-import CloseIcon from '@mui/icons-material/Close';
-import MoreHoriz from '@mui/icons-material/MoreHoriz';
-import List from '@mui/material/List';
-import ListItem from '@mui/material/ListItem';
-import ListItemButton from '@mui/material/ListItemButton';
-import { ClickAwayListener } from '@mui/material';
-import { FormProvider, useForm } from 'react-hook-form';
-
-import { CloseButton, Form, FormContent, Menu, MenuHeader } from './CreateClusterFlow.styled';
-
-import Button from '@/components/Button/Button';
-import { FIRE_BRICK, SALTBOX_BLUE } from '@/constants/colors';
-import ClusterCreationForm from '@/containers/ClusterForms/ClusterCreationForm/ClusterCreationForm';
-import ClusterDetails from '@/components/ClusterDetails/ClusterDetails';
-import {
- Cluster,
- ClusterCreationStep,
- ClusterStatus,
- DraftCluster,
- ManagementCluster,
- NewWorkloadClusterConfig,
-} from '@/types/provision';
-import { RESERVED_DRAFT_CLUSTER_NAME } from '@/constants';
-import useToggle from '@/hooks/useToggle';
-import Row from '@/components/Row/Row';
-import Typography from '@/components/Typography/Typography';
-
-interface CreateClusterFlowProps {
- cluster?: Cluster | DraftCluster;
- clusterCreationStep: ClusterCreationStep;
- defaultValues?: NewWorkloadClusterConfig;
- loading: boolean;
- managementCluster?: ManagementCluster;
- onClusterDelete: () => void;
- onDownloadKubeconfig: () => void;
- onMenuClose: () => void;
- onSubmit: () => void;
-}
-
-export const CreateClusterFlow: FC = ({
- cluster,
- clusterCreationStep,
- defaultValues,
- loading,
- managementCluster,
- onClusterDelete,
- onDownloadKubeconfig,
- onMenuClose,
- onSubmit,
-}) => {
- const { isOpen, close, toggle } = useToggle();
-
- const methods = useForm({
- defaultValues,
- mode: 'onChange',
- });
-
- const {
- formState: { isValid },
- } = methods;
-
- const handleClick = useCallback(() => {
- if (clusterCreationStep === ClusterCreationStep.DETAILS) {
- onClusterDelete();
- }
- }, [onClusterDelete, clusterCreationStep]);
-
- const submitButtonDisabled =
- !isValid ||
- loading ||
- (cluster?.clusterId !== RESERVED_DRAFT_CLUSTER_NAME &&
- cluster?.status === ClusterStatus.PROVISIONING);
-
- const showingClusterDetails = clusterCreationStep === ClusterCreationStep.DETAILS;
-
- return (
-
-
-
- );
-};
diff --git a/containers/ContactUsModal/ContactUsForm/ContactUsForm.styled.ts b/containers/ContactUsModal/ContactUsForm/ContactUsForm.styled.ts
deleted file mode 100644
index 84b41063..00000000
--- a/containers/ContactUsModal/ContactUsForm/ContactUsForm.styled.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import styled from 'styled-components';
-import { Box } from '@mui/material';
-
-export const Container = styled(Box)`
- width: 606px;
-`;
-
-export const Header = styled.div`
- align-items: center;
- display: flex;
- justify-content: space-between;
- padding: 24px;
-
- & > svg {
- cursor: pointer;
- }
-`;
-
-export const Footer = styled.div`
- display: flex;
- justify-content: flex-end;
- gap: 16px;
- padding: 16px 24px;
-`;
-
-export const NameSection = styled.div`
- display: flex;
- gap: 24px;
-`;
-
-export const FieldsContainer = styled.div`
- display: flex;
- flex-direction: column;
- padding: 0 24px;
- gap: 24px;
- margin-bottom: 24px;
-`;
diff --git a/containers/ContactUsModal/ContactUsForm/ContactUsForm.tsx b/containers/ContactUsModal/ContactUsForm/ContactUsForm.tsx
deleted file mode 100644
index fcc014a9..00000000
--- a/containers/ContactUsModal/ContactUsForm/ContactUsForm.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import React, { FunctionComponent } from 'react';
-import { useFormContext } from 'react-hook-form';
-import { Divider } from '@mui/material';
-import CloseIcon from '@mui/icons-material/Close';
-
-import { Container, FieldsContainer, Footer, Header, NameSection } from './ContactUsForm.styled';
-
-import Typography from '@/components/Typography/Typography';
-import { BISCAY, SALTBOX_BLUE, VOLCANIC_SAND } from '@/constants/colors';
-import Button from '@/components/Button/Button';
-import { ContactUsFields, UserRequest } from '@/types/subscription';
-import ControlledTextArea from '@/components/controlledFields/ControlledTextArea/ControlledTextArea';
-import ControlledTextField from '@/components/controlledFields/ControlledTextField/ControlledTextField';
-import { EMAIL_REGEX } from '@/constants';
-
-export interface ContactUsFormProps {
- closeModal: () => void;
- handleContactUsRequest: (userRequest: UserRequest) => void;
-}
-
-const ContactUsFormProps: FunctionComponent = ({
- closeModal,
- handleContactUsRequest,
-}) => {
- const {
- control,
- handleSubmit,
- reset,
- formState: { isValid },
- } = useFormContext();
-
- const onSubmit = async ({ email, firstName, lastName, message }: ContactUsFields) => {
- const requestData: UserRequest = {
- requestData: JSON.stringify({ message, email, name: `${firstName} ${lastName}` }),
- type: 'upgrade',
- };
-
- handleContactUsRequest(requestData);
- reset();
- };
-
- return (
-
-
-
- Contact us for an Enterprise Plan
-
-
-
-
-
- Get even more GitOps magic with an Enterprise Plan. Send us a few details and a member of
- our team will reach out to you as soon as possible.{' '}
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default ContactUsFormProps;
diff --git a/containers/ContactUsModal/ContactUsModal.tsx b/containers/ContactUsModal/ContactUsModal.tsx
deleted file mode 100644
index c889fbe4..00000000
--- a/containers/ContactUsModal/ContactUsModal.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import React, { FunctionComponent, useCallback } from 'react';
-import { FormProvider, useForm } from 'react-hook-form';
-
-import ContactUsForm from './ContactUsForm/ContactUsForm';
-
-import { CancelSubscriptionFields, UserRequest } from '@/types/subscription';
-import Modal from '@/components/Modal/Modal';
-import { useAppDispatch } from '@/redux/store';
-import { createUserRequest, validateLicenseKey } from '@/redux/thunks/subscription.thunk';
-
-export interface ContactUsProps {
- isOpen: boolean;
- closeModal: () => void;
-}
-
-const ContactUs: FunctionComponent = ({ isOpen, closeModal }) => {
- const dispatch = useAppDispatch();
-
- const methods = useForm({
- mode: 'onChange',
- });
-
- const handleContactUsRequest = useCallback(
- (userRequest: UserRequest) => {
- dispatch(createUserRequest(userRequest)).then(() => {
- dispatch(validateLicenseKey());
- closeModal();
- });
- },
- [closeModal, dispatch],
- );
-
- return (
-
-
-
-
-
- );
-};
-
-export default ContactUs;
diff --git a/containers/Environments/Environments.tsx b/containers/Environments/Environments.tsx
deleted file mode 100644
index 4077c52e..00000000
--- a/containers/Environments/Environments.tsx
+++ /dev/null
@@ -1,169 +0,0 @@
-'use client';
-import React, { FunctionComponent, useEffect, useState, useCallback } from 'react';
-import styled from 'styled-components';
-import Image from 'next/image';
-
-import Row from '@/components/Row/Row';
-import Column from '@/components/Column/Column';
-import Typography from '@/components/Typography/Typography';
-import LearnMore from '@/components/LearnMore/LearnMore';
-import Button from '@/components/Button/Button';
-import compDisplayImage from '@/assets/comp_display.svg';
-import useToggle from '@/hooks/useToggle';
-import Modal from '@/components/Modal/Modal';
-import { CreateEnvironmentMenu } from '@/components/CreateEnvironmentMenu/CreateEnvironmentMenu';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import {
- createEnvironment,
- deleteEnvironment,
- getAllEnvironments,
-} from '@/redux/thunks/environments.thunk';
-import EnvironmentsTable from '@/components/EnvironmentsTable/EnvironmentsTable';
-import { ClusterEnvironment } from '@/types/provision';
-import DeleteEnvironment from '@/components/DeleteEnvironment/DeleteEnvironment';
-import { clearEnvironmentError } from '@/redux/slices/environments.slice';
-import { noop } from '@/utils/noop';
-import { VOLCANIC_SAND } from '@/constants/colors';
-import { DOCS_LINK } from '@/constants';
-
-const Environments: FunctionComponent = () => {
- const { isOpen, close, open } = useToggle();
-
- const [selectedEnv, setSelectedEnv] = useState();
-
- const { environments, boundEnvironments, error } = useAppSelector(
- ({ environments }) => environments,
- );
- const dispatch = useAppDispatch();
-
- const handleAddEnvironment = useCallback(
- (env: ClusterEnvironment) => {
- dispatch(createEnvironment(env))
- .unwrap()
- .then(() => {
- close();
- })
- .catch(noop);
- },
- [dispatch, close],
- );
-
- const handleEnvironmentDelete = useCallback(() => {
- if (selectedEnv) {
- dispatch(deleteEnvironment(selectedEnv))
- .unwrap()
- .then(() => {
- setSelectedEnv(undefined);
- })
- .catch(noop);
- }
- }, [selectedEnv, dispatch]);
-
- const handleDeleteModal = useCallback(() => {
- setSelectedEnv(undefined);
- }, []);
-
- const handleErrorClose = useCallback(() => {
- dispatch(clearEnvironmentError());
- }, [dispatch]);
-
- const handleModalClose = useCallback(() => {
- dispatch(clearEnvironmentError());
- close();
- }, [dispatch, close]);
-
- const handleDeleteEnv = useCallback(
- (id: string) => {
- if (environments[id]) {
- setSelectedEnv(environments[id]);
- }
- },
- [environments],
- );
-
- useEffect(() => {
- dispatch(getAllEnvironments());
- }, [dispatch]);
-
- return (
-
-
-
- Environments
-
-
-
-
-
- {Object.keys(environments).length ? (
-
- ) : (
-
-
-
- You don't have any environments defined
-
-
- Create and add environments for your application development.
-
-
- )}
-
-
-
- {selectedEnv && (
-
- )}
-
- );
-};
-
-export default Environments;
-
-const Header = styled(Row)`
- margin: 40px;
- justify-content: space-between;
-`;
-
-const HeadingContainer = styled(Column)`
- gap: 8px;
-
- ${LearnMore} {
- color: ${VOLCANIC_SAND};
- }
-`;
-
-const DisplayContainer = styled(Column)`
- width: 100%;
- align-items: center;
- margin-top: 110px;
- gap: 16px;
-`;
diff --git a/containers/GitAccount/GitAccount.styled.ts b/containers/GitAccount/GitAccount.styled.ts
deleted file mode 100644
index 1a8a3b96..00000000
--- a/containers/GitAccount/GitAccount.styled.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import styled from 'styled-components';
-
-import Column from '@/components/Column/Column';
-import LearnMore from '@/components/LearnMore/LearnMore';
-import Row from '@/components/Row/Row';
-import { TRAFFIC_WHITE, VOLCANIC_SAND, WASH_ME } from '@/constants/colors';
-import { media } from '@/utils/media';
-
-export const Form = styled.form`
- display: flex;
- flex-direction: column;
- flex: 1;
- padding: 32px 40px;
- gap: 24px;
- overflow-y: auto;
-`;
-
-export const FormFooter = styled(Row)`
- padding: 16px 24px;
- border-top: 2px solid ${WASH_ME};
- justify-content: flex-end;
- gap: 16px;
-`;
-
-export const FormHeader = styled(Row)`
- padding: 16px 24px;
- border-bottom: 2px solid ${WASH_ME};
- justify-content: space-between;
- align-items: center;
- height: 40px;
-`;
-
-export const Header = styled(Row)`
- justify-content: space-between;
-`;
-
-export const HeadingContainer = styled(Column)`
- gap: 8px;
-
- ${LearnMore} {
- color: ${VOLCANIC_SAND};
- }
-`;
-
-export const GitFieldsContainer = styled(Column)`
- gap: 12px;
- flex: 1;
-
- ${media.greaterThan('sm')`
- flex-direction: row;
- `}
-`;
-
-export const GitUserField = styled(Column)`
- width: 100%;
- max-width: 312px;
-`;
-
-export const GitUserFieldInput = styled(Row)`
- background-color: ${TRAFFIC_WHITE};
- border-radius: 4px;
- color: ${({ theme }) => theme.colors.volcanicSand};
- height: 20px;
- margin-top: 8px;
- padding: 8px 12px;
- overflow: ellipsis;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-`;
diff --git a/containers/GitAccount/GitAccount.tsx b/containers/GitAccount/GitAccount.tsx
deleted file mode 100644
index 47b20a45..00000000
--- a/containers/GitAccount/GitAccount.tsx
+++ /dev/null
@@ -1,199 +0,0 @@
-'use client';
-import React, { FunctionComponent, useCallback, useMemo } from 'react';
-import { useForm } from 'react-hook-form';
-
-import {
- Form,
- FormFooter,
- FormHeader,
- GitFieldsContainer,
- GitUserField,
- GitUserFieldInput,
- Header,
- HeadingContainer,
-} from './GitAccount.styled';
-
-import Typography from '@/components/Typography/Typography';
-import LearnMore from '@/components/LearnMore/LearnMore';
-import { useAppSelector } from '@/redux/store';
-import FormContainer from '@/components/FormContainer/FormContainer';
-import Column from '@/components/Column/Column';
-import Row from '@/components/Row/Row';
-import Button from '@/components/Button/Button';
-import useToggle from '@/hooks/useToggle';
-import GitProviderLabel from '@/components/GitProviderLabel/GitProviderLabel';
-import { GitProvider } from '@/types';
-import { EXCLUSIVE_PLUM, VOLCANIC_SAND } from '@/constants/colors';
-import ControlledPassword from '@/components/controlledFields/ControlledPassword';
-import { GIT_PROVIDER_DISPLAY_NAME } from '@/constants';
-import Tooltip from '@/components/Tooltip/Tooltip';
-import ControlledTextField from '@/components/controlledFields/ControlledTextField/ControlledTextField';
-
-type GitAccountFields = {
- gitToken?: string;
- gitProvider?: string;
- gitOrg?: string;
- gitRepo?: string;
-};
-
-const GitAccount: FunctionComponent = () => {
- const { managementCluster, githubUser, gitlabUser } = useAppSelector(({ api, git }) => ({
- ...api,
- ...git,
- }));
-
- const { isOpen, toggle } = useToggle();
-
- const {
- control,
- handleSubmit,
- formState: { errors },
- reset,
- } = useForm({
- values: {
- gitToken: managementCluster?.gitAuth.gitToken,
- gitProvider: managementCluster?.gitProvider,
- gitOrg: managementCluster?.gitAuth.gitOwner,
- gitRepo: managementCluster?.gitHost,
- },
- mode: 'onSubmit',
- });
-
- const handleFormSubmit = useCallback(() => {
- // TODO: Handle submit
- }, []);
-
- const handleEdit = useCallback(() => {
- reset(undefined, { keepErrors: false, keepDirty: false });
- toggle();
- }, [reset, toggle]);
-
- const gitUserName = useMemo(
- () => githubUser?.login || gitlabUser?.name,
- [githubUser, gitlabUser],
- );
-
- const gitLabel = useMemo(
- () => GIT_PROVIDER_DISPLAY_NAME[managementCluster?.gitProvider as GitProvider],
- [managementCluster?.gitProvider],
- );
-
- const showTooltip = useMemo(() => (gitUserName?.length ?? 0) > 22, [gitUserName]);
-
- return (
-
- );
-};
-
-export default GitAccount;
diff --git a/containers/GitOpsCatalog/GitOpsCatalog.styled.ts b/containers/GitOpsCatalog/GitOpsCatalog.styled.ts
deleted file mode 100644
index bce7c5c9..00000000
--- a/containers/GitOpsCatalog/GitOpsCatalog.styled.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-'use client';
-import styled from 'styled-components';
-
-import Row from '@/components/Row/Row';
-import Column from '@/components/Column/Column';
-
-export const CardsContainer = styled(Row)`
- flex-wrap: wrap;
- gap: 16px;
-`;
-
-export const Container = styled(Row)`
- height: calc(100% - 80px);
-`;
-
-export const Content = styled.div`
- height: calc(100% - 30px);
- padding: 0 24px;
- width: 100%;
-`;
-
-export const Filter = styled.div`
- background: ${({ theme }) => theme.colors.white};
- border-width: 1px 1px 0px 1px;
- border-style: solid;
- border-color: ${({ theme }) => theme.colors.pastelLightBlue};
- border-radius: 8px;
- height: 100vh;
- overflow: auto;
- padding: 24px 24px 0 24px;
- width: 266px;
-`;
-
-export const CardsByCategory = styled(Column)`
- gap: 24px;
-`;
diff --git a/containers/GitOpsCatalog/GitOpsCatalog.tsx b/containers/GitOpsCatalog/GitOpsCatalog.tsx
deleted file mode 100644
index 8bbcd246..00000000
--- a/containers/GitOpsCatalog/GitOpsCatalog.tsx
+++ /dev/null
@@ -1,182 +0,0 @@
-import React, { FunctionComponent, useCallback, useMemo } from 'react';
-import { useSession } from 'next-auth/react';
-import { useForm } from 'react-hook-form';
-import NextLink from 'next/link';
-import sortBy from 'lodash/sortBy';
-import FormControlLabel from '@mui/material/FormControlLabel';
-import FormGroup from '@mui/material/FormGroup';
-
-import { CardsContainer, Container, Content, Filter } from './GitOpsCatalog.styled';
-
-import Checkbox from '@/components/Checkbox/Checkbox';
-import Typography from '@/components/Typography/Typography';
-import GitOpsCatalogCard from '@/components/GitOpsCatalogCard/GitOpsCatalogCard';
-import GitopsAppModal from '@/components/GitOpsAppModal/GitOpsAppModal';
-import useModal from '@/hooks/useModal';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { installGitOpsApp } from '@/redux/thunks/applications.thunk';
-import { AppCategory, GitOpsCatalogApp } from '@/types/applications';
-import { VOLCANIC_SAND } from '@/constants/colors';
-import {
- addCategory,
- removeCategory,
- setSelectedCatalogApp,
-} from '@/redux/slices/applications.slice';
-
-const STATIC_HELP_CARD: GitOpsCatalogApp = {
- name: '',
- display_name: 'Can’t find what you need?',
- image_url: 'https://assets.kubefirst.com/console/help.png',
-};
-
-interface GitOpsCatalogProps {
- catalogApplications: GitOpsCatalogApp[];
-}
-
-const GitOpsCatalog: FunctionComponent = ({ catalogApplications }) => {
- const {
- appsQueue,
- gitOpsCatalogApps,
- selectedCategories,
- clusterApplications,
- selectedCatalogApp,
- filter,
- } = useAppSelector(({ applications }) => applications);
-
- const { data: session } = useSession();
-
- const { isOpen, openModal, closeModal } = useModal();
-
- const {
- control,
- formState: { isValid },
- getValues,
- reset,
- } = useForm();
-
- const dispatch = useAppDispatch();
-
- const handleCategoryClick = useCallback(
- (category: AppCategory) => {
- const isCategorySelected = selectedCategories.includes(category);
-
- if (isCategorySelected) {
- dispatch(removeCategory(category));
- } else {
- dispatch(addCategory(category));
- }
- },
- [selectedCategories, dispatch],
- );
-
- const handleAddApp = useCallback(() => {
- const values = getValues();
-
- dispatch(
- installGitOpsApp({
- values,
- user: (session?.user?.email as string) || 'kbot',
- }),
- );
- reset();
- closeModal();
- }, [dispatch, closeModal, getValues, reset, session]);
-
- const handleSelectedApp = useCallback(
- (app: GitOpsCatalogApp) => {
- dispatch(setSelectedCatalogApp(app));
-
- if (app.secret_keys?.length || app.config_keys?.length) {
- openModal();
- } else {
- handleAddApp();
- }
- },
- [dispatch, handleAddApp, openModal],
- );
-
- const uninstalledCatalogApps = useMemo(
- () =>
- gitOpsCatalogApps.filter((app) => !clusterApplications.map((s) => s.name).includes(app.name)),
- [clusterApplications, gitOpsCatalogApps],
- );
-
- const sortedAvailableCategories = useMemo(
- () =>
- uninstalledCatalogApps.reduce((previous, current) => {
- if (current.category && !previous.includes(current.category)) {
- previous.push(current.category);
- }
- return sortBy(previous);
- }, []),
- [uninstalledCatalogApps],
- );
-
- return (
-
-
-
- Category
-
- {sortedAvailableCategories.map((category) => (
-
- handleCategoryClick(category)} />}
- label={
-
- {category}
-
- }
- sx={{ ml: 0 }}
- />
-
- ))}
-
-
-
- {catalogApplications.map((app) => (
- handleSelectedApp(app)}
- isInstalling={appsQueue.includes(app.name)}
- isDisabled={!filter.cluster}
- />
- ))}
-
- <>
- To suggest an open source app that installs to your cluster, discuss your idea via an{' '}
-
- issue
-
- . Learn how you can do this on our{' '}
-
- Contributing file
-
- .
-
-
- Alternatively contact us via our{' '}
-
- Slack Community
- {' '}
- in the #helping-hands or #contributors channels.
- >
-
-
-
- {isOpen && selectedCatalogApp && (
-
- )}
-
- );
-};
-
-export default GitOpsCatalog;
diff --git a/containers/Header/Header.tsx b/containers/Header/Header.tsx
index 65c9332c..18333a34 100644
--- a/containers/Header/Header.tsx
+++ b/containers/Header/Header.tsx
@@ -1,7 +1,5 @@
'use client';
import React, { FunctionComponent, useMemo } from 'react';
-import { useSession } from 'next-auth/react';
-import { signOut } from 'next-auth/react';
import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined';
import MenuBookOutlinedIcon from '@mui/icons-material/MenuBookOutlined';
import List from '@mui/material/List';
@@ -9,31 +7,20 @@ import ListItem from '@mui/material/ListItem';
import { ClickAwayListener, ListItemButton } from '@mui/material';
import Image from 'next/image';
import VideogameAssetOutlinedIcon from '@mui/icons-material/VideogameAssetOutlined';
-import LogoutIcon from '@mui/icons-material/Logout';
import { BsSlack } from 'react-icons/bs';
-import { Avatar, Container, Menu, ProfileMenu } from './Header.styled';
+import { Container, Menu } from './Header.styled';
import { noop } from '@/utils/noop';
import Youtube from '@/assets/youtube-dark.svg';
import { useAppSelector } from '@/redux/store';
import Typography from '@/components/Typography/Typography';
-import { ECHO_BLUE, PRIMARY, TRAFFIC_WHITE, VOLCANIC_SAND } from '@/constants/colors';
+import { ECHO_BLUE, PRIMARY, VOLCANIC_SAND } from '@/constants/colors';
import useToggle from '@/hooks/useToggle';
import useFeatureFlag from '@/hooks/useFeatureFlag';
import { FeatureFlag } from '@/types/config';
import { DOCS_LINK } from '@/constants';
-function stringAvatar(name?: string | null) {
- return {
- sx: {
- bgcolor: TRAFFIC_WHITE,
- color: '#94A3B8',
- },
- children: `${name && name[0]}`,
- };
-}
-
export interface HeaderProps {
handleOpenFlappy: typeof noop;
handleOpenKubefirstModal: typeof noop;
@@ -41,9 +28,7 @@ export interface HeaderProps {
const Header: FunctionComponent = ({ handleOpenFlappy, handleOpenKubefirstModal }) => {
const { isOpen: isHelpMenuOpen, open, close } = useToggle();
- const { isOpen: isProfileMenuOpen, open: openProfileMenu, close: closeProfileMenu } = useToggle();
- const { data: session } = useSession();
const { isClusterZero } = useAppSelector(({ api, config }) => ({
isClusterZero: config.isClusterZero,
managementCluster: api.managementCluster,
@@ -126,37 +111,6 @@ const Header: FunctionComponent = ({ handleOpenFlappy, handleOpenKu
)}
>
)}
- {session?.user && (
-
- )}
- {isProfileMenuOpen && (
-
-
-
- signOut()}
- >
-
-
-
- Logout
-
-
-
-
-
-
- )}
);
};
diff --git a/containers/Layout/Layout.tsx b/containers/Layout/Layout.tsx
index 05041b62..30bb5a38 100644
--- a/containers/Layout/Layout.tsx
+++ b/containers/Layout/Layout.tsx
@@ -1,52 +1,34 @@
'use client';
import React, { PropsWithChildren, useEffect, useState } from 'react';
-import { Typography } from '@mui/material';
import KubefirstContent from '../KubefirstContent/KubefirstContent';
-import { Link, Container, Content } from './Layout.styled';
+import { Container, Content } from './Layout.styled';
import Header from '@/containers/Header/Header';
import Navigation from '@/containers/Navigation/Navigation';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { getClusters } from '@/redux/thunks/api.thunk';
-import { License } from '@/types/subscription';
-import { setLicense } from '@/redux/slices/subscription.slice';
+import { useAppDispatch } from '@/redux/store';
import { EnvironmentVariables, FeatureFlag } from '@/types/config';
import { setFlags } from '@/redux/slices/featureFlags.slice';
import { setConfigValues } from '@/redux/slices/config.slice';
import FlappyKray from '@/components/FlappyKRay/FlappyKRay';
import useModal from '@/hooks/useModal';
-import {
- selectHasLicenseKey,
- selectIsLicenseActive,
- selectPendingInvoice,
-} from '@/redux/selectors/subscription.selector';
-import Banner from '@/components/Banner/Banner';
-import { WHITE } from '@/constants/colors';
-import { setIsBannerOpen } from '@/redux/slices/settings.slice';
export interface LayoutProps extends PropsWithChildren {
- license: License;
envVariables: EnvironmentVariables;
featureFlags: Record;
}
-export function Layout({ children, envVariables, featureFlags, license }: LayoutProps) {
+export function Layout({ children, envVariables, featureFlags }: LayoutProps) {
const [loadFlags, setLoadFlags] = useState(false);
const { isOpen, openModal, closeModal } = useModal();
+ const dispatch = useAppDispatch();
const {
isOpen: isModalContentOpen,
openModal: openModalContent,
closeModal: closeModalContent,
} = useModal();
- const dispatch = useAppDispatch();
- const isBannerOpen = useAppSelector(({ settings }) => settings.isBannerOpen);
- const hasLicenseKey = useAppSelector(selectHasLicenseKey());
- const isLicenseActive = useAppSelector(selectIsLicenseActive());
- const pendingInvoice = useAppSelector(selectPendingInvoice());
-
const handleOpenFlappy = () => {
openModal();
};
@@ -55,21 +37,11 @@ export function Layout({ children, envVariables, featureFlags, license }: Layout
openModalContent();
};
- const handleCloseBanner = () => {
- dispatch(setIsBannerOpen(false));
- };
-
useEffect(() => {
setLoadFlags(true);
dispatch(setFlags(featureFlags));
dispatch(setConfigValues(envVariables));
- dispatch(setLicense(license));
- dispatch(getClusters());
- }, [dispatch, envVariables, featureFlags, license, loadFlags]);
-
- useEffect(() => {
- dispatch(setIsBannerOpen(hasLicenseKey && !isLicenseActive));
- }, [dispatch, hasLicenseKey, isLicenseActive]);
+ }, [dispatch, envVariables, featureFlags, loadFlags]);
return (
@@ -78,18 +50,6 @@ export function Layout({ children, envVariables, featureFlags, license }: Layout
handleOpenKubefirstModal={handleOpenKubefirstModal}
/>
- {isBannerOpen && (
-
-
- Your payment was declined. Please{' '}
-
- update your billing information
- {' '}
- to continue to use the kubefirst UI to manage your physical clusters. Alternatively,
- manage your physical clusters directly in your GitOps repository on a Free Plan.
-
-
- )}
`
- border-radius: 8px;
- width: auto;
-
- ${({ hasMargin }) =>
- hasMargin &&
- `
- &:last-child {
- margin-top: 32px;
- }
- `}
-`;
-
-export const BottomFormContainer = styled(FormContainer)<{ hasMargin: boolean }>`
- align-items: center;
- border-radius: 0 0 8px 8px;
- border-top: 1px solid #e5e5e5;
- display: flex;
- justify-content: space-between;
- flex-direction: row;
- width: 100%;
-
- & > div {
- align-items: center;
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- width: 100%;
- }
-`;
-
-export const UList = styled.ul`
- padding-left: 20px;
-`;
-
-export const CancelContainer = styled.div`
- align-items: flex-start;
- background: #fff7ed;
- border: 1px solid #ffedd5;
- border-radius: 4px;
- display: flex;
- gap: 8px;
- margin-bottom: 8px;
- padding: 16px;
-`;
diff --git a/containers/License/License.tsx b/containers/License/License.tsx
deleted file mode 100644
index dfece71e..00000000
--- a/containers/License/License.tsx
+++ /dev/null
@@ -1,148 +0,0 @@
-import React, { FunctionComponent, useMemo } from 'react';
-import moment from 'moment';
-import { Box, CircularProgress } from '@mui/material';
-import { FieldValues, useFormContext } from 'react-hook-form';
-import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
-
-import { BottomFormContainer, CancelContainer, FormContainer, UList } from './License.styled';
-
-import { COAL_MINE, EXCLUSIVE_PLUM, ORANGEALICIOUS, VOLCANIC_SAND } from '@/constants/colors';
-import Button from '@/components/Button/Button';
-import LearnMore from '@/components/LearnMore/LearnMore';
-import Typography from '@/components/Typography/Typography';
-import { useAppSelector } from '@/redux/store';
-import ControlledPassword from '@/components/controlledFields/ControlledPassword';
-import { selectHasLicenseKey, selectRequestByType } from '@/redux/selectors/subscription.selector';
-
-export interface LicenseProps {
- handleActivateLicense: (licenseKey: string) => void;
- handleCancelSubscription: () => void;
-}
-
-const License: FunctionComponent = ({
- handleActivateLicense,
- handleCancelSubscription,
-}) => {
- const { isLoading, license, error } = useAppSelector(({ subscription }) => subscription);
-
- const hasLicenseKey = useAppSelector(selectHasLicenseKey());
- const cancelRequest = useAppSelector(selectRequestByType('cancel'));
-
- const formattedLicenseKey = useMemo(
- () =>
- license?.licenseKey &&
- `${license?.licenseKey.slice(0, 4).toUpperCase()}************************************`,
- [license?.licenseKey],
- );
-
- const {
- control,
- handleSubmit,
- formState: { isValid },
- } = useFormContext();
-
- const onSubmit = async ({ licenseKey }: FieldValues) => {
- handleActivateLicense(licenseKey);
- };
-
- return (
-
-
-
- {!hasLicenseKey && (
-
- )}
-
- }
- >
- {`You are on a ${
- license?.plan?.name || 'Community'
- } Plan`}
- {hasLicenseKey ? (
- <>
-
- License key
-
-
- {formattedLicenseKey}
-
- >
- ) : (
-
- )}
-
- {hasLicenseKey && (
- <>
-
-
-
-
- }
- >
-
- Cancel my subscription
-
- {!!cancelRequest?.id && (
-
-
-
- {`Your request to cancel your subscription was submitted ${moment(
- cancelRequest.createdAt,
- ).format('DD MMM YYYY, HH:MM:SS')}`}
-
-
- )}
-
-
- What to expect:
-
- You will be downgraded to a Free Plan.
-
- You will no longer be able to view and manage any physical clusters you may have
- provisioned, this will only by possible via the kubefirst CLI.
-
- We will send you an email confirming that your account has been downgraded.
- You will still have access until the end of your current billing cycle.
-
-
-
- >
- )}
-
- );
-};
-
-export default License;
diff --git a/containers/Navigation/Navigation.tsx b/containers/Navigation/Navigation.tsx
index 36cfab08..c9c424fd 100644
--- a/containers/Navigation/Navigation.tsx
+++ b/containers/Navigation/Navigation.tsx
@@ -1,25 +1,11 @@
'use client';
-import React, { FunctionComponent, useCallback, useEffect, useMemo, useState } from 'react';
+import React, { FunctionComponent, useCallback, useEffect, useState } from 'react';
import { usePathname } from 'next/navigation';
-import { BsSlack } from 'react-icons/bs';
-// import { FaGitAlt } from 'react-icons/fa';
-import ScatterPlotIcon from '@mui/icons-material/ScatterPlot';
-import GridViewOutlinedIcon from '@mui/icons-material/GridViewOutlined';
-import CollectionsOutlinedIcon from '@mui/icons-material/CollectionsOutlined';
-import ReceiptLongIcon from '@mui/icons-material/ReceiptLong';
-import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined';
-import StarBorderOutlinedIcon from '@mui/icons-material/StarBorderOutlined';
-import NavigationComponent, { FooterItem } from '@/components/Navigation/Navigation';
+import NavigationComponent from '@/components/Navigation/Navigation';
import { useAppSelector } from '@/redux/store';
import { noop } from '@/utils/noop';
import { selectConfig } from '@/redux/selectors/config.selector';
-import useFeatureFlag from '@/hooks/useFeatureFlag';
-import { InstallationType } from '@/types/redux';
-import { FeatureFlag } from '@/types/config';
-import { ASMANI_SKY } from '@/constants/colors';
-import { SaasPlans } from '@/types/subscription';
-import { DOCS_LINK, Route } from '@/constants';
export interface NavigationProps {
handleOpenFlappy: typeof noop;
@@ -33,98 +19,7 @@ const Navigation: FunctionComponent = ({
const [domLoaded, setDomLoaded] = useState(false);
const asPath = usePathname();
- const { kubefirstVersion, isClusterZero } = useAppSelector(selectConfig());
- const { managementCluster } = useAppSelector(({ api }) => ({
- managementCluster: api.managementCluster,
- }));
- const license = useAppSelector(({ subscription }) => subscription.license);
-
- const { isEnabled: isMultiClusterEnabled } = useFeatureFlag(FeatureFlag.MULTICLUSTER_MANAGEMENT);
- const { isEnabled: isSubscriptionEnabled } = useFeatureFlag(FeatureFlag.SAAS_SUBSCRIPTION);
-
- const routes = useMemo(
- () =>
- [
- {
- icon: ,
- path: Route.CLUSTER_MANAGEMENT,
- title: 'Cluster Management',
- isEnabled:
- isMultiClusterEnabled &&
- !isClusterZero &&
- managementCluster?.cloudProvider !== InstallationType.LOCAL,
- },
- {
- icon: ,
- path: Route.APPLICATIONS,
- title: 'Applications',
- isEnabled: !isClusterZero,
- },
- {
- icon: ,
- path: Route.ENVIRONMENTS,
- title: 'Environments',
- isEnabled: !isClusterZero && managementCluster?.cloudProvider !== InstallationType.LOCAL,
- },
- {
- icon: ,
- path: Route.SUBSCRIPTION,
- title: 'Subscription',
- group: 'Admin settings',
- groupOrder: 2,
- isEnabled: !isClusterZero && isSubscriptionEnabled,
- },
- // {
- // icon: ,
- // path: Route.GIT_ACCOUNT,
- // title: 'Git account',
- // group: 'Admin settings',
- // groupOrder: 3,
- // isEnabled: !isClusterZero && managementCluster?.cloudProvider !== InstallationType.LOCAL,
- // },
- ].filter(({ isEnabled }) => isEnabled),
- [isMultiClusterEnabled, isClusterZero, managementCluster?.cloudProvider, isSubscriptionEnabled],
- );
-
- const nextLicenseUpgradeTitle = useMemo(() => {
- if (!license?.licenseKey) {
- return 'Upgrade to Pro';
- }
-
- if (license?.plan?.name === SaasPlans.Pro) {
- return 'Upgrade to Enterprise';
- }
-
- return undefined;
- }, [license?.licenseKey, license?.plan?.name]);
-
- const footerItems = useMemo(
- () =>
- isSubscriptionEnabled && !isClusterZero
- ? nextLicenseUpgradeTitle && [
- {
- icon: ,
- path: Route.SUBSCRIPTION_PLANS,
- title: nextLicenseUpgradeTitle,
- color: ASMANI_SKY,
- },
- ]
- : [
- {
- icon: ,
- path: DOCS_LINK,
- title: 'Documentation',
- color: '',
- },
- {
- icon: ,
- path: 'http://konstruct.io/slack',
- title: 'Slack',
- color: '',
- },
- ],
- [isClusterZero, isSubscriptionEnabled, nextLicenseUpgradeTitle],
- );
+ const { kubefirstVersion } = useAppSelector(selectConfig());
const handleIsActiveItem = useCallback(
(route: string) => {
@@ -150,12 +45,11 @@ const Navigation: FunctionComponent = ({
}
- isSubscriptionEnabled={isSubscriptionEnabled}
+ footerItems={[]}
/>
);
};
diff --git a/containers/Provision/Provision.tsx b/containers/Provision/Provision.tsx
index d7c7d761..0382334c 100644
--- a/containers/Provision/Provision.tsx
+++ b/containers/Provision/Provision.tsx
@@ -20,18 +20,17 @@ import ErrorBanner from '@/components/ErrorBanner/ErrorBanner';
import Button from '@/components/Button/Button';
import {
clearError,
- setError,
setInstallType,
setInstallValues,
setInstallationStep,
} from '@/redux/slices/installation.slice';
import { clearClusterState, clearValidation } from '@/redux/slices/api.slice';
import { useAppDispatch, useAppSelector } from '@/redux/store';
-import { createCluster, resetClusterProgress } from '@/redux/thunks/api.thunk';
+import { createCluster, getCloudRegions, resetClusterProgress } from '@/redux/thunks/api.thunk';
import { useInstallation } from '@/hooks/useInstallation';
import { InstallValues, InstallationType } from '@/types/redux';
import { GitProvider } from '@/types';
-import { AUTHENTICATION_ERROR_MSG, DEFAULT_CLOUD_INSTANCE_SIZES, DOCS_LINK } from '@/constants';
+import { DEFAULT_CLOUD_INSTANCE_SIZES, DOCS_LINK } from '@/constants';
import { useQueue } from '@/hooks/useQueue';
import LearnMore from '@/components/LearnMore/LearnMore';
@@ -174,6 +173,13 @@ const Provision: FunctionComponent = () => {
if (isValid) {
dispatch(setInstallValues(values));
+ // this step validates the authentication provided
+ if (isAuthStep) {
+ return dispatch(
+ getCloudRegions({ installType: installType as InstallationType, values, validate: true }),
+ );
+ }
+
if (isSetupStep) {
try {
await provisionCluster();
@@ -275,14 +281,6 @@ const Provision: FunctionComponent = () => {
href,
]);
- useEffect(() => {
- if (isAuthStep && isAuthenticationValid === false) {
- dispatch(setError({ error: AUTHENTICATION_ERROR_MSG }));
- } else if (isAuthStep && isAuthenticationValid) {
- handleGoNext();
- }
- }, [dispatch, handleGoNext, isAuthStep, isAuthenticationValid]);
-
useEffect(() => {
if (isMarketplace && installMethod) {
const [cloud] = installMethod.split('-') || [''];
diff --git a/containers/Subscription/Subscription.styled.ts b/containers/Subscription/Subscription.styled.ts
deleted file mode 100644
index d7776280..00000000
--- a/containers/Subscription/Subscription.styled.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { styled } from 'styled-components';
-
-import Column from '@/components/Column/Column';
-
-export const Container = styled(Column)`
- margin: 40px;
-`;
-
-export const PlansContainer = styled.div`
- align-items: center;
- display: flex;
- gap: 40px;
- height: 100%;
-`;
diff --git a/containers/Subscription/Subscription.tsx b/containers/Subscription/Subscription.tsx
deleted file mode 100644
index 18264404..00000000
--- a/containers/Subscription/Subscription.tsx
+++ /dev/null
@@ -1,152 +0,0 @@
-'use client';
-import React, { FunctionComponent, useEffect, useMemo } from 'react';
-import Box from '@mui/material/Box';
-import Tabs from '@mui/material/Tabs';
-import { FormProvider, useForm } from 'react-hook-form';
-
-import License from '../License/License';
-import CancelSubscription from '../CancelSubscription/CancelSubscription';
-import Billing from '../Billing/Billing';
-import ContactUs from '../ContactUsModal/ContactUsModal';
-
-import { Container, PlansContainer } from './Subscription.styled';
-
-import TabPanel, { Tab, a11yProps } from '@/components/Tab/Tab';
-import { BISCAY, VOLCANIC_SAND } from '@/constants/colors';
-import { useAppDispatch, useAppSelector } from '@/redux/store';
-import Typography from '@/components/Typography/Typography';
-import { setActiveTab } from '@/redux/slices/settings.slice';
-import { SettingsTab, SettingsTabMap } from '@/constants/setttings';
-import { Plan } from '@/types/plan';
-import { activateLicenseKey, validateLicenseKey } from '@/redux/thunks/subscription.thunk';
-import useModal from '@/hooks/useModal';
-import { SaasPlans } from '@/types/subscription';
-import { selectHasLicenseKey } from '@/redux/selectors/subscription.selector';
-import Pricing from '@/components/Pricing/Pricing';
-
-interface SubscriptionProps {
- activeTabParam?: string;
- plans: Array;
-}
-
-const Subscription: FunctionComponent = ({ activeTabParam, plans }) => {
- const dispatch = useAppDispatch();
- const { isOpen, closeModal, openModal } = useModal();
- const {
- isOpen: isContactUsModalOpen,
- closeModal: closeContactUsModal,
- openModal: openContactUsModal,
- } = useModal();
-
- const { activeTab, license, saasURL } = useAppSelector(({ settings, subscription, config }) => ({
- activeTab: settings.activeTab,
- license: subscription.license,
- saasURL: config.saasURL,
- }));
-
- const methods = useForm<{ licenseKey: string }>({
- mode: 'onChange',
- defaultValues: {
- licenseKey: license?.licenseKey || '',
- },
- });
-
- const currentPlanIndex = useMemo(
- () => plans.findIndex(({ name }) => name === license?.plan?.name),
- [license, plans],
- );
-
- const handleOnChangeTab = (event: React.SyntheticEvent, tabIndex: number) => {
- dispatch(setActiveTab(tabIndex));
- };
-
- const handleActivateLicense = (licenseKey: string) => {
- dispatch(activateLicenseKey(licenseKey)).then(() => dispatch(validateLicenseKey()));
- };
-
- const handleRedirectToSaas = (plan: string) => {
- if (plan === SaasPlans.Enterprise && hasLicenseKey) {
- openContactUsModal();
- } else {
- window.open(`${saasURL}?plan=${plan}`, '_blank');
- }
- };
-
- const isActivePlan = (plan: string): boolean => {
- if (!license?.licenseKey && plan === SaasPlans.Community) {
- return true;
- }
-
- return license?.plan?.name === plan;
- };
-
- const hasLicenseKey = useAppSelector(selectHasLicenseKey());
-
- useEffect(() => {
- if (activeTabParam) {
- dispatch(setActiveTab(SettingsTabMap[activeTabParam]));
- } else if (hasLicenseKey) {
- dispatch(setActiveTab(SettingsTab.LICENSE_KEY));
- }
- }, [activeTabParam, dispatch, hasLicenseKey]);
-
- return (
-
-
- Subscription
-
- <>
-
-
- Billing}
- {...a11yProps(SettingsTab.BILLING)}
- sx={{ textTransform: 'initial', marginRight: '24px' }}
- />
- License key}
- {...a11yProps(SettingsTab.LICENSE_KEY)}
- sx={{ textTransform: 'initial', marginRight: '24px' }}
- />
- Plans}
- {...a11yProps(SettingsTab.PLANS)}
- sx={{ textTransform: 'initial', marginRight: 0 }}
- />
-
-
-
-
-
-
-
-
-
-
-
-
- {plans.map((plan, index) => (
- index}
- isActive={isActivePlan(plan.name)}
- onClick={() => handleRedirectToSaas(plan.name)}
- />
- ))}
-
-
- >
-
-
-
- );
-};
-
-export default Subscription;
diff --git a/custom.d.ts b/custom.d.ts
index 5f20f8a6..10574166 100644
--- a/custom.d.ts
+++ b/custom.d.ts
@@ -157,3 +157,20 @@ declare module 'next-auth' {
groups: Array;
}
}
+
+declare namespace NodeJS {
+ export interface ProcessEnv {
+ readonly API_URL: string;
+ readonly CLUSTER_ID: string;
+ readonly CLUSTER_TYPE: string;
+ readonly DISABLE_TELEMETRY: string;
+ readonly INSTALL_METHOD: string;
+ readonly IS_CLUSTER_ZERO: string;
+ readonly DISABLE_AUTH: string;
+ readonly KUBEFIRST_VERSION: string;
+ readonly POSTHOG_KEY: string;
+ readonly CLIENT_ID: string;
+ readonly SECRET_ID: string;
+ readonly DOMAIN: string;
+ }
+}
diff --git a/environment.d.ts b/environment.d.ts
deleted file mode 100644
index 7964b145..00000000
--- a/environment.d.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-declare namespace NodeJS {
- export interface ProcessEnv {
- readonly API_URL: string;
- readonly CLUSTER_ID: string;
- readonly CLUSTER_TYPE: string;
- readonly DISABLE_TELEMETRY: string;
- readonly INSTALL_METHOD: string;
- readonly IS_CLUSTER_ZERO: string;
- readonly DISABLE_AUTH: string;
- readonly KUBEFIRST_VERSION: string;
- readonly POSTHOG_KEY: string;
- readonly CLIENT_ID: string;
- readonly SECRET_ID: string;
- readonly DOMAIN: string;
- readonly SAAS_URL: string;
- }
-}
diff --git a/hooks/__tests__/usePaywall.test.ts b/hooks/__tests__/usePaywall.test.ts
deleted file mode 100644
index 4a9dd664..00000000
--- a/hooks/__tests__/usePaywall.test.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import { renderHook } from '@testing-library/react';
-
-import usePaywall from '../usePaywall';
-// eslint-disable-next-line import/order
-import { SaasFeatures, SaasPlans } from '../../types/subscription';
-
-jest.mock('@/redux/store', () => ({
- useAppSelector: jest.fn(),
-}));
-
-import { useAppSelector } from '../../redux/store';
-
-describe('usePaywall', () => {
- beforeEach(() => {
- jest.clearAllMocks();
- });
-
- it('should return the correct plan', () => {
- const mockState = {
- api: { clusterMap: {} },
- subscription: {
- license: { plan: { name: SaasPlans.Pro }, is_active: true, clusters: [] },
- },
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.plan).toBe(SaasPlans.Pro);
- });
-
- it('should return active clusters', () => {
- const activeClusters = [
- { id: 1, isActive: true },
- { id: 2, isActive: true },
- ];
-
- const mockState = {
- api: { clusterMap: {} },
- subscription: {
- license: { plan: { name: SaasPlans.Pro }, is_active: true, clusters: activeClusters },
- },
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.activeClusters).toEqual(activeClusters);
- });
-
- it('should return false if the feature is not available', () => {
- const mockState = {
- api: { clusterMap: {} },
- subscription: {
- license: { plan: { name: SaasPlans.Pro, features: [] }, is_active: true, clusters: [] },
- },
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.canUseFeature('some_feature')).toBe(false);
- });
-
- describe('pro plan', () => {
- it('should return true if the feature is available', () => {
- const featureCode = 'some_feature';
- const mockState = {
- api: { clusterMap: {} },
- subscription: {
- license: {
- plan: { name: SaasPlans.Pro, features: [{ code: featureCode }] },
- is_active: true,
- clusters: [],
- },
- },
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.canUseFeature(featureCode)).toBe(true);
- });
-
- it('should allow feature if cluster limit is not exceeded', () => {
- const activeClusters = [
- { id: 1, isActive: true },
- { id: 2, isActive: true },
- ];
- const featureCode = SaasFeatures.WorkloadClustersLimit;
- const mockState = {
- api: { clusterMap: {} },
- subscription: {
- license: {
- plan: {
- name: SaasPlans.Pro,
- features: [{ code: featureCode, data: { limit: 3 } }],
- },
- is_active: true,
- clusters: activeClusters,
- },
- },
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.canUseFeature(featureCode)).toBe(true);
- });
-
- it('should not allow feature if cluster limit has exceeded', () => {
- const activeClusters = [
- { id: 1, isActive: true },
- { id: 2, isActive: true },
- { id: 2, isActive: true },
- { id: 2, isActive: true },
- ];
- const featureCode = SaasFeatures.WorkloadClustersLimit;
- const mockState = {
- api: { clusterMap: {} },
- subscription: {
- license: {
- plan: {
- name: SaasPlans.Pro,
- features: [{ code: featureCode, data: { limit: 3 } }],
- },
- is_active: true,
- clusters: activeClusters,
- },
- },
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.canUseFeature(featureCode)).toBe(false);
- });
- });
-
- describe('community plan', () => {
- it('should enforce cluster limit for Community plan without license key', () => {
- const clusterMap = {
- cluster1: { id: 1 },
- cluster2: { id: 2 },
- cluster3: { id: 3 },
- cluster4: { id: 4 },
- };
-
- const mockState = {
- api: { clusterMap },
- subscription: {},
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.canUseFeature(SaasFeatures.WorkloadClustersLimit)).toBe(false);
- });
-
- it('should allow use feature for Community plan without license key when the clusters are less than 3', () => {
- const clusterMap = {
- cluster1: { id: 1 },
- cluster2: { id: 2 },
- draft: { id: 3 },
- };
-
- const mockState = {
- api: { clusterMap },
- subscription: {},
- };
-
- (useAppSelector as jest.Mock).mockImplementation((selector) => selector(mockState));
-
- const { result } = renderHook(() => usePaywall());
- expect(result.current.canUseFeature(SaasFeatures.WorkloadClustersLimit)).toBe(true);
- });
- });
-});
diff --git a/hooks/usePaywall.ts b/hooks/usePaywall.ts
deleted file mode 100644
index bac2b009..00000000
--- a/hooks/usePaywall.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { useMemo } from 'react';
-
-import { useAppSelector } from '@/redux/store';
-import { SaasFeatures, SaasPlans } from '@/types/subscription';
-
-export const CLUSTERS_LIMIT_FALLBACK: { [key: string]: number } = {
- [SaasPlans.Community]: 3,
- [SaasPlans.Pro]: 10,
- [SaasPlans.Enterprise]: Infinity,
-};
-
-export default function usePaywall() {
- const { clusterMap, license, plan } = useAppSelector(({ api, subscription }) => ({
- clusterMap: api.clusterMap,
- license: subscription.license,
- plan: subscription.license?.plan?.name,
- }));
-
- const canUseFeature = (featureCode: string): boolean => {
- if (license?.plan && license?.is_active) {
- const feature = license.plan.features.find(({ code }) => code === featureCode);
-
- if (featureCode === SaasFeatures.WorkloadClustersLimit) {
- const clusterLimit = feature?.data.limit || CLUSTERS_LIMIT_FALLBACK[plan as string];
-
- return !!activeClusters && clusterLimit > activeClusters.length;
- }
-
- return !!feature;
- }
-
- if (!license?.licenseKey) {
- // Gets and checks number of clusters to allow workload creation
- return (
- Object.keys(clusterMap).filter((clusterKey) => {
- const { status } = clusterMap[clusterKey];
- return clusterKey != 'draft' && status != 'deleted';
- }).length < CLUSTERS_LIMIT_FALLBACK[SaasPlans.Community]
- );
- }
-
- return false;
- };
-
- const activeClusters = useMemo(
- () => license?.clusters?.filter(({ isActive }) => isActive),
- [license?.clusters],
- );
-
- return {
- canUseFeature,
- activeClusters,
- plan,
- };
-}
diff --git a/hooks/usePhysicalClustersPermission.ts b/hooks/usePhysicalClustersPermission.ts
deleted file mode 100644
index c5538cfe..00000000
--- a/hooks/usePhysicalClustersPermission.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { useCallback, useMemo } from 'react';
-
-import { useAppSelector } from '@/redux/store';
-import { InstallationType } from '@/types/redux';
-import { selectFeatureFlags } from '@/redux/selectors/featureFlags.selector';
-import { FeatureFlag } from '@/types/config';
-
-export function usePhysicalClustersPermissions(installationType?: InstallationType) {
- const { flags } = useAppSelector(selectFeatureFlags());
- const canProvisionAwsPhysicalClusters = flags[FeatureFlag.PROVISION_AWS_PYHS_CLUSTERS];
- const canProvisionDOPhysicalClusters = flags[FeatureFlag.PROVISION_DO_PYHS_CLUSTERS];
- const canProvisionGCPPhysicalClusters = flags[FeatureFlag.PROVISION_GCP_PYHS_CLUSTERS];
- const canProvisionVultrPhysicalClusters = flags[FeatureFlag.PROVISION_VULTR_PYHS_CLUSTERS];
-
- // check if user has permission to provision physical clusters based on cloud provider,
- // otherwise default to true if no feature flag check
- const physicalClustersPermission = useMemo(
- (): Record => ({
- [InstallationType.AWS]: canProvisionAwsPhysicalClusters,
- [InstallationType.DIGITAL_OCEAN]: canProvisionDOPhysicalClusters,
- [InstallationType.GOOGLE]: canProvisionGCPPhysicalClusters,
- [InstallationType.VULTR]: canProvisionVultrPhysicalClusters,
- [InstallationType.CIVO]: true,
- [InstallationType.LOCAL]: true,
- [InstallationType.AKAMAI]: true,
- }),
- [
- canProvisionAwsPhysicalClusters,
- canProvisionDOPhysicalClusters,
- canProvisionGCPPhysicalClusters,
- canProvisionVultrPhysicalClusters,
- ],
- );
-
- const getHasPermission = useCallback(() => {
- if (!installationType) {
- return false;
- }
-
- return installationType ? physicalClustersPermission[installationType] : false;
- }, [physicalClustersPermission, installationType]);
-
- // have to pass a function that fetches permissions since i am unable to pass a simple boolean from
- // physical clusters permissions indexed by installation type
- // encountered error - TypeError: getSnapshot is not a function
- return { hasPermissions: getHasPermission() };
-}
diff --git a/hooks/useQueue/queue.provider.tsx b/hooks/useQueue/queue.provider.tsx
index 9a9145bd..f31da909 100644
--- a/hooks/useQueue/queue.provider.tsx
+++ b/hooks/useQueue/queue.provider.tsx
@@ -18,7 +18,7 @@ import { getClusters } from '@/redux/thunks/api.thunk';
import { RESERVED_DRAFT_CLUSTER_NAME } from '@/constants';
const QueueProvider: FunctionComponent = ({ children }) => {
- const { clusterQueue, clusterMap } = useAppSelector(({ queue, api }) => ({ ...queue, ...api }));
+ const { clusterQueue } = useAppSelector(({ queue }) => ({ ...queue }));
const dispatch = useAppDispatch();
const queue: { [key: string]: NodeJS.Timer } = useMemo(() => ({}), []);
@@ -26,9 +26,7 @@ const QueueProvider: FunctionComponent = ({ children }) => {
const getClusterInterval = useCallback(
({ clusterName }: ClusterQueue) => {
return setInterval(async () => {
- const { clusterCache } = await dispatch(getClusters()).unwrap();
-
- const { status } = clusterCache[clusterName];
+ const { status } = await dispatch(getClusters()).unwrap();
dispatch(
setClusterQueue({
@@ -83,23 +81,6 @@ const QueueProvider: FunctionComponent = ({ children }) => {
};
useEffect(() => {
- // Look inside of clusterMap as well for the workload clusters that have been provisioned
- // during the during the creation of the management cluster.
- // omit draft cluster that is a part of the clusterMap during provisioning of a
- // new workload cluster
- Object.values(clusterMap).forEach(({ clusterId, clusterName, status }) => {
- if (
- clusterId !== RESERVED_DRAFT_CLUSTER_NAME &&
- !queue[clusterName] &&
- [ClusterStatus.DELETING, ClusterStatus.PROVISIONING].includes(status)
- ) {
- queue[clusterName] = getClusterInterval({ clusterName, status });
- }
- if (status === ClusterStatus.DELETED) {
- dispatch(removeClusterFromQueue(clusterName));
- }
- });
-
Object.values(clusterQueue).forEach(({ clusterName, status }) => {
if (
clusterName !== RESERVED_DRAFT_CLUSTER_NAME &&
@@ -112,7 +93,7 @@ const QueueProvider: FunctionComponent = ({ children }) => {
dispatch(removeClusterFromQueue(clusterName));
}
});
- }, [clusterQueue, getClusterInterval, queue, dispatch, clusterMap]);
+ }, [clusterQueue, getClusterInterval, queue, dispatch]);
return (
(null);
-
- useEffect(() => {
- const newSocket = new WebSocket(url);
- setSocket(newSocket);
- return () => {
- newSocket.close();
- };
- }, [url]);
-
- return socket;
-}
diff --git a/jest-preset.json b/jest-preset.json
deleted file mode 100644
index e69de29b..00000000
diff --git a/pages/api/auth/[...nextauth].ts b/pages/api/auth/[...nextauth].ts
deleted file mode 100644
index 037c2573..00000000
--- a/pages/api/auth/[...nextauth].ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import NextAuth, { NextAuthOptions } from 'next-auth';
-import { OAuthConfig } from 'next-auth/providers';
-
-import { Route } from '@/constants';
-
-interface User {
- id: string;
- name: string;
- email: string;
- groups: Array;
-}
-
-const nestJSOAuth: OAuthConfig = {
- id: 'vault',
- name: 'vault',
- type: 'oauth',
- version: '2.0',
- jwks_endpoint: `https://vault.${process.env.DOMAIN}/v1/identity/oidc/provider/kubefirst/.well-known/keys`,
- authorization: {
- url: `https://vault.${process.env.DOMAIN}/ui/vault/identity/oidc/provider/kubefirst/authorize`,
- params: {
- scope: 'openid email profile user groups id',
- },
- },
- token: `https://vault.${process.env.DOMAIN}/v1/identity/oidc/provider/kubefirst/token`,
- issuer: `https://vault.${process.env.DOMAIN}/v1/identity/oidc/provider/kubefirst`,
- idToken: true,
- async profile(profile: User): Promise {
- return { ...profile, id: profile.email };
- },
- clientId: process.env.CLIENT_ID,
- clientSecret: process.env.SECRET_ID,
-};
-
-export const authOptions: NextAuthOptions = {
- providers: [nestJSOAuth],
- session: {
- strategy: 'jwt',
- maxAge: 3600,
- },
- callbacks: {
- async jwt({ token, account, profile }) {
- if (account) {
- token.groups = profile?.groups;
- }
- return token;
- },
- async session({ user, session, token }) {
- return { ...user, ...session, groups: token.groups };
- },
- },
- pages: {
- signIn: Route.SIGN_IN,
- },
-};
-
-export default NextAuth(authOptions);
diff --git a/pages/api/proxy.ts b/pages/api/proxy.ts
index 754cb12a..4910ff0a 100644
--- a/pages/api/proxy.ts
+++ b/pages/api/proxy.ts
@@ -1,18 +1,16 @@
import axios from 'axios';
import type { NextApiRequest, NextApiResponse } from 'next';
-const API_TARGET_ID = 'api';
-
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
- const { API_URL = '', ENTERPRISE_API_URL = '', K1_ACCESS_TOKEN = '' } = process.env;
+ const { API_URL = '', K1_ACCESS_TOKEN = '' } = process.env;
const { body, url } = req.body;
- const { url: queryUrl, target = API_TARGET_ID } = req.query;
+ const { url: queryUrl } = req.query;
if (!API_URL) {
return res.status(200).json('API_URL not provided');
}
- const apiBaseUrl = target === API_TARGET_ID ? API_URL : ENTERPRISE_API_URL;
+ const apiBaseUrl = API_URL;
// eslint-disable-next-line no-console
console.log('BASE URL:', apiBaseUrl);
diff --git a/redux/selectors/applications.selector.ts b/redux/selectors/applications.selector.ts
deleted file mode 100644
index a3353151..00000000
--- a/redux/selectors/applications.selector.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { createSelector } from '@reduxjs/toolkit';
-
-import { RootState } from '@/redux/store';
-
-const applicationsSelector = (state: RootState) => state.applications;
-
-export const selectApplications = () =>
- createSelector(applicationsSelector, (applicationsState) => applicationsState);
diff --git a/redux/selectors/environments.selector.ts b/redux/selectors/environments.selector.ts
deleted file mode 100644
index 514d887b..00000000
--- a/redux/selectors/environments.selector.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { createSelector } from '@reduxjs/toolkit';
-
-import { RootState } from '@/redux/store';
-
-const environmentsSelector = (state: RootState) => state.environments;
-
-export const selectEnvironmentsState = () =>
- createSelector(environmentsSelector, (environmentsState) => environmentsState);
diff --git a/redux/selectors/subscription.selector.ts b/redux/selectors/subscription.selector.ts
deleted file mode 100644
index 9669e28e..00000000
--- a/redux/selectors/subscription.selector.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { createSelector } from '@reduxjs/toolkit';
-
-import { RootState } from '@/redux/store';
-import { SaasPlans } from '@/types/subscription';
-
-const subscriptionSelector = (state: RootState) => state.subscription;
-
-export const selectHasLicenseKey = () =>
- createSelector(subscriptionSelector, ({ license }) => !!license?.licenseKey);
-
-export const selectSubscriptionPlan = () =>
- createSelector(subscriptionSelector, ({ license }) => license?.plan?.name);
-
-export const selectIsLicenseActive = () =>
- createSelector(subscriptionSelector, ({ license }) => !!license?.is_active);
-
-export const selectPendingInvoice = () =>
- createSelector(
- subscriptionSelector,
- ({ license }) => license?.invoices && license?.invoices.find(({ status }) => status === 'open'),
- );
-
-export const selectUpgradeLicenseDefinition = () =>
- createSelector(subscriptionSelector, ({ license }) => {
- if (!license?.licenseKey) {
- return {
- text: 'You’ve reached the workload clusters limit.',
- description: 'Upgrade to a Pro plan to provision the number of clusters you need.',
- ctaText: 'Upgrade to a Pro plan',
- };
- }
-
- if (license?.plan?.name === SaasPlans.Pro) {
- return {
- text: 'You’ve reached the workload clusters limit.',
- description: 'Upgrade to an Enterprise plan to provision the number of clusters you need.',
- ctaText: 'Contact us to upgrade',
- };
- }
- });
-
-export const selectRequestByType = (requestType: string) =>
- createSelector(
- subscriptionSelector,
- ({ license }) =>
- license?.requests && license?.requests.find(({ type }) => type === requestType),
- );
diff --git a/redux/slices/api.slice.ts b/redux/slices/api.slice.ts
index 9fff30e7..78f07992 100644
--- a/redux/slices/api.slice.ts
+++ b/redux/slices/api.slice.ts
@@ -3,8 +3,6 @@ import { sortBy } from 'lodash';
import {
createCluster,
- createWorkloadCluster,
- deleteCluster,
getCloudDomains,
getCloudRegions,
getClusters,
@@ -15,14 +13,8 @@ import {
ManagementCluster,
ClusterCreationStep,
ClusterStatus,
- NewWorkloadClusterConfig,
- WorkloadCluster,
Cluster,
- DraftCluster,
} from '../../types/provision';
-import { ClusterCache } from '../../types/redux';
-
-import { RESERVED_DRAFT_CLUSTER_NAME } from '@/constants';
export interface ApiState {
loading: boolean;
@@ -40,8 +32,6 @@ export interface ApiState {
instanceSizes: string[];
isAuthenticationValid?: boolean;
clusterCreationStep: ClusterCreationStep;
- clusterConfig?: NewWorkloadClusterConfig;
- clusterMap: ClusterCache;
}
export const initialState: ApiState = {
@@ -58,7 +48,6 @@ export const initialState: ApiState = {
instanceSizes: [],
isAuthenticationValid: undefined,
clusterCreationStep: ClusterCreationStep.CONFIG,
- clusterMap: {},
};
const apiSlice = createSlice({
@@ -77,9 +66,6 @@ const apiSlice = createSlice({
state.isError = payload?.status === ClusterStatus.ERROR;
state.isProvisioned = payload?.status === ClusterStatus.PROVISIONED;
},
- setClusterMap: (state, { payload }: PayloadAction) => {
- state.clusterMap = payload;
- },
setCompletedSteps: (state, action) => {
state.completedSteps = action.payload;
},
@@ -102,25 +88,6 @@ const apiSlice = createSlice({
setClusterCreationStep: (state, { payload }: PayloadAction) => {
state.clusterCreationStep = payload;
},
- setClusterConfig: (state, { payload }: PayloadAction) => {
- state.clusterConfig = payload;
- },
- createDraftCluster: (state, { payload }: PayloadAction) => {
- state.clusterMap[payload.clusterId] = payload;
- state.presentedClusterName = payload.clusterName;
- },
- removeDraftCluster: (state) => {
- delete state.clusterMap[RESERVED_DRAFT_CLUSTER_NAME];
- },
- updateDraftCluster: (state, { payload }: PayloadAction) => {
- const currentDraftCluster = state.clusterMap[RESERVED_DRAFT_CLUSTER_NAME];
- if (currentDraftCluster) {
- state.clusterMap[RESERVED_DRAFT_CLUSTER_NAME] = {
- ...currentDraftCluster,
- ...payload,
- };
- }
- },
clearResponseError: (state) => {
state.responseError = undefined;
},
@@ -138,40 +105,9 @@ const apiSlice = createSlice({
state.isError = true;
state.responseError = action.error.message;
})
- .addCase(createWorkloadCluster.pending, (state) => {
- state.loading = true;
- })
- .addCase(createWorkloadCluster.rejected, (state, action) => {
- state.loading = false;
- state.isError = true;
- state.responseError = action.error.message;
- })
- .addCase(createWorkloadCluster.fulfilled, (state, { payload }) => {
- state.loading = false;
-
- state.presentedClusterName = payload.clusterName;
- state.clusterMap[payload.clusterName] = payload;
- delete state.clusterMap[RESERVED_DRAFT_CLUSTER_NAME];
-
- state.clusterCreationStep = ClusterCreationStep.DETAILS;
- })
- .addCase(deleteCluster.pending, (state) => {
- if (state.presentedClusterName) {
- state.clusterMap[state.presentedClusterName].status = ClusterStatus.DELETING;
- }
- })
- .addCase(deleteCluster.fulfilled, (state) => {
- state.loading = false;
- })
- .addCase(deleteCluster.rejected, (state, action) => {
- state.loading = false;
- state.isError = true;
- state.responseError = action.error.message;
- })
- .addCase(getClusters.fulfilled, (state, { payload: { managementCluster, clusterCache } }) => {
+ .addCase(getClusters.fulfilled, (state, { payload: managementCluster }) => {
state.loading = false;
state.managementCluster = managementCluster;
- state.clusterMap = { ...state.clusterMap, ...clusterCache };
state.lastErrorCondition = managementCluster.lastErrorCondition;
state.isError = managementCluster.status === ClusterStatus.ERROR;
@@ -239,13 +175,8 @@ export const {
clearClusterState,
clearDomains,
setClusterCreationStep,
- setClusterConfig,
- createDraftCluster,
- removeDraftCluster,
- updateDraftCluster,
setPresentedClusterName,
setManagementCluster,
- setClusterMap,
clearResponseError,
} = apiSlice.actions;
diff --git a/redux/slices/applications.slice.ts b/redux/slices/applications.slice.ts
deleted file mode 100644
index 92a42b2c..00000000
--- a/redux/slices/applications.slice.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-
-import {
- getClusterApplications,
- getGitOpsCatalogApps,
- installGitOpsApp,
- uninstallGitOpsApp,
- validateGitOpsApplication,
-} from '@/redux/thunks/applications.thunk';
-import { GitOpsCatalogApp, ClusterApplication, Target, AppCategory } from '@/types/applications';
-import { ManagementCluster, WorkloadCluster } from '@/types/provision';
-
-export interface ApplicationsState {
- selectedCluster?: ManagementCluster | WorkloadCluster;
- selectedCategories: AppCategory[];
- selectedApplicationName?: string;
- selectedCatalogApp?: GitOpsCatalogApp;
- canDeleteSelectedApp: boolean;
- clusterApplications: Array;
- installedClusterAppNames: ClusterApplication['name'][];
- selectedClusterApplication?: ClusterApplication;
- isLoading: boolean;
- isValidating: boolean;
- gitOpsCatalogApps: Array;
- appsQueue: Array;
- filter: { target?: Target; cluster?: string };
-}
-
-export const initialState: ApplicationsState = {
- selectedCluster: undefined,
- selectedClusterApplication: undefined,
- selectedCategories: [],
- clusterApplications: [],
- installedClusterAppNames: [],
- isLoading: false,
- isValidating: false,
- gitOpsCatalogApps: [],
- canDeleteSelectedApp: true,
- appsQueue: [],
- filter: {
- target: Target.CLUSTER,
- cluster: '',
- },
-};
-
-const applicationsSlice = createSlice({
- name: 'applications',
- initialState,
- reducers: {
- setSelectedCluster: (
- state,
- { payload }: PayloadAction,
- ) => {
- state.selectedCluster = payload;
- },
- setFilterState: (state, { payload }: PayloadAction) => {
- const targetChanged = payload.target !== state.filter.target;
- if (targetChanged) {
- state.clusterApplications = [];
- }
- state.filter = {
- ...payload,
- cluster: targetChanged ? undefined : payload.cluster,
- };
- },
- addAppToQueue: (state, { payload }: PayloadAction) => {
- state.appsQueue.push(payload);
- },
- removeAppFromQueue: (state, { payload }: PayloadAction) => {
- state.appsQueue = state.appsQueue.filter((name) => name !== payload);
- },
- resetClusterApplications: (state) => {
- state.clusterApplications = [];
- },
- addCategory: (state, { payload }: PayloadAction) => {
- state.selectedCategories = [...state.selectedCategories, payload];
- },
- removeCategory: (state, { payload }: PayloadAction) => {
- state.selectedCategories = state.selectedCategories.filter(
- (selectedCategory) => selectedCategory !== payload,
- );
- },
- setSelectedCatalogApp: (
- state,
- { payload }: PayloadAction,
- ) => {
- state.selectedCatalogApp = payload;
- },
- setSelectedClusterApplication: (
- state,
- { payload }: PayloadAction,
- ) => {
- state.selectedClusterApplication = payload;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(getClusterApplications.pending, (state) => {
- state.clusterApplications = [];
- state.installedClusterAppNames = [];
- })
- .addCase(getClusterApplications.fulfilled, (state, { payload }) => {
- if (payload) {
- state.clusterApplications = payload;
-
- state.installedClusterAppNames = payload.map((app) => app.name);
- } else {
- state.installedClusterAppNames = [];
- state.clusterApplications = [];
- }
- })
- .addCase(getClusterApplications.rejected, (state) => {
- state.clusterApplications = [];
- state.installedClusterAppNames = [];
- })
- .addCase(installGitOpsApp.fulfilled, (state, { payload }) => {
- state.appsQueue = state.appsQueue.filter((name) => name !== payload.name);
-
- const { name, description, image_url } = payload;
- state.clusterApplications.push({
- default: false,
- description: description as string,
- name,
- image: image_url,
- links: [],
- });
- state.installedClusterAppNames.push(name);
- })
- .addCase(installGitOpsApp.rejected, (state) => {
- const queue = Object.assign(state.appsQueue, []);
- queue.pop();
- state.appsQueue = queue;
- })
- .addCase(
- getGitOpsCatalogApps.fulfilled,
- (state, { payload }: PayloadAction>) => {
- state.gitOpsCatalogApps = payload;
- },
- )
- .addCase(getGitOpsCatalogApps.rejected, (state) => {
- state.gitOpsCatalogApps = [];
- })
- .addCase(uninstallGitOpsApp.pending, (state) => {
- state.isLoading = true;
- })
- .addCase(uninstallGitOpsApp.fulfilled, (state) => {
- state.isLoading = false;
- })
- .addCase(uninstallGitOpsApp.rejected, (state) => {
- state.isLoading = false;
- })
- .addCase(validateGitOpsApplication.pending, (state) => {
- state.isValidating = true;
- })
- .addCase(validateGitOpsApplication.fulfilled, (state, { payload }) => {
- state.canDeleteSelectedApp = !!payload.can_delete_service;
- state.isValidating = false;
- })
- .addCase(validateGitOpsApplication.rejected, (state) => {
- state.canDeleteSelectedApp = true;
- state.isValidating = false;
- });
- },
-});
-
-export const {
- addAppToQueue,
- removeAppFromQueue,
- resetClusterApplications,
- setFilterState,
- addCategory,
- removeCategory,
- setSelectedCatalogApp,
- setSelectedCluster,
- setSelectedClusterApplication,
-} = applicationsSlice.actions;
-
-export const applicationsReducer = applicationsSlice.reducer;
diff --git a/redux/slices/config.slice.ts b/redux/slices/config.slice.ts
index cccb92c4..d666aeef 100644
--- a/redux/slices/config.slice.ts
+++ b/redux/slices/config.slice.ts
@@ -12,7 +12,6 @@ export interface ConfigState {
installMethod?: string;
isLoading: boolean;
clusterManagementTab: ClusterManagementTab;
- saasURL?: string;
}
export const initialState: ConfigState = {
@@ -20,7 +19,6 @@ export const initialState: ConfigState = {
isTelemetryDisabled: false,
isClusterZero: false,
isLoading: false,
- saasURL: '',
clusterManagementTab: ClusterManagementTab.GRAPH_VIEW,
};
@@ -29,21 +27,14 @@ const configSlice = createSlice({
initialState,
reducers: {
setConfigValues: (state, action: PayloadAction) => {
- const {
- isClusterZero,
- installMethod,
- disableTelemetry,
- kubefirstVersion,
- disableAuth,
- saasURL,
- } = action.payload;
+ const { isClusterZero, installMethod, disableTelemetry, kubefirstVersion, disableAuth } =
+ action.payload;
state.isTelemetryDisabled = !!disableTelemetry;
state.kubefirstVersion = kubefirstVersion;
state.isClusterZero = isClusterZero;
state.installMethod = installMethod;
state.isAuthDisabled = !!disableAuth;
- state.saasURL = saasURL;
},
setClusterManagamentTab: (state, { payload }: PayloadAction) => {
state.clusterManagementTab = payload;
diff --git a/redux/slices/environments.slice.ts b/redux/slices/environments.slice.ts
deleted file mode 100644
index 29ca1aeb..00000000
--- a/redux/slices/environments.slice.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import { PayloadAction, createSlice } from '@reduxjs/toolkit';
-
-import { ClusterEnvironment } from '../../types/provision';
-import {
- createEnvironment,
- deleteEnvironment,
- getAllEnvironments,
-} from '../thunks/environments.thunk';
-import { EnvCache } from '../../types/redux';
-import { getClusters } from '../thunks/api.thunk';
-
-export type EnvMap = Record;
-export interface EnvironmentsState {
- loading: boolean;
- environments: EnvMap;
- /**
- * environments cache for environments in use by cluster(s)
- */
- boundEnvironments: EnvCache;
- error?: string;
-}
-
-export const initialState: EnvironmentsState = {
- loading: false,
- environments: {},
- boundEnvironments: {},
-};
-
-const environmentsSlice = createSlice({
- name: 'environments',
- initialState,
- reducers: {
- setEnvironments: (state, { payload }: PayloadAction) => {
- state.environments = payload;
- },
- setBoundEnvironments: (state, { payload }: PayloadAction) => {
- state.boundEnvironments = payload;
- },
- setEnvironmentError: (state, { payload }: PayloadAction) => {
- state.error = payload;
- },
- clearEnvironmentError: (state) => {
- state.error = undefined;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(getAllEnvironments.pending, (state) => {
- state.loading = true;
- })
- .addCase(getAllEnvironments.rejected, (state, action) => {
- state.loading = false;
- state.environments = {};
- state.error = action.error.message;
- })
- .addCase(getAllEnvironments.fulfilled, (state, { payload }) => {
- state.loading = false;
- state.environments = payload;
- })
- .addCase(createEnvironment.pending, (state) => {
- state.loading = true;
- })
- .addCase(createEnvironment.rejected, (state, action) => {
- state.loading = false;
- state.error = action.error.message;
- })
- .addCase(createEnvironment.fulfilled, (state, { payload }) => {
- state.loading = false;
- state.environments[payload.id] = payload;
- })
- .addCase(deleteEnvironment.pending, (state) => {
- state.loading = true;
- })
- .addCase(deleteEnvironment.rejected, (state, action) => {
- state.loading = false;
- state.error = action.error.message;
- })
- .addCase(deleteEnvironment.fulfilled, (state, { payload: envId }) => {
- state.loading = false;
- delete state.environments[envId];
- })
- .addCase(getClusters.fulfilled, (state, { payload: { envCache } }) => {
- state.boundEnvironments = envCache;
- });
- },
-});
-
-export const { setEnvironments, setBoundEnvironments, setEnvironmentError, clearEnvironmentError } =
- environmentsSlice.actions;
-
-export const environmentsReducer = environmentsSlice.reducer;
diff --git a/redux/slices/index.ts b/redux/slices/index.ts
index 012e7eae..241b0246 100644
--- a/redux/slices/index.ts
+++ b/redux/slices/index.ts
@@ -1,14 +1,8 @@
-export { readinessReducer } from './readiness.slice';
export { gitReducer } from './git.slice';
export { configReducer } from './config.slice';
export { installationReducer } from './installation.slice';
export { apiReducer } from './api.slice';
export { featureFlagsReducer } from './featureFlags.slice';
-export { applicationsReducer } from './applications.slice';
-export { reactFlowReducer } from './reactFlow.slice';
export { queueReducer } from './queue.slice';
-export { environmentsReducer } from './environments.slice';
export { notificationsReducer } from './notifications.slice';
-export { settingsReducer } from './settings.slice';
-export { subscriptionReducer } from './subscription.slice';
export { digitalOceanReducer } from './digitalOcean.slice';
diff --git a/redux/slices/installation.slice.ts b/redux/slices/installation.slice.ts
index 5b6cb8fd..d0a0d75f 100644
--- a/redux/slices/installation.slice.ts
+++ b/redux/slices/installation.slice.ts
@@ -53,21 +53,11 @@ const installationSlice = createSlice({
},
},
extraReducers: (builder) => {
- builder.addCase(
- getClusters.fulfilled,
- (
- state,
- {
- payload: {
- managementCluster: { status, lastErrorCondition },
- },
- },
- ) => {
- if (status === ClusterStatus.ERROR) {
- state.error = lastErrorCondition;
- }
- },
- );
+ builder.addCase(getClusters.fulfilled, (state, { payload: { status, lastErrorCondition } }) => {
+ if (status === ClusterStatus.ERROR) {
+ state.error = lastErrorCondition;
+ }
+ });
},
});
diff --git a/redux/slices/queue.slice.ts b/redux/slices/queue.slice.ts
index 058b4c4d..6ec0dc66 100644
--- a/redux/slices/queue.slice.ts
+++ b/redux/slices/queue.slice.ts
@@ -1,7 +1,7 @@
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { ClusterQueue } from '../../types/provision';
-import { createCluster, createWorkloadCluster, deleteCluster } from '../thunks/api.thunk';
+import { createCluster } from '../thunks/api.thunk';
import { Cluster } from '../../types/provision';
export type Queue = {
@@ -30,16 +30,9 @@ const queueSlice = createSlice({
},
},
extraReducers: (builder) => {
- builder
- .addCase(createCluster.fulfilled, (state, { payload: { clusterName, status } }) => {
- state.clusterQueue[clusterName] = { clusterName, status };
- })
- .addCase(createWorkloadCluster.fulfilled, (state, { payload: { clusterName, status } }) => {
- state.clusterQueue[clusterName] = { clusterName, status };
- })
- .addCase(deleteCluster.fulfilled, (state, { payload: { clusterName, status } }) => {
- state.clusterQueue[clusterName] = { clusterName, status };
- });
+ builder.addCase(createCluster.fulfilled, (state, { payload: { clusterName, status } }) => {
+ state.clusterQueue[clusterName] = { clusterName, status };
+ });
},
});
diff --git a/redux/slices/reactFlow.slice.ts b/redux/slices/reactFlow.slice.ts
deleted file mode 100644
index 5ac6aadc..00000000
--- a/redux/slices/reactFlow.slice.ts
+++ /dev/null
@@ -1,83 +0,0 @@
-'use client';
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-import {
- addEdge,
- applyEdgeChanges,
- applyNodeChanges,
- Connection,
- Edge,
- EdgeChange,
- NodeChange,
-} from 'reactflow';
-
-import { setPresentedClusterName } from './api.slice';
-
-import { CustomGraphNode } from '@/components/GraphNode/GraphNode';
-
-export interface ReactFlowState {
- nodes: CustomGraphNode[];
- edges: Edge[];
-}
-
-export const initialState: ReactFlowState = {
- nodes: [],
- edges: [],
-};
-
-const reactFlowSlice = createSlice({
- name: 'react-flow',
- initialState,
- reducers: {
- setNodes: (state, { payload }: PayloadAction) => {
- state.nodes = payload;
- },
- addNode: (state, { payload }: PayloadAction) => {
- state.nodes = [...state.nodes, payload];
- },
- setEdges: (state, { payload }: PayloadAction) => {
- state.edges = payload;
- },
- addNewEdge: (state, { payload }: PayloadAction) => {
- state.edges = addEdge(payload, state.edges);
- },
- onNodesChange: (state, { payload }: PayloadAction) => {
- state.nodes = applyNodeChanges(payload, state.nodes);
- },
- onEdgesChange: (state, { payload }: PayloadAction) => {
- state.edges = applyEdgeChanges(payload, state.edges);
- },
- onConnect: (state, { payload }: PayloadAction) => {
- state.edges = addEdge(payload, state.edges);
- },
- selectNodeById: (state, { payload }: PayloadAction) => {
- const selectedNode = state.nodes.find((node) => node.id === payload);
- if (selectedNode) {
- selectedNode.selected = true;
- }
- },
- unSelectNodes: (state) => {
- state.nodes = state.nodes.map((node) => ({ ...node, selected: false }));
- },
- },
- extraReducers: (builder) => {
- builder.addCase(setPresentedClusterName, (state, { payload }) => {
- if (!payload) {
- state.nodes = state.nodes.map((node) => ({ ...node, selected: false }));
- }
- });
- },
-});
-
-export const {
- setNodes,
- addNode,
- setEdges,
- addNewEdge,
- onNodesChange,
- onEdgesChange,
- onConnect,
- selectNodeById,
- unSelectNodes,
-} = reactFlowSlice.actions;
-
-export const reactFlowReducer = reactFlowSlice.reducer;
diff --git a/redux/slices/readiness.slice.ts b/redux/slices/readiness.slice.ts
deleted file mode 100644
index 4671d680..00000000
--- a/redux/slices/readiness.slice.ts
+++ /dev/null
@@ -1,43 +0,0 @@
-import { createSlice } from '@reduxjs/toolkit';
-
-import { checkSiteReadiness } from '../thunks/readiness.thunk';
-
-export interface ReadinessState {
- availableSites: Array;
- error: string | null;
- loading: boolean;
-}
-
-export const initialState: ReadinessState = {
- availableSites: [],
- error: null,
- loading: false,
-};
-
-const readinessSlice = createSlice({
- name: 'readiness',
- initialState,
- reducers: {
- clearReadinessError: (state) => {
- state.error = null;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(checkSiteReadiness.pending, (state) => {
- state.loading = true;
- })
- .addCase(checkSiteReadiness.fulfilled, (state, action) => {
- state.loading = false;
- state.availableSites.push(action.payload.url);
- })
- .addCase(checkSiteReadiness.rejected, (state, action) => {
- state.loading = false;
- state.error = action.error.message ?? 'failed to check readiness';
- });
- },
-});
-
-export const { clearReadinessError } = readinessSlice.actions;
-
-export const readinessReducer = readinessSlice.reducer;
diff --git a/redux/slices/settings.slice.ts b/redux/slices/settings.slice.ts
deleted file mode 100644
index 0f91e12b..00000000
--- a/redux/slices/settings.slice.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { PayloadAction, createSlice } from '@reduxjs/toolkit';
-
-import { getClusterTourStatus, updateClusterTourStatus } from '../thunks/settings.thunk';
-
-import { SettingsTab } from '@/constants/setttings';
-
-export interface SettingsState {
- isLoading: boolean;
- activeTab: number;
- takenConsoleTour: boolean;
- isBannerOpen: boolean;
-}
-
-export const initialState: SettingsState = {
- isLoading: false,
- activeTab: SettingsTab.PLANS,
- takenConsoleTour: false,
- isBannerOpen: false,
-};
-
-const settingsSlice = createSlice({
- name: 'slice',
- initialState,
- reducers: {
- setActiveTab: (state, { payload }: PayloadAction) => {
- state.activeTab = payload;
- },
- setIsBannerOpen: (state, { payload }: PayloadAction) => {
- state.isBannerOpen = payload;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(getClusterTourStatus.rejected, () => {
- // eslint-disable-next-line no-console
- console.error('unable to retrieve console tour secret');
- })
- .addCase(getClusterTourStatus.fulfilled, (state, { payload }) => {
- const tourStatus = payload === 'true';
- state.takenConsoleTour = tourStatus;
- })
- .addCase(updateClusterTourStatus.rejected, () => {
- // eslint-disable-next-line no-console
- console.error('unable to update cluster tour status');
- });
- },
-});
-
-export const { setActiveTab, setIsBannerOpen } = settingsSlice.actions;
-
-export const settingsReducer = settingsSlice.reducer;
diff --git a/redux/slices/subscription.slice.ts b/redux/slices/subscription.slice.ts
deleted file mode 100644
index a6aa6ccc..00000000
--- a/redux/slices/subscription.slice.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-
-import { ClusterUsage, License } from '@/types/subscription';
-import {
- activateLicenseKey,
- getClusterUsage,
- validateLicenseKey,
-} from '@/redux/thunks/subscription.thunk';
-
-export interface LicenseState {
- license?: License;
- isLoading: boolean;
- clusterUsageList: Array;
- error?: string;
-}
-
-export const initialState: LicenseState = {
- isLoading: false,
- clusterUsageList: [],
-};
-
-const subscriptionSlice = createSlice({
- name: 'license',
- initialState,
- reducers: {
- setLicense: (state, { payload }: PayloadAction) => {
- state.license = payload;
- },
- },
- extraReducers: (builder) => {
- builder
- .addCase(validateLicenseKey.fulfilled, (state, { payload }) => {
- state.license = payload;
- state.isLoading = false;
- })
- .addCase(validateLicenseKey.pending, (state) => {
- state.isLoading = true;
- })
- .addCase(validateLicenseKey.rejected, (state) => {
- state.isLoading = false;
- })
- .addCase(activateLicenseKey.fulfilled, (state) => {
- state.isLoading = false;
- })
- .addCase(activateLicenseKey.pending, (state) => {
- state.isLoading = true;
- state.error = undefined;
- })
- .addCase(activateLicenseKey.rejected, (state) => {
- state.isLoading = false;
- state.error =
- 'Please enter a valid license key. If this error persists please reach out to the kubefirst team.';
- })
- .addCase(getClusterUsage.fulfilled, (state, { payload }) => {
- state.isLoading = false;
- state.clusterUsageList = payload;
- })
- .addCase(getClusterUsage.pending, (state) => {
- state.isLoading = true;
- state.error = undefined;
- })
- .addCase(getClusterUsage.rejected, (state) => {
- state.isLoading = false;
- });
- },
-});
-
-export const { setLicense } = subscriptionSlice.actions;
-
-export const subscriptionReducer = subscriptionSlice.reducer;
diff --git a/redux/store.ts b/redux/store.ts
index b241ced9..3745a9f2 100644
--- a/redux/store.ts
+++ b/redux/store.ts
@@ -14,14 +14,8 @@ import {
gitReducer,
installationReducer,
queueReducer,
- reactFlowReducer,
- readinessReducer,
- environmentsReducer,
notificationsReducer,
- settingsReducer,
- subscriptionReducer,
digitalOceanReducer,
- applicationsReducer,
} from './slices';
const rootReducer = combineReducers({
@@ -29,16 +23,10 @@ const rootReducer = combineReducers({
config: configReducer,
installation: installationReducer,
git: gitReducer,
- readiness: readinessReducer,
api: apiReducer,
featureFlags: featureFlagsReducer,
- applications: applicationsReducer,
- reactFlow: reactFlowReducer,
queue: queueReducer,
- environments: environmentsReducer,
notifications: notificationsReducer,
- settings: settingsReducer,
- subscription: subscriptionReducer,
digitalOcean: digitalOceanReducer,
});
@@ -52,7 +40,6 @@ const config = getPersistConfig({
'installation.values.do_auth',
'installation.values.vultr_auth',
'installation.values.google_auth',
- 'applications',
'api',
'featureFlags',
'git',
@@ -63,9 +50,6 @@ const config = getPersistConfig({
'config.installMethod',
'config.isLoading',
'internalApi',
- 'readiness',
- 'environments',
- 'subscription',
],
rootReducer,
});
diff --git a/redux/thunks/__tests__/api.thunk.test.ts b/redux/thunks/__tests__/api.thunk.test.ts
index a9803caa..946ba9b2 100644
--- a/redux/thunks/__tests__/api.thunk.test.ts
+++ b/redux/thunks/__tests__/api.thunk.test.ts
@@ -5,8 +5,6 @@ import { sortBy } from 'lodash';
import { makeStore } from '../../store';
import {
createCluster,
- createWorkloadCluster,
- deleteCluster,
getCloudDomains,
getCloudRegions,
getClusters,
@@ -15,15 +13,7 @@ import {
} from '../api.thunk';
import { mapClusterFromRaw } from '../../../utils/mapClustersFromRaw';
import { mockClusterResponse } from '../../../tests/mocks/mockClusterResponse';
-import {
- clearResponseError,
- setClusterMap,
- setManagementCluster,
- setPresentedClusterName,
-} from '../../slices/api.slice';
-import { ClusterCreationStep, ClusterStatus } from '../../../types/provision';
-import { ClusterCache } from '../../../types/redux';
-import { RESERVED_DRAFT_CLUSTER_NAME } from '../../../constants';
+import { clearResponseError } from '../../slices/api.slice';
describe('redux/thunks/api', () => {
const reduxStore = makeStore();
@@ -55,67 +45,6 @@ describe('redux/thunks/api', () => {
expect(responseError).toBe('Request failed with status code 400');
});
- test('createWorkloadCluster - unsuccessful response - missing management cluster', async () => {
- mock.onPost().reply(200); // set to 200 to show that thunk is throwing internally
- await reduxStore.dispatch(createWorkloadCluster());
-
- const { isError, responseError, managementCluster } = reduxStore.getState().api;
-
- expect(isError).toBe(true);
- expect(responseError).toStrictEqual('missing management cluster');
- expect(managementCluster).toBe(undefined);
- });
-
- test('createWorkloadCluster - unsuccessful response - missing draft cluster', async () => {
- mock.onPost().reply(200); // set to 200 to show that thunk is throwing internally
-
- const { managementCluster } = mapClusterFromRaw(mockClusterResponse);
- reduxStore.dispatch(setManagementCluster(managementCluster));
-
- await reduxStore.dispatch(createWorkloadCluster());
-
- const { isError, responseError, managementCluster: manCluster } = reduxStore.getState().api;
-
- expect(isError).toBe(true);
- expect(responseError).toStrictEqual('missing draft cluster');
- expect(manCluster).toStrictEqual(managementCluster);
- });
-
- test('createWorkloadCluster - successful response ', async () => {
- const mockCreatedClusterId = 'superDopeId';
- mock.onPost().reply(200, { cluster_id: mockCreatedClusterId });
-
- const { managementCluster } = mapClusterFromRaw(mockClusterResponse);
- const { workloadClusters } = managementCluster;
-
- const mockClusterCache: ClusterCache = {
- [RESERVED_DRAFT_CLUSTER_NAME]: workloadClusters[0],
- };
-
- reduxStore.dispatch(setManagementCluster(managementCluster));
- reduxStore.dispatch(setClusterMap(mockClusterCache));
-
- await reduxStore.dispatch(createWorkloadCluster());
-
- const {
- isError,
- responseError,
- managementCluster: manCluster,
- clusterMap,
- clusterCreationStep,
- } = reduxStore.getState().api;
-
- const provisioningCluster = clusterMap[workloadClusters[0].clusterName];
-
- expect(responseError).toBe(undefined);
- expect(isError).toBe(false);
- expect(manCluster).toStrictEqual(managementCluster);
- expect(provisioningCluster).toBeDefined();
- expect(provisioningCluster.clusterId).toStrictEqual(mockCreatedClusterId);
- expect(provisioningCluster.status).toStrictEqual(ClusterStatus.PROVISIONING);
- expect(clusterCreationStep).toStrictEqual(ClusterCreationStep.DETAILS);
- });
-
test('getClusters - successful response', async () => {
mock.onGet().reply(200, [mockClusterResponse]);
@@ -123,12 +52,8 @@ describe('redux/thunks/api', () => {
await reduxStore.dispatch(getClusters());
- const { managementCluster, clusterMap } = reduxStore.getState().api;
- const { boundEnvironments } = reduxStore.getState().environments;
-
- expect(managementCluster).toStrictEqual(mockResult.managementCluster);
- expect(clusterMap).toStrictEqual(mockResult.clusterCache);
- expect(boundEnvironments).toStrictEqual(mockResult.envCache);
+ const { managementCluster } = reduxStore.getState().api;
+ expect(managementCluster).toStrictEqual(mockResult);
});
test('getClusters - unsuccessful response - no clusters found', async () => {
@@ -151,26 +76,6 @@ describe('redux/thunks/api', () => {
expect(responseError).toBe('Request failed with status code 400');
});
- test('deleteCluster - unsuccessful response', async () => {
- mock.onGet().reply(200, [mockClusterResponse]);
- mock.onDelete().reply(400);
-
- const {
- managementCluster: { workloadClusters },
- } = mapClusterFromRaw(mockClusterResponse);
-
- const [{ clusterName }] = workloadClusters;
-
- await reduxStore.dispatch(getClusters());
- reduxStore.dispatch(setPresentedClusterName(undefined));
- await reduxStore.dispatch(deleteCluster(clusterName));
-
- const { isError, responseError } = reduxStore.getState().api;
-
- expect(isError).toBe(true);
- expect(responseError).toBe('Request failed with status code 400');
- });
-
test('getCloudRegions - successful response', async () => {
const mockCloudRegions = ['LON1', 'FRA1', 'JAP1', 'GERM1'];
mock.onPost().reply(200, { regions: mockCloudRegions });
diff --git a/redux/thunks/__tests__/license.thunk.test.ts b/redux/thunks/__tests__/license.thunk.test.ts
deleted file mode 100644
index 2ca6ee6a..00000000
--- a/redux/thunks/__tests__/license.thunk.test.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-
-import { makeStore } from '../../store';
-import { validateLicenseKey } from '../subscription.thunk';
-import { mockUserLicense } from '../../../tests/mocks/mockUserLicense';
-import { setLicense } from '../../slices/subscription.slice';
-
-//ToDo: fix test
-describe('redux/thunks/license', () => {
- const reduxStore = makeStore();
-
- beforeEach(() => {
- mock.reset();
- reduxStore.dispatch(setLicense(undefined));
- });
-
- const mock = new MockAdapter(axios);
-
- test.skip('validateLicenseKey - successful response', async () => {
- mock.reset();
- mock.onGet().reply(200, mockUserLicense);
- const { payload } = await reduxStore.dispatch(validateLicenseKey());
-
- const { license } = reduxStore.getState().license;
-
- expect(payload).toStrictEqual(mockUserLicense);
- expect(payload).toStrictEqual(license);
- });
-
- test.skip('validateLicenseKey - unsuccessful response', async () => {
- mock.reset();
- mock.onGet().reply(400);
- const { payload } = await reduxStore.dispatch(validateLicenseKey());
-
- const { license } = reduxStore.getState().license;
-
- expect(payload).toBe(undefined);
- expect(payload).toStrictEqual(license);
- });
-});
diff --git a/redux/thunks/api.thunk.ts b/redux/thunks/api.thunk.ts
index ef247c25..a3d79f85 100644
--- a/redux/thunks/api.thunk.ts
+++ b/redux/thunks/api.thunk.ts
@@ -1,6 +1,8 @@
import axios from 'axios';
import { createAsyncThunk } from '@reduxjs/toolkit';
+import { clearError, setError, setInstallationStep } from '../slices/installation.slice';
+
import { AppDispatch, RootState } from '@/redux/store';
import {
ClusterResponse,
@@ -8,18 +10,15 @@ import {
ImageRepository,
ClusterType,
ClusterStatus,
- ClusterEnvironment,
- WorkloadCluster,
ClusterQueue,
- DraftCluster,
+ ManagementCluster,
} from '@/types/provision';
import { createQueryString } from '@/utils/url/formatDomain';
import { InstallValues, InstallationType } from '@/types/redux';
import { TelemetryClickEvent } from '@/types/telemetry';
import { mapClusterFromRaw } from '@/utils/mapClustersFromRaw';
import { GitProtocol } from '@/types';
-import { RESERVED_DRAFT_CLUSTER_NAME } from '@/constants';
-import { getCloudProviderAuth } from '@/utils/getCloudProviderAuth';
+import { AUTHENTICATION_ERROR_MSG } from '@/constants';
export const createCluster = createAsyncThunk<
ClusterQueue,
@@ -88,60 +87,8 @@ export const createCluster = createAsyncThunk<
return { clusterName: values?.clusterName as string, status: ClusterStatus.PROVISIONING };
});
-export const createWorkloadCluster = createAsyncThunk<
- WorkloadCluster,
- void,
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('api/cluster/createWorkloadCluster', async (_, { getState }) => {
- const { managementCluster, clusterMap } = getState().api;
-
- const draftCluster = clusterMap[RESERVED_DRAFT_CLUSTER_NAME];
-
- if (!managementCluster) {
- throw new Error('missing management cluster');
- }
-
- if (!draftCluster) {
- throw new Error('missing draft cluster');
- }
-
- const clusterEnvironment = !draftCluster.environment
- ? undefined
- : {
- name: draftCluster.environment?.name,
- color: draftCluster.environment?.color,
- description: draftCluster.environment?.description,
- };
-
- const { cluster_id } = (
- await axios.post<{ cluster_id: string }>(`/api/proxy?target=ee`, {
- url: `/cluster/${managementCluster?.clusterId}`,
- body: {
- cluster_name: draftCluster.clusterName,
- cloud_region: draftCluster.cloudRegion,
- node_type: draftCluster.instanceSize,
- node_count: draftCluster.nodeCount,
- environment: clusterEnvironment,
- cluster_type: draftCluster.type,
- },
- })
- ).data;
-
- const provisioningWorkloadCluster: WorkloadCluster = {
- ...draftCluster,
- clusterId: cluster_id,
- status: ClusterStatus.PROVISIONING,
- environment: draftCluster.environment as ClusterEnvironment,
- };
-
- return provisioningWorkloadCluster;
-});
-
export const getClusters = createAsyncThunk<
- ReturnType,
+ ManagementCluster,
void,
{
dispatch: AppDispatch;
@@ -160,50 +107,33 @@ export const getClusters = createAsyncThunk<
return mapClusterFromRaw(res.data[0]);
});
-export const deleteCluster = createAsyncThunk<
- ClusterQueue,
- Cluster['clusterName'],
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('api/cluster/delete', async (clusterName, { getState }) => {
- const {
- api: { managementCluster, clusterMap },
- } = getState();
-
- const { clusterId } = clusterMap[clusterName];
-
- // returned cluster_id is unused at this time.
- if (managementCluster) {
- await axios.delete<{ cluster_id: string }>(
- `/api/proxy?${createQueryString(
- 'url',
- `/cluster/${managementCluster.clusterId}/${clusterId}`,
- )}&target=ee`,
- );
- }
-
- return { clusterName, status: ClusterStatus.DELETING };
-});
-
export const getCloudRegions = createAsyncThunk<
Array,
- { values: InstallValues | Cluster; installType?: InstallationType },
+ { values: InstallValues | Cluster; installType?: InstallationType; validate: boolean },
{
dispatch: AppDispatch;
state: RootState;
}
->('api/getCloudRegions', async ({ values, installType }) => {
- const { regions } = (
- await axios.post<{ regions: Array }>('/api/proxy', {
- url: `/region/${installType || (values as Cluster).cloudProvider}`,
- body:
- installType === InstallationType.AWS ? { ...values, cloud_region: 'us-east-1' } : values,
- })
- ).data;
-
- return regions;
+>('api/getCloudRegions', async ({ values, installType, validate }, { getState, dispatch }) => {
+ try {
+ const { installation } = getState();
+ const { regions } = (
+ await axios.post<{ regions: Array }>('/api/proxy', {
+ url: `/region/${installType || (values as Cluster).cloudProvider}`,
+ body:
+ installType === InstallationType.AWS ? { ...values, cloud_region: 'us-east-1' } : values,
+ })
+ ).data;
+
+ if (validate) {
+ dispatch(setInstallationStep(installation.installationStep + 1));
+ dispatch(clearError());
+ }
+ return regions;
+ } catch (error) {
+ dispatch(setError({ error: AUTHENTICATION_ERROR_MSG }));
+ throw new Error('Failed to fetch cloud regions');
+ }
});
export const getCloudDomains = createAsyncThunk<
@@ -309,35 +239,3 @@ export const sendTelemetryEvent = createAsyncThunk<
body,
});
});
-
-export const downloadKubeconfig = createAsyncThunk<
- string,
- { presentedCluster: Cluster | DraftCluster },
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('api/downloadKubeconfig', async ({ presentedCluster }, { getState }) => {
- const { managementCluster } = getState().api;
-
- const { clusterName, cloudProvider, cloudRegion, type } = presentedCluster;
- if (managementCluster) {
- const { key, value } = getCloudProviderAuth(managementCluster);
- const {
- data: { config },
- } = await axios.post<{ config: string }>(`/api/proxy`, {
- url: `/kubeconfig/${cloudProvider}`,
- body: {
- cluster_name: clusterName,
- man_clust_name: managementCluster.clusterName,
- vcluster: type !== ClusterType.MANAGEMENT,
- cloud_region: cloudRegion,
- [`${key}_auth`]: value,
- },
- });
-
- return `data:text/yaml;chatset=utf-8,${encodeURIComponent(config)}`;
- } else {
- throw new Error('no management cluster found');
- }
-});
diff --git a/redux/thunks/applications.thunk.ts b/redux/thunks/applications.thunk.ts
deleted file mode 100644
index 56e84fb4..00000000
--- a/redux/thunks/applications.thunk.ts
+++ /dev/null
@@ -1,210 +0,0 @@
-import axios from 'axios';
-import { createAsyncThunk } from '@reduxjs/toolkit';
-import { FieldValues } from 'react-hook-form';
-
-import { AppDispatch, RootState } from '../store';
-import { createQueryString } from '../../utils/url/formatDomain';
-import { ClusterRequestProps } from '../../types/provision';
-import {
- GitOpsCatalogApp,
- ClusterApplication,
- Target,
- ValidateGitOpsCatalog,
-} from '../../types/applications';
-import { addAppToQueue, removeAppFromQueue } from '../slices/applications.slice';
-import { transformObjectToStringKey } from '../../utils/transformObjectToStringKey';
-import { createNotification } from '../slices/notifications.slice';
-
-export const installGitOpsApp = createAsyncThunk<
- GitOpsCatalogApp,
- { values: FieldValues; user: string },
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('applications/installGitOpsApp', async ({ values, user }, { dispatch, getState }) => {
- const {
- applications: { selectedCatalogApp, filter },
- api: { managementCluster, clusterMap },
- } = getState();
-
- if (!selectedCatalogApp) {
- throw new Error('missing selected catalog app');
- }
-
- const formValues = transformObjectToStringKey(values);
-
- const keys = Object.keys(formValues);
-
- const getMapValues = (values: Array<{ name: string; label: string }> | undefined) =>
- values &&
- values
- .filter(({ name }) => keys?.includes(name))
- .map(({ name: key }) => ({
- name: key,
- value: formValues && formValues[key],
- }));
-
- const secret_keys = getMapValues(selectedCatalogApp.secret_keys);
- const config_keys = getMapValues(selectedCatalogApp.config_keys);
-
- const cluster = clusterMap[filter.cluster as string];
-
- const params = {
- config_keys,
- secret_keys,
- user,
- is_template: filter.target === Target.TEMPLATE,
- workload_cluster_name: filter.cluster,
- environment: cluster?.environment?.name,
- };
-
- // Removing workload_cluster_name for management cluster installations
- if (managementCluster?.clusterName === filter.cluster) {
- delete params.workload_cluster_name;
- }
-
- dispatch(addAppToQueue(selectedCatalogApp.name));
-
- const res = await axios.post('/api/proxy', {
- // same for delete gitops app
- url: `/services/${managementCluster?.clusterName}/${selectedCatalogApp.name}`,
- body: params,
- });
-
- if ('error' in res) {
- dispatch(removeAppFromQueue(selectedCatalogApp?.name));
- throw res.error;
- }
-
- dispatch(
- createNotification({
- message: `${selectedCatalogApp.display_name} successfully added to provisioned services in cluster ${filter.cluster}!`,
- type: 'success',
- snackBarOrigin: { vertical: 'bottom', horizontal: 'right' },
- }),
- );
-
- dispatch(getClusterApplications({ clusterName: filter.cluster }));
-
- return selectedCatalogApp;
-});
-
-export const getClusterApplications = createAsyncThunk<
- ClusterApplication[],
- ClusterRequestProps,
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('applications/getClusterApplications', async ({ clusterName }) => {
- return (
- await axios.get<{ services: ClusterApplication[] }>(
- `/api/proxy?${createQueryString('url', `/services/${clusterName}`)}`,
- )
- ).data.services;
-});
-
-export const getGitOpsCatalogApps = createAsyncThunk<
- GitOpsCatalogApp[],
- string,
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('applications/getGitOpsCatalogApps', async (cloudProvider, { getState }) => {
- const {
- api: { managementCluster },
- } = getState();
-
- return (
- await axios.get<{ apps: GitOpsCatalogApp[] }>(
- `/api/proxy?${createQueryString(
- 'url',
- `/gitops-catalog/${managementCluster?.clusterName}/${cloudProvider}/apps`,
- )}`,
- )
- ).data.apps;
-});
-
-export const validateGitOpsApplication = createAsyncThunk<
- ValidateGitOpsCatalog,
- { application: ClusterApplication },
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('applications/validateGitOpsApplication', async ({ application }, { getState }) => {
- const {
- applications: { filter },
- api: { managementCluster },
- } = getState();
-
- if (!application) {
- throw new Error('missing selected catalog app');
- }
-
- const params = {
- is_template: filter.target === Target.TEMPLATE,
- workload_cluster_name: filter.cluster,
- };
-
- // Removing workload_cluster_name for management cluster installations
- if (managementCluster?.clusterName === filter.cluster) {
- delete params.workload_cluster_name;
- }
-
- return (
- await axios.post('/api/proxy', {
- url: `/services/${managementCluster?.clusterName}/${application.name}/validate`,
- body: params,
- })
- ).data;
-});
-
-export const uninstallGitOpsApp = createAsyncThunk<
- void,
- { application: ClusterApplication; user: string },
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('applications/uninstallGitOpsApp', async ({ application, user }, { dispatch, getState }) => {
- const {
- applications: { filter, canDeleteSelectedApp, selectedClusterApplication },
- api: { managementCluster },
- } = getState();
-
- if (!application) {
- throw new Error('missing selected catalog app');
- }
-
- const params = {
- user,
- is_template: filter.target === Target.TEMPLATE,
- workload_cluster_name: filter.cluster,
- skip_files: !canDeleteSelectedApp,
- };
-
- // Removing workload_cluster_name for management cluster installations
- if (managementCluster?.clusterName === filter.cluster) {
- delete params.workload_cluster_name;
- }
-
- await axios.delete('/api/proxy', {
- data: {
- url: `/services/${managementCluster?.clusterName}/${application.name}`,
- body: params,
- },
- });
-
- dispatch(removeAppFromQueue(selectedClusterApplication?.name as string));
- dispatch(getClusterApplications({ clusterName: filter.cluster }));
- dispatch(
- createNotification({
- message: `${application.name} successfully uninstalled from cluster ${filter.cluster}!`,
- type: 'success',
- snackBarOrigin: { vertical: 'bottom', horizontal: 'right' },
- }),
- );
-});
diff --git a/redux/thunks/environments.thunk.ts b/redux/thunks/environments.thunk.ts
deleted file mode 100644
index 59066d7b..00000000
--- a/redux/thunks/environments.thunk.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import { createAsyncThunk } from '@reduxjs/toolkit';
-import axios from 'axios';
-
-import { ClusterEnvironment, EnvironmentResponse } from '../../types/provision';
-import { createQueryString } from '../../utils/url/formatDomain';
-import { mapEnvironmentFromRaw } from '../../utils/mapEnvironmentFromRaw';
-import { createNotification } from '../../redux/slices/notifications.slice';
-import { EnvMap } from '../../redux/slices/environments.slice';
-import { createEnvMap } from '../../utils/createEnvMap';
-
-export const getAllEnvironments = createAsyncThunk(
- 'environments/getAllEnvironments',
- async () => {
- try {
- const { data } = await axios.get(
- `/api/proxy?${createQueryString('url', `/environment`)}`,
- );
-
- return createEnvMap(data ?? []);
- } catch (error) {
- if (axios.isAxiosError(error)) {
- throw error.response?.data.error;
- } else {
- throw error;
- }
- }
- },
-);
-
-export const createEnvironment = createAsyncThunk(
- 'environments/createEnvironment',
- async (environment) => {
- try {
- const { data } = await axios.post('/api/proxy', {
- url: '/environment',
- body: environment,
- });
- return mapEnvironmentFromRaw(data);
- } catch (error) {
- if (axios.isAxiosError(error)) {
- throw error.response?.data.error;
- } else {
- throw error;
- }
- }
- },
-);
-
-export const deleteEnvironment = createAsyncThunk(
- 'environments/deleteEnvironment',
- async (environment, { dispatch }) => {
- try {
- await axios.delete(
- `/api/proxy?${createQueryString('url', `/environment/${environment.id}`)}`,
- );
-
- dispatch(
- createNotification({
- message: `${environment.name} environment successfully deleted.`,
- type: 'success',
- snackBarOrigin: {
- vertical: 'bottom',
- horizontal: 'right',
- },
- }),
- );
-
- return environment.id;
- } catch (error) {
- if (axios.isAxiosError(error)) {
- throw error.response?.data.error;
- } else {
- throw error;
- }
- }
- },
-);
diff --git a/redux/thunks/readiness.thunk.ts b/redux/thunks/readiness.thunk.ts
deleted file mode 100644
index 39b5db18..00000000
--- a/redux/thunks/readiness.thunk.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { createAsyncThunk } from '@reduxjs/toolkit';
-
-import { endpoints } from '../api/';
-import { AppDispatch, RootState } from '../store';
-import { ReadinessData } from '../../pages/api/readiness';
-
-export const checkSiteReadiness = createAsyncThunk<
- ReadinessData,
- Omit,
- {
- dispatch: AppDispatch;
- state: RootState;
- }
->('readiness/check', async (body, { dispatch }) => {
- if (body.url.includes('localdev.me')) {
- await fetch(body.url, { mode: 'no-cors' });
- return { success: true, url: body.url };
- } else {
- const res = await dispatch(endpoints.readiness.initiate(body));
- if ('error' in res) {
- throw res.error;
- }
- return res.data;
- }
-});
diff --git a/redux/thunks/settings.thunk.ts b/redux/thunks/settings.thunk.ts
deleted file mode 100644
index 9ae1ce8d..00000000
--- a/redux/thunks/settings.thunk.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { createAsyncThunk } from '@reduxjs/toolkit';
-import axios from 'axios';
-
-import { RootState } from '../store';
-
-import { createQueryString } from '@/utils/url/formatDomain';
-
-type TourStatusReturn = {
- 'console-tour': string;
-};
-
-export const getClusterTourStatus = createAsyncThunk(
- 'settings/getClusterTourStatus',
- async (clusterName) => {
- return (
- await axios.get(
- `/api/proxy?${createQueryString('url', `/secret/${clusterName}/kubefirst-state`)}`,
- )
- ).data['console-tour'];
- },
-);
-
-export const updateClusterTourStatus = createAsyncThunk<
- void,
- { clusterName: string; takenTour: boolean },
- { state: RootState }
->('settings/updateClusterTourStatus', async ({ clusterName, takenTour }) => {
- await axios.put('/api/proxy', {
- url: `/secret/${clusterName}/kubefirst-state`,
- body: {
- 'console-tour': `${takenTour}`,
- },
- });
-});
diff --git a/redux/thunks/subscription.thunk.ts b/redux/thunks/subscription.thunk.ts
deleted file mode 100644
index b2179c61..00000000
--- a/redux/thunks/subscription.thunk.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { createAsyncThunk } from '@reduxjs/toolkit';
-import axios from 'axios';
-
-import { RootState } from '../store';
-import { createNotification } from '../slices/notifications.slice';
-
-import { ClusterUsage, License, UserRequest } from '@/types/subscription';
-
-export const validateLicenseKey = createAsyncThunk(
- 'subscription/validateLicenseKey',
- async () => {
- return (
- await axios.post('/api/proxy?target=ee', {
- url: `/subscription/validate`,
- })
- ).data;
- },
-);
-
-export const activateLicenseKey = createAsyncThunk<
- License,
- string,
- {
- state: RootState;
- }
->('subscription/activateLicenseKey', async (licenseKey, { getState }) => {
- const { managementCluster } = getState().api;
-
- return (
- await axios.post('/api/proxy?target=ee', {
- url: `/subscription/${managementCluster?.clusterId}/activateCluster`,
- body: {
- licenseKey,
- },
- })
- ).data;
-});
-
-export const getClusterUsage = createAsyncThunk<
- Array,
- string,
- {
- state: RootState;
- }
->('subscription/getCluserUsage', async (licenseKey) => {
- return (
- await axios.post>('/api/proxy?target=ee', {
- url: `/subscription/clusterUsage`,
- body: {
- licenseKey,
- },
- })
- ).data;
-});
-
-export const createUserRequest = createAsyncThunk<
- void,
- UserRequest,
- {
- state: RootState;
- }
->('subscription/createUserRequest', async (userRequest, { dispatch }) => {
- await axios.post('/api/proxy?target=ee', {
- url: '/subscription/user-request',
- body: {
- ...userRequest,
- },
- });
-
- dispatch(
- createNotification({
- message: 'Your message is on it’s way',
- type: 'success',
- snackBarOrigin: {
- vertical: 'bottom',
- horizontal: 'right',
- },
- }),
- );
-});
diff --git a/tests/mocks/mockClusterResponse.ts b/tests/mocks/mockClusterResponse.ts
index 715c1d9a..06752d26 100644
--- a/tests/mocks/mockClusterResponse.ts
+++ b/tests/mocks/mockClusterResponse.ts
@@ -1,6 +1,6 @@
-import { GitProvider } from '@/types';
-import { ClusterResponse, ClusterStatus, ClusterType } from '@/types/provision';
-import { InstallationType } from '@/types/redux';
+import { GitProvider } from '../../types';
+import { ClusterResponse, ClusterStatus, ClusterType } from '../../types/provision';
+import { InstallationType } from '../../types/redux';
export const mockClusterResponse: ClusterResponse = {
_id: '64c2ec0b057c0e84e1738aaa',
@@ -36,12 +36,6 @@ export const mockClusterResponse: ClusterResponse = {
cloud_region: 'LON1',
instance_size: '8 GPU',
node_count: 3,
- environment: {
- _id: '1',
- creation_timestamp: '1693932566',
- name: 'preprod',
- color: 'gold',
- },
status: ClusterStatus.PROVISIONING,
cluster_type: ClusterType.WORKLOAD_V_CLUSTER,
git_auth: {
@@ -63,12 +57,6 @@ export const mockClusterResponse: ClusterResponse = {
cloud_region: 'LON1',
instance_size: '8 GPU',
node_count: 3,
- environment: {
- _id: '2',
- creation_timestamp: '1693932566',
- name: 'preprod',
- color: 'gold',
- },
status: ClusterStatus.PROVISIONED,
cluster_type: ClusterType.WORKLOAD,
git_auth: {
@@ -90,12 +78,6 @@ export const mockClusterResponse: ClusterResponse = {
cloud_region: 'LON1',
instance_size: '8 GPU',
node_count: 3,
- environment: {
- _id: '3',
- creation_timestamp: '1693932566',
- name: 'preprod',
- color: 'gold',
- },
status: ClusterStatus.PROVISIONED,
cluster_type: ClusterType.WORKLOAD,
git_auth: {
@@ -117,12 +99,6 @@ export const mockClusterResponse: ClusterResponse = {
cloud_region: 'LON1',
instance_size: '8 GPU',
node_count: 3,
- environment: {
- _id: '4',
- creation_timestamp: '1693932566',
- name: 'preprod',
- color: 'gold',
- },
status: ClusterStatus.PROVISIONED,
cluster_type: ClusterType.WORKLOAD,
git_auth: {
diff --git a/tests/mocks/mockUserLicense.ts b/tests/mocks/mockUserLicense.ts
deleted file mode 100644
index 493c385b..00000000
--- a/tests/mocks/mockUserLicense.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { License } from '../../types/license';
-
-export const mockUserLicense: License = {
- key: '0e5ba61e-88b3-11ee-b9d1-0242ac120002',
-};
diff --git a/types/applications/index.ts b/types/applications/index.ts
deleted file mode 100644
index 50e699f1..00000000
--- a/types/applications/index.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import { FieldValues } from 'react-hook-form';
-
-export enum AppCategory {
- APP_MANAGEMENT = 'App Management',
- ARCHITECTURE = 'Architecture',
- CI_CD = 'CI/CD',
- DATABASE = 'Database',
- FIN_OPS = 'FinOps',
- INFRASTRUCTURE = 'Infrastructure',
- MONITORING = 'Monitoring',
- OBSERVABIILITY = 'Observability',
- SECURITY = 'Security',
- STORAGE = 'Storage',
- TESTING = 'Testing',
- QUEUEING = 'Queueing',
- KUBESHOP = 'Kubeshop',
- APPLICATIONS = 'Applications',
-}
-
-export interface GitOpsCatalogApp {
- name: string;
- display_name: string;
- secret_keys?: Array<{ name: string; label: string }>;
- config_keys?: Array<{ name: string; label: string }>;
- image_url: string;
- description?: string;
- category?: AppCategory;
-}
-
-export interface ClusterApplication {
- name: string;
- default: boolean;
- description: string;
- image: string;
- links: Array;
- status?: string;
-}
-
-export interface GitOpsCatalogProps {
- app: GitOpsCatalogApp;
- clusterName: string;
- values?: FieldValues;
- user: string;
-}
-
-export interface ValidateGitOpsCatalog {
- can_delete_service: boolean;
-}
-
-export enum Target {
- TEMPLATE = 'Template',
- CLUSTER = 'Cluster',
-}
diff --git a/types/config/index.ts b/types/config/index.ts
index 6836b63b..061c2f33 100644
--- a/types/config/index.ts
+++ b/types/config/index.ts
@@ -18,7 +18,6 @@ export interface EnvironmentVariables {
isClusterZero: boolean;
kubefirstVersion?: string;
installMethod?: string;
- saasURL?: string;
}
export enum ClusterManagementTab {
diff --git a/types/plan/index.ts b/types/plan/index.ts
deleted file mode 100644
index 992ceaf9..00000000
--- a/types/plan/index.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-export interface Plan {
- id: string;
- object: string;
- active: true;
- attributes: [];
- created: number;
- default_price: string;
- description: string;
- features: Array<{
- name: string;
- }>;
- images: Array;
- livemode: false;
- metadata: {
- [key: string]: string;
- };
- name: string;
- tax_code: string;
- type: string;
- unit_label: string | null;
- updated: number;
- url: string | null;
-}
diff --git a/types/provision/index.ts b/types/provision/index.ts
index 431cabb4..e105d424 100644
--- a/types/provision/index.ts
+++ b/types/provision/index.ts
@@ -1,7 +1,5 @@
import { GitProvider, Row } from '../';
-import { AdvancedOptions, InstallationType } from '../redux';
-
-import { TagColor } from '@/components/Tag/Tag';
+import { InstallationType } from '../redux';
export enum ClusterStatus {
DELETED = 'deleted',
@@ -18,22 +16,6 @@ export enum ClusterType {
}
export const CLUSTER_TYPES = Object.values(ClusterType);
-export const WORKLOAD_CLUSTER_TYPES = CLUSTER_TYPES.filter(
- (type) => type !== ClusterType.MANAGEMENT,
-);
-
-export type ClusterEnvironment = {
- id: string;
- name: string;
- color: TagColor;
- description?: string;
- creationDate: string;
-};
-
-export type EnvironmentResponse = Omit & {
- _id: string;
- creation_timestamp: string;
-};
export enum ClusterCreationStep {
CONFIG,
@@ -45,11 +27,6 @@ export enum ImageRepository {
ECR = 'ecr',
}
-export type NewWorkloadClusterConfig = Partial<
- Pick
-> &
- AdvancedOptions & { environment?: Partial };
-
export interface ClusterRequestProps {
clusterName?: string;
}
@@ -85,7 +62,6 @@ export interface ClusterResponse {
domain_name: string;
subdomain_name: string;
dns_provider: string;
- environment?: EnvironmentResponse;
git_auth: {
git_owner?: string;
git_token?: string;
@@ -159,7 +135,6 @@ export interface Cluster {
domainName: string;
subDomainName?: string;
dnsProvider: string;
- environment?: ClusterEnvironment;
gitProvider: GitProvider;
instanceSize?: string;
nodeCount?: number;
@@ -174,7 +149,6 @@ export interface Cluster {
export interface ManagementCluster extends Cluster, Row {
lastErrorCondition: string;
- workloadClusters: WorkloadCluster[];
gitHost: string;
vaultAuth: {
kbotPassword: string;
@@ -221,15 +195,6 @@ export interface ManagementCluster extends Cluster, Row {
};
}
-export interface WorkloadCluster extends Cluster {
- instanceSize?: string;
- machineType?: string;
-}
-
-export type DraftCluster = Omit & {
- environment?: Partial;
-};
-
export interface ClusterQueue {
clusterName: string;
status: ClusterStatus;
diff --git a/types/redux/index.ts b/types/redux/index.ts
index 0a68f32a..02dba6ec 100644
--- a/types/redux/index.ts
+++ b/types/redux/index.ts
@@ -1,4 +1,4 @@
-import { Cluster, ClusterEnvironment, DraftCluster, ImageRepository } from '../provision';
+import { ImageRepository } from '../provision';
export interface GitValues {
gitToken?: string;
@@ -105,8 +105,6 @@ export type AuthKeys = {
name: string;
label: string;
helperText?: string;
+ defaultValue?: string;
}>;
};
-
-export type EnvCache = Record;
-export type ClusterCache = Record;
diff --git a/types/subscription/index.ts b/types/subscription/index.ts
deleted file mode 100644
index 0832ef89..00000000
--- a/types/subscription/index.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-export enum SaasPlans {
- Community = 'Community',
- Pro = 'Pro',
- Enterprise = 'Enterprise',
-}
-
-export enum SaasFeatures {
- WorkloadClustersLimit = 'workloadClustersLimit',
-}
-
-export enum LicenseStatus {
- Active = 'active',
- UpToDate = 'up-todate',
- PaymentFailed = 'payment-failed',
- PaymentActionRequired = 'payment-action-required',
-}
-
-export interface License {
- id: string;
- plan: Plan;
- is_active: boolean;
- status: LicenseStatus;
- /**
- * Price id from stripe
- */
- priceId: string;
- licenseKey: string;
- created_at: Date;
- clusters: Cluster[];
- invoices: Invoice[];
- requests: UserRequest[];
-}
-
-export interface Plan {
- id: string;
- name: string;
- features: PlanFeatures[];
- licenses: License[];
-}
-
-export interface ClusterLimitPlan {
- limit: number;
-}
-export interface PlanFeatures {
- id: string;
- code: string;
- name: string;
- data: ClusterLimitPlan;
- plan: Plan;
- isActive: boolean;
-}
-
-export interface Cluster {
- id: string;
- clusterType: string;
- isActive: boolean;
- clusterName: string;
- clusterID: string;
- domainName: string;
- environment: string;
- deletedAt: Date;
- createdAt: Date;
-}
-
-export interface CancelSubscriptionFields {
- projectIsComplete: boolean;
- kubefirstIsTooExpensive: boolean;
- kubefirstIsDifficult: boolean;
- didnotUsePaidPlan: boolean;
- didnotProvideFunctionality: boolean;
- other: boolean;
- description: string;
-}
-
-export interface ContactUsFields {
- firstName: string;
- lastName: string;
- email: string;
- message: string;
-}
-
-export interface ClusterUsage {
- clusterName: string;
- clusterID: string;
- clusterType: string;
- createdAt: Date;
- deletedAt: Date;
- hours: number;
- total: number;
-}
-
-export interface Invoice {
- id: string;
- hosted_invoice_url: string;
- status: string;
-}
-
-export interface UserRequest {
- createdAt?: string;
- id?: string;
- type: string;
- requestData: string;
-}
diff --git a/utils/createEnvMap.ts b/utils/createEnvMap.ts
deleted file mode 100644
index 7a569ef2..00000000
--- a/utils/createEnvMap.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { EnvMap } from '../redux/slices/environments.slice';
-import { EnvironmentResponse } from '../types/provision';
-
-import { mapEnvironmentFromRaw } from './mapEnvironmentFromRaw';
-
-export function createEnvMap(environments: EnvironmentResponse[]): EnvMap {
- return environments.reduce((acc, curVal) => {
- acc[curVal._id] = mapEnvironmentFromRaw(curVal);
- return acc;
- }, {});
-}
diff --git a/utils/getPreviouslyUsedClusterNames.ts b/utils/getPreviouslyUsedClusterNames.ts
deleted file mode 100644
index 74d81c93..00000000
--- a/utils/getPreviouslyUsedClusterNames.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { ManagementCluster } from '../types/provision';
-
-export function getPreviouslyUsedClusterNames(cluster: ManagementCluster): string[] {
- const { workloadClusters, ...managementCluster } = cluster;
- return [...workloadClusters, managementCluster].reduce((acc, currentCluster) => {
- const { clusterName } = currentCluster;
- if (clusterName && !acc.includes(clusterName)) {
- acc.push(clusterName);
- }
- return acc;
- }, []);
-}
diff --git a/utils/mapClustersFromRaw.ts b/utils/mapClustersFromRaw.ts
index f0883ebb..4c724f0a 100644
--- a/utils/mapClustersFromRaw.ts
+++ b/utils/mapClustersFromRaw.ts
@@ -1,13 +1,7 @@
-import {
- ClusterResponse,
- ManagementCluster,
- WorkloadCluster,
- ClusterStatus,
-} from '../types/provision';
-import { ClusterCache, EnvCache } from '../types/redux';
+import { ClusterResponse, ManagementCluster } from '@/types/provision';
-export const mapClusterFromRaw = (cluster: ClusterResponse) => {
- const managementCluster: ManagementCluster = {
+export const mapClusterFromRaw = (cluster: ClusterResponse): ManagementCluster => {
+ return {
id: cluster._id,
clusterId: cluster.cluster_id,
clusterName: cluster.cluster_name,
@@ -63,65 +57,4 @@ export const mapClusterFromRaw = (cluster: ClusterResponse) => {
users_terraform_apply_check: cluster.users_terraform_apply_check,
},
};
-
- const { envCache, workloadClusters, clusterCache } = [
- ...(cluster.workload_clusters ?? []),
- ].reduce<{
- envCache: EnvCache;
- clusterCache: ClusterCache;
- workloadClusters: WorkloadCluster[];
- }>(
- (acc, curVal) => {
- const formattedWorkloadCluster: WorkloadCluster = {
- clusterId: curVal.cluster_id,
- clusterName: curVal.cluster_name,
- cloudRegion: curVal.cloud_region,
- cloudProvider: curVal.cloud_provider,
- dnsProvider: curVal.dns_provider,
- nodeCount: curVal.node_count,
- instanceSize: curVal.node_type,
- creationDate: curVal.creation_timestamp,
- environment: {
- id: curVal.environment?._id ?? '',
- name: curVal.environment?.name ?? '',
- creationDate: curVal.environment?.creation_timestamp ?? '',
- color: curVal.environment?.color ?? 'gray',
- },
- status: curVal.status,
- type: curVal.cluster_type,
- domainName: curVal.domain_name,
- subDomainName: cluster.subdomain_name, // take subdomain from management since we do not store it on the workload cluster
- gitProvider: cluster.git_provider,
- adminEmail: cluster.alerts_email,
- gitAuth: {
- gitOwner: curVal.git_auth.git_owner,
- gitToken: curVal.git_auth.git_token,
- gitUser: curVal.git_auth.git_username,
- },
- };
-
- acc.workloadClusters.push(formattedWorkloadCluster);
-
- if (
- curVal.environment &&
- curVal.environment.name &&
- curVal.status !== ClusterStatus.DELETED
- ) {
- acc.envCache[curVal.environment.name] = true;
- }
-
- acc.clusterCache[curVal.cluster_name] = formattedWorkloadCluster;
- return acc;
- },
- { clusterCache: {}, envCache: {}, workloadClusters: [] },
- );
-
- managementCluster.workloadClusters = workloadClusters;
- clusterCache[managementCluster.clusterName] = managementCluster;
-
- return {
- managementCluster,
- envCache,
- clusterCache,
- };
};
diff --git a/utils/mapEnvironmentFromRaw.ts b/utils/mapEnvironmentFromRaw.ts
deleted file mode 100644
index 65167818..00000000
--- a/utils/mapEnvironmentFromRaw.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { EnvironmentResponse, ClusterEnvironment } from '../types/provision';
-
-export const mapEnvironmentFromRaw = ({
- creation_timestamp,
- _id,
- ...rest
-}: EnvironmentResponse): ClusterEnvironment => ({
- ...rest,
- id: _id,
- creationDate: creation_timestamp,
-});
diff --git a/utils/reactFlow/index.ts b/utils/reactFlow/index.ts
deleted file mode 100644
index d6b96c69..00000000
--- a/utils/reactFlow/index.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { Edge } from 'reactflow';
-
-import {
- ManagementCluster,
- ClusterStatus,
- Cluster,
- ClusterType,
- DraftCluster,
-} from '@/types/provision';
-import { ClusterCache } from '@/types/redux';
-import { CustomGraphNode } from '@/components/GraphNode/GraphNode';
-import { RESERVED_DRAFT_CLUSTER_NAME } from '@/constants';
-
-const WORKLOAD_CLUSTER_Y_SPACE = 60;
-const WORKLOAD_CLUSTER_X_SPACE = 250;
-const WORKLOAD_NODE_HEIGHT = 128;
-const MANAGEMENT_NODE_HEIGHT = 97;
-const NODE_WIDTH = 360;
-
-export function generateNode(
- id: string,
- position: { x: number; y: number },
- info: Cluster | DraftCluster,
- selected = false,
- className?: string,
-): CustomGraphNode {
- return {
- id,
- type: 'custom',
- data: info,
- position,
- draggable: false,
- selected,
- className,
- };
-}
-
-export function generateEdge(id: string, source: string, target: string, animated = false): Edge {
- return {
- id,
- source,
- target,
- animated,
- type: 'straight',
- style: { strokeWidth: 2, stroke: '#CBD5E1' },
- };
-}
-
-export function generateNodesConfig(
- managementCluster: ManagementCluster,
- clusters: ClusterCache,
-): [CustomGraphNode[], Edge[]] {
- const { clusterId: managementClusterId } = managementCluster;
-
- const filteredWorkloadClusters = Object.values(clusters).filter(
- (cluster) =>
- cluster.status !== ClusterStatus.DELETED && cluster.type !== ClusterType.MANAGEMENT,
- );
-
- const workloadClusterLength = filteredWorkloadClusters.length;
- const spacesBetweenClusterNodes = workloadClusterLength - 1;
-
- // get total height of all nodes and space inbetween
- const totalHeight =
- workloadClusterLength * WORKLOAD_NODE_HEIGHT +
- spacesBetweenClusterNodes * WORKLOAD_CLUSTER_Y_SPACE;
-
- // place the middle of the node at the top of the column
- const initialClusterYPosition = -(totalHeight / 2) + MANAGEMENT_NODE_HEIGHT / 2;
-
- const nodes: CustomGraphNode[] = [
- generateNode(
- managementClusterId,
- {
- x: 0,
- y: 0,
- },
- managementCluster,
- false,
- 'management-cluster',
- ),
- ];
-
- const edges: Edge[] = [];
-
- for (let i = 0; i < workloadClusterLength; i += 1) {
- const workloadCluster = filteredWorkloadClusters[i];
- const { clusterId: workloadClusterId } = workloadCluster;
-
- // if first node place at initial position
- // otherwise add workload node height and space multiplied by index
- const nodeYPosition = !i
- ? initialClusterYPosition
- : initialClusterYPosition + (WORKLOAD_CLUSTER_Y_SPACE + WORKLOAD_NODE_HEIGHT) * i;
-
- const animatedEdge =
- workloadCluster.clusterId === RESERVED_DRAFT_CLUSTER_NAME ||
- workloadCluster.status === ClusterStatus.PROVISIONING;
-
- nodes.push(
- generateNode(
- workloadClusterId,
- { x: WORKLOAD_CLUSTER_X_SPACE + NODE_WIDTH, y: nodeYPosition },
- workloadCluster,
- false,
- `workload-cluster-${i + 1}`,
- ),
- );
-
- edges.push(
- generateEdge(
- `edge-${workloadClusterId}`,
- managementClusterId,
- workloadClusterId,
- animatedEdge,
- ),
- );
- }
-
- return [nodes, edges];
-}