Просмотр исходного кода

clusters -> contexts reintegrated on FE

jusrhee 5 лет назад
Родитель
Сommit
d7f6f32b28

+ 0 - 302
dashboard/src/main/home/dashboard/Dashboard.tsx

@@ -1,302 +0,0 @@
-import React, { Component } from 'react';
-import styled from 'styled-components';
-
-import Grad from '../../assets/grad.jpg';
-import ServiceFunction from './ServiceFunction';
-import StatusSummary from './StatusSummary';
-import Analytics from './Analytics';
-import { Context } from '../../Context';
-
-import Loading from '../../Loading';
-
-class Dashboard extends Component {
-  state = {
-    demo: false,
-  }
-
-  renderStatusSummary = () => {
-    return (
-        <StatusSummary 
-          resources={this.context.activeProject.resources}
-          namespace={this.context.activeProject.namespace}
-        />          
-    );
-  }
-
-  render() {
-    if (!this.context.activeProject || !this.context.activeProject.namespace) {
-      return (
-        <StyledDashboard>
-          <DashboardWrapper>
-            <Loading fixed={true} />
-          </DashboardWrapper>
-        </StyledDashboard>
-      );
-    }
-    return ( 
-      <StyledDashboard>
-        <DashboardWrapper>
-        <TitleSection demo={this.state.demo}>
-          <ProjectIcon>
-            <ProjectImage src={Grad} />
-            <Overlay>{this.context.activeProject && this.context.activeProject.name[0].toUpperCase()}</Overlay>
-          </ProjectIcon>
-          <Title>{this.context.activeProject && this.context.activeProject.name}</Title>
-          <i 
-            className="material-icons" 
-            onClick={() => { if (!this.state.demo) { this.context.setCurrentModal('UpdateProjectModal') }}}
-          >
-            more_vert
-          </i>
-        </TitleSection>
-
-        <InfoSection>
-          <TopRow>
-            <InfoLabel onClick={()=>this.setState({ info: !this.state.info })}>
-              <i className="material-icons">info</i> Info
-            </InfoLabel>
-            {this.renderStatusSummary()}
-          </TopRow>
-          <Description>{this.context.activeProject && this.context.activeProject.description}</Description>
-        </InfoSection>
-
-        <LineBreak />
-
-        <ServiceSection>
-          <ButtonWrap>
-            <Button onClick={() => {this.context.setCurrentModal('CreateService')}}>
-              <i className="material-icons">add</i>
-              Add a Container
-            </Button>
-            <ConfigButtonAlt onClick={() => {this.context.setCurrentModal('UpdateConfig')}}>
-              <i className="material-icons">add</i>
-              Update ConfigMaps
-            </ConfigButtonAlt>
-          </ButtonWrap>
-
-          <ServiceFunction 
-            namespace={this.context.activeProject.namespace}
-            app={this.context}
-          />
-        </ServiceSection>
-
-        </DashboardWrapper>
-        <Banner>You are currently on your 7 day free trial.</Banner>
-      </StyledDashboard>
-    );
-  }
-}
-
-Dashboard.contextType = Context;
-export default Dashboard;
-
-const Banner = styled.div`
-  position: fixed;
-  bottom: 0;
-  display: flex;
-  left: 0;
-  padding-left: 200px;
-  width: calc(100%);
-  align-items: center;
-  justify-content: center;
-  height: 30px;
-  background: #616FEEcc;
-  color: white;
-  z-index: 1;
-`;
-
-const TopRow = styled.div`
-  display: flex;
-  align-items: center;
-`;
-
-const Description = styled.div`
-  color: ${props => props.theme.font};
-  margin-top: 13px;
-  font-size: 13px;
-`;
-
-const InfoLabel = styled.div`
-  width: 72px;
-  height: 20px;
-  display: flex;
-  align-items: center;
-  color: #7A838F;
-  font-size: 13px;
-  > i {
-    color: #8B949F;
-    font-size: 18px;
-    margin-right: 5px;
-  }
-`;
-
-const InfoSection = styled.div`
-  margin-top: 20px;
-  font-family: 'Work Sans', sans-serif;
-  margin-left: 7px;
-  margin-bottom: 35px;
-`;
-
-const ButtonWrap = styled.div`
-  display: flex;
-  align-items: center;
-  font-size: 18px;
-  margin-top: 2px;
-  margin-bottom: 25px;
-  color: #00000020;
-`;
-
-const Button = styled.div`
-  min-width: 145px;
-  max-width: 145px;
-  display: flex;
-  flex: 1;
-  flex-direction: row;
-  align-items: center;
-  justify-content: space-between;
-  font-size: 13px;
-  cursor: pointer;
-  font-family: 'Work Sans', sans-serif;
-  margin-left: 5px;
-  border-radius: 20px;
-  color: white;
-  padding: 6px 8px;
-  margin-right: 10px;
-  padding-right: 13px;
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-
-  background: #616FEEcc;
-  :hover {
-    background: #505edddd;
-  }
-
-  > i {
-    color: white;
-    width: 18px;
-    height: 18px;
-    font-size: 12px;
-    border-radius: 20px;
-    display: flex;
-    align-items: center;
-    margin-top: -1px;
-    justify-content: center;
-  }
-`;
-
-const ButtonStack = styled(Button)`
-  min-width: 119px;
-  max-width: 119px;
-  background: #616FEEcc;
-  :hover {
-    background: #505edddd;
-  }
-`;
-
-const ButtonAlt = styled(Button)`
-  min-width: 150px;
-  max-width: 150px;
-  background: #7A838Fdd;
-
-  :hover {
-    background: #69727eee;
-  }
-`;
-
-const ConfigButtonAlt = styled(ButtonAlt)`
-  min-width: 166px;
-  max-width: 166px;
-`;
-
-const LineBreak = styled.div`
-  width: calc(100% - 180px);
-  height: 2px;
-  background: ${props => props.theme.lineBreak};
-  margin: 10px 80px 35px;
-`;
-
-const ServiceSection = styled.div`
-  padding-bottom: 150px;
-`;
-
-const Overlay = styled.div`
-  height: 100%;
-  width: 100%;
-  position: absolute;
-  background: #00000011;
-  top: 0;
-  left: 0;
-  border-radius: 5px;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  font-size: 24px;
-  font-weight: 500;
-  font-family: 'Work Sans', sans-serif;
-  color: white;
-`;
-
-const ProjectImage = styled.img`
-  height: 45px;
-  width: 45px;
-  border-radius: 5px;
-`;
-
-const ProjectIcon = styled.div`
-  position: relative;
-  height: 45px;
-  width: 45px;
-  border-radius: 5px;
-`;
-
-const Title = styled.div`
-  font-size: 20px;
-  font-weight: 500;
-  font-family: 'Work Sans', sans-serif;
-  margin-left: 20px;
-  color: ${props => props.theme.dashboardTitle};
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-`;
-
-const TitleSection = styled.div`
-  height: 80px;
-  margin-bottom: 10px;
-  display: flex;
-  flex-direction: row;
-  align-items: center;
-  padding-left: 17px;
-
-  > i {
-    margin-left: 8px;
-    cursor: ${props => props.demo ? 'not-allowed' : 'pointer'};
-    font-size 18px;
-    color: #858FAAaa;
-    padding: 5px;
-    border-radius: 100px;
-    :hover {
-      background: ${props => props.theme.shade};
-    }
-    margin-bottom: -3px;
-  }
-`;
-
-const StyledDashboard = styled.div`
-  height: 100%;
-  width: 100vw;
-  padding-top: 80px;
-  overflow-y: auto;
-  display: flex;
-  flex: 1;
-  justify-content: center;
-  background: ${props => props.theme.bg};
-  position: relative;
-`;
-
-const DashboardWrapper = styled.div`
-  width: 80%;
-  min-width: 300px;
-  padding-bottom: 120px;
-`;

+ 0 - 68
dashboard/src/main/home/dashboard/StatusSummary.tsx

@@ -1,68 +0,0 @@
-import React, { Component, useState, useContext } from 'react';
-import styled from 'styled-components';
-import { useQuery, useSubscription } from '@apollo/client'; 
-import helpers from '../../helpers';
-
-import { SUBSCRIBE_TO_RESOURCE_UPDATES } from '../../queries';
-
-function StatusSummary(props) {
-    let namespace = props.namespace;
-    let resources = props.resources;
-
-    const { ...resourcesSub } = useSubscription(SUBSCRIBE_TO_RESOURCE_UPDATES, {
-        variables: { namespace: namespace }
-    });
-    
-    let cpuUsed = helpers.cpuParser(resources.used['limits.cpu']);
-    let cpuHard = helpers.cpuParser(resources.hard['limits.cpu']);
-    
-    let memUsed = `${helpers.memoryParser(resources.used['limits.memory']) / (1024 ** 2)}Mi`;
-    let memHard = `${helpers.memoryParser(resources.hard['limits.memory']) / (1024 ** 2)}Mi`;
-    
-    if (resourcesSub.data) {
-      cpuUsed = parseFloat(cpuUsed) + parseFloat(resourcesSub.data.resourceUpdates.cpu);
-      memUsed = `${(helpers.memoryParser(resources.used['limits.memory']) + parseFloat(resourcesSub.data.resourceUpdates.memory)) / (1024 ** 2)}Mi`;
-    }
-
-    cpuUsed = Number((cpuUsed).toFixed(2))
-
-    return (
-        <StatusSection>
-        <Indicator /> 
-        <Status> 
-        {`${resources.used.pods ? resources.used.pods : '?'}/${resources.hard.pods ? resources.hard.pods : '?'}`} containers created 
-        </Status>
-        <Indicator /> 
-        <Status> 
-        {`${memUsed}/${memHard}`} RAM reserved 
-        </Status>
-        <Indicator /> 
-        <Status> 
-        {`${cpuUsed}/${cpuHard}`} vCPUs reserved 
-        </Status>    
-        </StatusSection>
-    )
-}
-
-export default StatusSummary;
-
-const StatusSection = styled.div`
-  font-size: 13px;
-  color: ${props => props.theme.statusSummary};
-  display: flex;
-  margin-left: 10px;
-  align-items: center;
-`;
-
-const Indicator = styled.div`
-  min-width: 9px;
-  min-height: 9px;
-  background: ${props => props.theme.indicator};
-  border-radius: 10px;
-  margin-right: 10px;
-`;
-
-const Status = styled.span`
-  font-size: 13px;
-  margin-right: 24px; 
-`

+ 23 - 39
dashboard/src/main/home/modals/ClusterConfigModal.tsx

@@ -4,7 +4,7 @@ import close from '../../../assets/close.png';
 
 import api from '../../../shared/api';
 import { Context } from '../../../shared/Context';
-import { ClusterConfig } from '../../../shared/types';
+import { KubeContextConfig } from '../../../shared/types';
 
 import YamlEditor from '../../../components/YamlEditor';
 import SaveButton from '../../../components/SaveButton';
@@ -14,8 +14,7 @@ type PropsType = {
 
 type StateType = {
   currentTab: string,
-  clusters: ClusterConfig[],
-  selected: boolean[],
+  kubeContexts: KubeContextConfig[],
   rawKubeconfig: string,
   saveKubeconfigStatus: string | null,
   saveSelectedStatus: string | null
@@ -24,8 +23,7 @@ type StateType = {
 export default class ClusterConfigModal extends Component<PropsType, StateType> {
   state = {
     currentTab: 'kubeconfig',
-    clusters: [] as ClusterConfig[],
-    selected: [] as boolean[],
+    kubeContexts: [] as KubeContextConfig[],
     rawKubeconfig: '# If you are using certificate files, include those explicitly',
     saveKubeconfigStatus: null as (string | null),
     saveSelectedStatus: null as (string | null),
@@ -35,26 +33,12 @@ export default class ClusterConfigModal extends Component<PropsType, StateType>
     let { setCurrentError, userId } = this.context;
 
     // Parse kubeconfig to retrieve all possible clusters
-    api.getAllClusters('<token>', {}, { id: userId }, (err: any, res: any) => {
+    api.getContexts('<token>', {}, { id: userId }, (err: any, res: any) => {
       if (err) {
         setCurrentError('getAllClusters: ' + JSON.stringify(err));
       } else {
-        let clusters = res.data;
-        this.setState({ clusters });
-
-        if (clusters && clusters.length > 0) {
-          
-          // Check against list of connected clusters
-          api.getClusters('<token>', {}, { id: userId }, (err: any, res: any) => {
-            if (err) {
-              setCurrentError('getClusters: ' + JSON.stringify(err));
-            } else {
-              console.log(res)
-              let selected = clusters.map((x: ClusterConfig) => res.data.includes(x));
-              this.setState({ selected });
-            }
-          });
-        }
+        console.log(res.data)
+        this.setState({ kubeContexts: res.data })
       }
     });
   }
@@ -64,7 +48,7 @@ export default class ClusterConfigModal extends Component<PropsType, StateType>
 
     api.getUser('<token>', {}, { id: userId }, (err: any, res: any) => {
       if (err) {
-        setCurrentError('getUser: ' + JSON.stringify(err));
+        setCurrentError(JSON.stringify(err));
       } else if (res.data.rawKubeConfig !== '') {
         this.setState({ rawKubeconfig: res.data.rawKubeConfig });
       }
@@ -80,22 +64,22 @@ export default class ClusterConfigModal extends Component<PropsType, StateType>
   };
 
   toggleCluster = (i: number): void => {
-    let newSelected = this.state.selected;
-    newSelected[i] = !this.state.selected[i];
-    this.setState({ selected: newSelected });
+    let newKubeContexts = this.state.kubeContexts;
+    newKubeContexts[i].selected = !newKubeContexts[i].selected;
+    this.setState({ kubeContexts: newKubeContexts });
   };
 
   renderClusterList = (): JSX.Element[] | JSX.Element => {
-    let { clusters, selected } = this.state;
+    let { kubeContexts } = this.state;
 
-    if (clusters && clusters.length > 0) {
-      return clusters.map((cluster: ClusterConfig, i) => {
+    if (kubeContexts && kubeContexts.length > 0) {
+      return kubeContexts.map((kubeContext: KubeContextConfig, i) => {
         return (
           <Row key={i} onClick={() => this.toggleCluster(i)}>
-            <Checkbox checked={selected[i]}>
+            <Checkbox checked={kubeContext.selected}>
               <i className="material-icons">done</i>
             </Checkbox>
-            {cluster.name}
+            {kubeContext.name}
           </Row>
         );
       })
@@ -137,22 +121,22 @@ export default class ClusterConfigModal extends Component<PropsType, StateType>
   }
 
   handleSaveSelected = () => {
-    let { clusters, selected } = this.state;
+    let { kubeContexts } = this.state;
     let { userId } = this.context;
 
     this.setState({ saveSelectedStatus: 'loading' });
-    let allowedClusters: string[] = [];
-    clusters.forEach((x, i) => {
-      if (selected[i]) {
-        allowedClusters.push(x.name);
+    let allowedContexts: string[] = [];
+    kubeContexts.forEach((x, i) => {
+      if (x.selected) {
+        allowedContexts.push(x.name);
       }
     });
 
-    console.log(allowedClusters);
+    console.log(allowedContexts);
     
     api.updateUser(
       '<token>',
-      { allowedClusters },
+      { allowedContexts },
       { id: userId },
       (err: any, res: any) => {
         if (err) {
@@ -190,7 +174,7 @@ export default class ClusterConfigModal extends Component<PropsType, StateType>
         </ClusterList>
         <SaveButton
           text='Save Selected'
-          disabled={this.state.clusters.length === 0}
+          disabled={this.state.kubeContexts.length === 0}
           onClick={this.handleSaveSelected}
           status={this.state.saveSelectedStatus}
         />

+ 8 - 30
dashboard/src/main/home/sidebar/ClusterSection.tsx

@@ -4,7 +4,6 @@ import drawerBg from '../../../assets/drawer-bg.png';
 
 import api from '../../../shared/api';
 import { Context } from '../../../shared/Context';
-import { ClusterConfig } from '../../../shared/types';
 
 import Drawer from './Drawer';
 
@@ -17,31 +16,10 @@ type StateType = {
   configExists: boolean,
   showDrawer: boolean,
   initializedDrawer: boolean,
-  clusters: any[],
+  kubeContexts: string[],
   activeIndex: number,
 };
 
-const dummyClusters: ClusterConfig[]  = [
-  { 
-    name: 'happy-ol-trees', 
-    server: 'idc',
-    context: 'idk',
-    user: 'jusrhee'
-  },
-  { 
-    name: 'joyous-petite-rocks', 
-    server: 'idc',
-    context: 'idk',
-    user: 'jusrhee'
-  },
-  { 
-    name: 'friendly-small-bush', 
-    server: 'idc',
-    context: 'idk',
-    user: 'jusrhee'
-  }
-];
-
 export default class ClusterSection extends Component<PropsType, StateType> {
 
   // Need to track initialized for animation mounting
@@ -49,18 +27,18 @@ export default class ClusterSection extends Component<PropsType, StateType> {
     configExists: true,
     showDrawer: false,
     initializedDrawer: false,
-    clusters: [] as ClusterConfig[],
+    kubeContexts: [] as string[],
     activeIndex: 0,
   };
 
   componentDidMount() {
     let { setCurrentError, userId } = this.context;
 
-    api.getClusters('<token>', {}, { id: userId }, (err: any, res: any) => {      
+    api.getContexts('<token>', {}, { id: userId }, (err: any, res: any) => {      
       if (err) {
         setCurrentError(JSON.stringify(err));
       } else {
-        this.setState({ clusters: res.data });
+        this.setState({ kubeContexts: res });
       }
     });
   }
@@ -88,7 +66,7 @@ export default class ClusterSection extends Component<PropsType, StateType> {
         <Drawer
           toggleDrawer={this.toggleDrawer}
           showDrawer={this.state.showDrawer}
-          clusters={this.state.clusters}
+          kubeContexts={this.state.kubeContexts}
           activeIndex={this.state.activeIndex}
           setActiveIndex={(i: number): void => this.setState({ activeIndex: i })}
         />
@@ -97,14 +75,14 @@ export default class ClusterSection extends Component<PropsType, StateType> {
   };
 
   renderContents = (): JSX.Element => {
-    let { clusters, activeIndex, showDrawer } = this.state;
+    let { kubeContexts, activeIndex, showDrawer } = this.state;
 
-    if (clusters.length > 0) {
+    if (kubeContexts.length > 0) {
       return (
         <ClusterSelector showDrawer={showDrawer}>
           <LinkWrapper>
             <ClusterIcon><i className="material-icons">polymer</i></ClusterIcon>
-            <ClusterName>{clusters[activeIndex].name}</ClusterName>
+            <ClusterName>{kubeContexts[activeIndex]}</ClusterName>
           </LinkWrapper>
           <DrawerButton onClick={this.toggleDrawer}>
             <BgAccent src={drawerBg} />

+ 3 - 4
dashboard/src/main/home/sidebar/Drawer.tsx

@@ -3,12 +3,11 @@ import styled from 'styled-components';
 import close from '../../../assets/close.png';
 
 import { Context } from '../../../shared/Context';
-import { ClusterConfig } from '../../../shared/types';
 
 type PropsType = {
   toggleDrawer: () => void,
   showDrawer: boolean,
-  clusters: ClusterConfig[],
+  kubeContexts: string[],
   activeIndex: number,
   setActiveIndex: (i: number) => void
 };
@@ -19,7 +18,7 @@ type StateType = {
 export default class Drawer extends Component<PropsType, StateType> {
 
   renderClusterList = (): JSX.Element[] => {
-    return this.props.clusters.map((cluster, i) => {
+    return this.props.kubeContexts.map((kubeContext: string, i: number) => {
       /*
       let active = this.context.activeProject &&
         this.context.activeProject.namespace == val.namespace; 
@@ -32,7 +31,7 @@ export default class Drawer extends Component<PropsType, StateType> {
           onClick={() => this.props.setActiveIndex(i)}
         >
           <ClusterIcon><i className="material-icons">polymer</i></ClusterIcon>
-          <ClusterName>{cluster.name}</ClusterName>
+          <ClusterName>{kubeContext}</ClusterName>
         </ClusterOption>
       );
     });

+ 0 - 3
dashboard/src/main/home/sidebar/Sidebar.tsx

@@ -118,9 +118,6 @@ export default class Sidebar extends Component<PropsType, StateType> {
           />
 
           <BottomSection>
-            <LogOutButton onClick={this.handleLogout}>
-              <i className="material-icons">keyboard_return</i> DevOps Mode
-            </LogOutButton>
             <LogOutButton onClick={this.handleLogout}>
               Log Out <i className="material-icons">keyboard_return</i>
             </LogOutButton>

+ 1 - 1
dashboard/src/shared/Context.tsx

@@ -48,7 +48,7 @@ class ContextProvider extends Component {
   };
 
   componentDidMount() {
-    this.setState({ userId: 3 });
+    this.setState({ userId: 1 });
   }
 
   render() {

+ 4 - 9
dashboard/src/shared/api.tsx

@@ -29,17 +29,13 @@ const getUser = baseApi<{}, { id: number }>('GET', pathParams => {
 
 const updateUser = baseApi<{
   rawKubeConfig?: string,
-  allowedClusters?: string[]
+  allowedContexts?: string[]
 }, { id: number }>('PUT', pathParams => {
   return `/api/users/${pathParams.id}`;
 });
 
-const getClusters = baseApi<{}, { id: number }>('GET', pathParams => {
-  return `/api/users/${pathParams.id}/clusters`;
-});
-
-const getAllClusters = baseApi<{}, { id: number }>('GET', pathParams => {
-  return `/api/users/${pathParams.id}/clusters/all`;
+const getContexts = baseApi<{}, { id: number }>('GET', pathParams => {
+  return `/api/users/${pathParams.id}/contexts`;
 });
 
 // Bundle export to allow default api import (api.<method> is more readable)
@@ -50,6 +46,5 @@ export default {
   logOutUser,
   getUser,
   updateUser,
-  getClusters,
-  getAllClusters
+  getContexts,
 }

+ 3 - 2
dashboard/src/shared/types.tsx

@@ -1,6 +1,7 @@
-export interface ClusterConfig {
+export interface KubeContextConfig {
+  cluster: string,
   name: string,
+  selected?: boolean,
   server: string,
-  context: string,
   user: string
 }