Преглед на файлове

adding compare version functionality

Feroze Mohideen преди 3 години
родител
ревизия
dbf0504cd4

+ 19 - 5
dashboard/src/main/home/cluster-dashboard/expanded-chart/ExpandedChart.tsx

@@ -52,6 +52,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
   const [currentChart, setCurrentChart] = useState<ChartType>(
   const [currentChart, setCurrentChart] = useState<ChartType>(
     props.currentChart
     props.currentChart
   );
   );
+  const [compareChart, setCompareChart] = useState<ChartType>(null);
   const [showRevisions, setShowRevisions] = useState<boolean>(false);
   const [showRevisions, setShowRevisions] = useState<boolean>(false);
   const [loading, setLoading] = useState<boolean>(false);
   const [loading, setLoading] = useState<boolean>(false);
   const [components, setComponents] = useState<ResourceType[]>([]);
   const [components, setComponents] = useState<ResourceType[]>([]);
@@ -79,6 +80,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
   const [logData, setLogData] = useState<InitLogData>({});
   const [logData, setLogData] = useState<InitLogData>({});
   const [overrideCurrentTab, setOverrideCurrentTab] = useState("");
   const [overrideCurrentTab, setOverrideCurrentTab] = useState("");
   const [isAgentInstalled, setIsAgentInstalled] = useState<boolean>(false);
   const [isAgentInstalled, setIsAgentInstalled] = useState<boolean>(false);
+  const [comparisonMode, setComparisonMode] = useState<boolean>(false);
 
 
   const {
   const {
     isStack,
     isStack,
@@ -192,7 +194,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
           if (
           if (
             oldControllers &&
             oldControllers &&
             oldControllers[object.metadata.uid]?.status?.conditions ==
             oldControllers[object.metadata.uid]?.status?.conditions ==
-              object.status?.conditions
+            object.status?.conditions
           ) {
           ) {
             return oldControllers;
             return oldControllers;
           }
           }
@@ -525,6 +527,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
         return (
         return (
           <ValuesYaml
           <ValuesYaml
             currentChart={chart}
             currentChart={chart}
+            compareChart={compareChart}
             refreshChart={() => getChartData(currentChart)}
             refreshChart={() => getChartData(currentChart)}
             disabled={!isAuthorized("application", "", ["get", "update"])}
             disabled={!isAuthorized("application", "", ["get", "update"])}
           />
           />
@@ -612,6 +615,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
 
 
     setIsPreview(!isCurrent);
     setIsPreview(!isCurrent);
     getChartData(chart);
     getChartData(chart);
+    setCurrentChart(chart);
   };
   };
 
 
   // TODO: consolidate with pop + push in refreshTabs
   // TODO: consolidate with pop + push in refreshTabs
@@ -886,7 +890,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
               isFullscreen={true}
               isFullscreen={true}
               setIsFullscreen={setIsFullscreen}
               setIsFullscreen={setIsFullscreen}
               currentChart={currentChart}
               currentChart={currentChart}
-              setInitData={() => {}}
+              setInitData={() => { }}
             />
             />
           ) : (
           ) : (
             <StyledExpandedChart>
             <StyledExpandedChart>
@@ -956,6 +960,7 @@ const ExpandedChart: React.FC<Props> = (props) => {
                       setShowRevisions(!showRevisions);
                       setShowRevisions(!showRevisions);
                     }}
                     }}
                     chart={currentChart}
                     chart={currentChart}
+                    compareChart={compareChart}
                     refreshChart={() => getChartData(currentChart)}
                     refreshChart={() => getChartData(currentChart)}
                     setRevision={setRevision}
                     setRevision={setRevision}
                     forceRefreshRevisions={forceRefreshRevisions}
                     forceRefreshRevisions={forceRefreshRevisions}
@@ -963,10 +968,19 @@ const ExpandedChart: React.FC<Props> = (props) => {
                     shouldUpdate={
                     shouldUpdate={
                       currentChart.latest_version &&
                       currentChart.latest_version &&
                       currentChart.latest_version !==
                       currentChart.latest_version !==
-                        currentChart.chart.metadata.version
+                      currentChart.chart.metadata.version
                     }
                     }
+                    setCompareChart={setCompareChart}
                     latestVersion={currentChart.latest_version}
                     latestVersion={currentChart.latest_version}
                     upgradeVersion={handleUpgradeVersion}
                     upgradeVersion={handleUpgradeVersion}
+                    comparisonMode={comparisonMode}
+                    toggleComparisonMode={() => {
+                      if (!comparisonMode) {
+                        setOverrideCurrentTab('values');
+
+                      }
+                      setComparisonMode(!comparisonMode);
+                    }}
                   />
                   />
                   {isStack && isLoadingStackEnvGroups ? (
                   {isStack && isLoadingStackEnvGroups ? (
                     <>
                     <>
@@ -1169,11 +1183,11 @@ const TabButton = styled.div`
   border-radius: 20px;
   border-radius: 20px;
   text-shadow: 0px 0px 8px
   text-shadow: 0px 0px 8px
     ${(props: { devOpsMode: boolean }) =>
     ${(props: { devOpsMode: boolean }) =>
-      props.devOpsMode ? "#ffffff66" : "none"};
+    props.devOpsMode ? "#ffffff66" : "none"};
   cursor: pointer;
   cursor: pointer;
   :hover {
   :hover {
     color: ${(props: { devOpsMode: boolean }) =>
     color: ${(props: { devOpsMode: boolean }) =>
-      props.devOpsMode ? "" : "#aaaabb99"};
+    props.devOpsMode ? "" : "#aaaabb99"};
   }
   }
 
 
   > i {
   > i {

+ 55 - 10
dashboard/src/main/home/cluster-dashboard/expanded-chart/RevisionSection.tsx

@@ -24,6 +24,10 @@ type PropsType = WithAuthProps & {
   latestVersion: string;
   latestVersion: string;
   showRevisions?: boolean;
   showRevisions?: boolean;
   toggleShowRevisions?: () => void;
   toggleShowRevisions?: () => void;
+  comparisonMode: boolean;
+  toggleComparisonMode: () => void;
+  setCompareChart: (chart: ChartType) => void;
+  compareChart?: ChartType;
 };
 };
 
 
 type StateType = {
 type StateType = {
@@ -73,6 +77,7 @@ class RevisionSection extends Component<PropsType, StateType> {
       .catch(console.log);
       .catch(console.log);
   };
   };
 
 
+
   componentDidMount() {
   componentDidMount() {
     this.refreshHistory();
     this.refreshHistory();
     this.connectToLiveUpdates();
     this.connectToLiveUpdates();
@@ -146,6 +151,7 @@ class RevisionSection extends Component<PropsType, StateType> {
       this.refreshHistory().then(() => {
       this.refreshHistory().then(() => {
         this.props.setRevision(this.state.revisions[0], true);
         this.props.setRevision(this.state.revisions[0], true);
       });
       });
+
     } else if (this.props.chart !== prevProps.chart) {
     } else if (this.props.chart !== prevProps.chart) {
       this.refreshHistory();
       this.refreshHistory();
     }
     }
@@ -184,12 +190,28 @@ class RevisionSection extends Component<PropsType, StateType> {
   };
   };
 
 
   handleClickRevision = (revision: ChartType) => {
   handleClickRevision = (revision: ChartType) => {
-    this.props.setRevision(
-      revision,
-      revision.version === this.state.maxVersion
-    );
+    if (this.props.comparisonMode) {
+      this.props.setCompareChart(revision);
+    } else {
+      this.props.setRevision(
+        revision,
+        revision.version === this.state.maxVersion
+      );
+    }
   };
   };
 
 
+  startComparison = () => {
+    this.props.setCompareChart(
+      this.props.comparisonMode ?
+        null
+        :
+        this.props.chart.version > 0 ?
+          this.state.revisions.find((revision) => revision.version === this.props.chart.version - 1)
+          :
+          null);
+    this.props.toggleComparisonMode();
+  }
+
   renderRevisionList = () => {
   renderRevisionList = () => {
     return this.state.revisions.map((revision: ChartType, i: number) => {
     return this.state.revisions.map((revision: ChartType, i: number) => {
       let isCurrent = revision.version === this.state.maxVersion;
       let isCurrent = revision.version === this.state.maxVersion;
@@ -206,7 +228,7 @@ class RevisionSection extends Component<PropsType, StateType> {
         <Tr
         <Tr
           key={i}
           key={i}
           onClick={() => this.handleClickRevision(revision)}
           onClick={() => this.handleClickRevision(revision)}
-          selected={this.props.chart.version === revision.version}
+          selected={this.props.chart.version === revision.version || this.props.compareChart?.version === revision.version}
         >
         >
           <Td>{revision.version}</Td>
           <Td>{revision.version}</Td>
           <Td>{readableDate(revision.info.last_deployed)}</Td>
           <Td>{readableDate(revision.info.last_deployed)}</Td>
@@ -251,7 +273,7 @@ class RevisionSection extends Component<PropsType, StateType> {
   };
   };
 
 
   renderExpanded = () => {
   renderExpanded = () => {
-    if (this.state.expandRevisions) {
+    if (this.state.expandRevisions || this.props.comparisonMode) {
       return (
       return (
         <TableWrapper>
         <TableWrapper>
           <RevisionsTable>
           <RevisionsTable>
@@ -342,6 +364,16 @@ class RevisionSection extends Component<PropsType, StateType> {
               </RevisionUpdateMessage>
               </RevisionUpdateMessage>
             </div>
             </div>
           )}
           )}
+          <CompareVersionsWrapper>
+            <CompareVersionsToggle
+              checked={this.props.comparisonMode}
+              disabled={this.state.revisions.length < 2}
+              onChange={this.startComparison}
+              onClick={(e) => {
+                e.stopPropagation();
+              }} />
+            <span>Compare Versions</span>
+          </CompareVersionsWrapper>
         </RevisionHeader>
         </RevisionHeader>
         <RevisionList>{this.renderExpanded()}</RevisionList>
         <RevisionList>{this.renderExpanded()}</RevisionList>
       </div>
       </div>
@@ -418,7 +450,7 @@ const RollbackButton = styled.div`
     props.disabled ? "#aaaabbee" : "#616FEEcc"};
     props.disabled ? "#aaaabbee" : "#616FEEcc"};
   :hover {
   :hover {
     background: ${(props: { disabled: boolean }) =>
     background: ${(props: { disabled: boolean }) =>
-      props.disabled ? "" : "#405eddbb"};
+    props.disabled ? "" : "#405eddbb"};
   }
   }
 `;
 `;
 
 
@@ -430,8 +462,10 @@ const Tr = styled.tr`
     props.selected ? "#ffffff11" : ""};
     props.selected ? "#ffffff11" : ""};
   :hover {
   :hover {
     background: ${(props: { disableHover?: boolean; selected?: boolean }) =>
     background: ${(props: { disableHover?: boolean; selected?: boolean }) =>
-      props.disableHover ? "" : "#ffffff22"};
+    props.disableHover ? "" : "#ffffff22"};
   }
   }
+  border: ${(props: { disableHover?: boolean; selected?: boolean }) =>
+    props.selected ? "2px solid #8590ff" : ""};
 `;
 `;
 
 
 const Td = styled.td`
 const Td = styled.td`
@@ -485,9 +519,9 @@ const RevisionHeader = styled.div`
     cursor: pointer;
     cursor: pointer;
     border-radius: 20px;
     border-radius: 20px;
     background: ${(props: { showRevisions: boolean; isCurrent: boolean }) =>
     background: ${(props: { showRevisions: boolean; isCurrent: boolean }) =>
-      props.showRevisions ? "#ffffff18" : ""};
+    props.showRevisions ? "#ffffff18" : ""};
     transform: ${(props: { showRevisions: boolean; isCurrent: boolean }) =>
     transform: ${(props: { showRevisions: boolean; isCurrent: boolean }) =>
-      props.showRevisions ? "rotate(180deg)" : ""};
+    props.showRevisions ? "rotate(180deg)" : ""};
   }
   }
 `;
 `;
 
 
@@ -519,8 +553,15 @@ const StyledRevisionSection = styled.div`
 const RevisionPreview = styled.div`
 const RevisionPreview = styled.div`
   display: flex;
   display: flex;
   align-items: center;
   align-items: center;
+  justify-content: space-between;
 `;
 `;
 
 
+const CompareVersionsWrapper = styled.div`
+  display: flex;
+  align-items: center;
+  padding-right: 15px;
+`
+
 const RevisionUpdateMessage = styled.div`
 const RevisionUpdateMessage = styled.div`
   color: white;
   color: white;
   display: flex;
   display: flex;
@@ -548,3 +589,7 @@ const A = styled.a`
   text-decoration: underline;
   text-decoration: underline;
   cursor: pointer;
   cursor: pointer;
 `;
 `;
+
+const CompareVersionsToggle = styled.input.attrs({ type: 'checkbox' })`
+  
+`;

+ 41 - 21
dashboard/src/main/home/cluster-dashboard/expanded-chart/ValuesYaml.tsx

@@ -9,15 +9,18 @@ import { Context } from "shared/Context";
 
 
 import YamlEditor from "components/YamlEditor";
 import YamlEditor from "components/YamlEditor";
 import SaveButton from "components/SaveButton";
 import SaveButton from "components/SaveButton";
+import ReactDiffViewer from "react-diff-viewer";
 
 
 type PropsType = {
 type PropsType = {
   currentChart: ChartType;
   currentChart: ChartType;
+  compareChart?: ChartType;
   refreshChart: () => void;
   refreshChart: () => void;
   disabled?: boolean;
   disabled?: boolean;
 };
 };
 
 
 type StateType = {
 type StateType = {
   values: string;
   values: string;
+  compareValues: string;
   saveValuesStatus: string | null;
   saveValuesStatus: string | null;
 };
 };
 
 
@@ -25,15 +28,20 @@ type StateType = {
 export default class ValuesYaml extends Component<PropsType, StateType> {
 export default class ValuesYaml extends Component<PropsType, StateType> {
   state = {
   state = {
     values: "",
     values: "",
+    compareValues: "",
     saveValuesStatus: null as string | null,
     saveValuesStatus: null as string | null,
   };
   };
 
 
   updateValues() {
   updateValues() {
     let values = "# Nothing here yet";
     let values = "# Nothing here yet";
+    let compareValues = "# Nothing here yet";
     if (this.props.currentChart.config) {
     if (this.props.currentChart.config) {
       values = yaml.dump(this.props.currentChart.config);
       values = yaml.dump(this.props.currentChart.config);
+      if (this.props.compareChart?.config) {
+        compareValues = yaml.dump(this.props.compareChart.config);
+      }
     }
     }
-    this.setState({ values });
+    this.setState({ values, compareValues });
   }
   }
 
 
   componentDidMount() {
   componentDidMount() {
@@ -41,7 +49,7 @@ export default class ValuesYaml extends Component<PropsType, StateType> {
   }
   }
 
 
   componentDidUpdate(prevProps: PropsType) {
   componentDidUpdate(prevProps: PropsType) {
-    if (this.props.currentChart !== prevProps.currentChart) {
+    if (this.props.currentChart !== prevProps.currentChart || this.props.compareChart !== prevProps.compareChart) {
       this.updateValues();
       this.updateValues();
     }
     }
   }
   }
@@ -94,26 +102,38 @@ export default class ValuesYaml extends Component<PropsType, StateType> {
 
 
   render() {
   render() {
     return (
     return (
-      <StyledValuesYaml>
-        <Wrapper>
-          <YamlEditor
-            value={this.state.values}
-            onChange={(e: any) => this.setState({ values: e })}
-            readOnly={this.props.disabled}
-            height="calc(100vh - 412px)"
+      <>
+        {this.props.compareChart ?
+          <ReactDiffViewer
+            oldValue={this.state.values}
+            newValue={this.state.compareValues}
+            splitView
+            useDarkTheme
+            leftTitle={`Version ${this.props.currentChart.version.toString()}`}
+            rightTitle={`Version ${this.props.compareChart.version.toString()}`}
           />
           />
-        </Wrapper>
-        {!this.props.disabled && (
-          <SaveButton
-            text="Update values"
-            onClick={this.handleSaveValues}
-            status={this.state.saveValuesStatus}
-            statusPosition="right"
-            clearPosition={true}
-            makeFlush={true}
-          />
-        )}
-      </StyledValuesYaml>
+          :
+          <StyledValuesYaml>
+            <Wrapper>
+              <YamlEditor
+                value={this.state.values}
+                onChange={(e: any) => this.setState({ values: e })}
+                readOnly={this.props.disabled}
+                height="calc(100vh - 412px)"
+              />
+            </Wrapper>
+            {!this.props.disabled && (
+              <SaveButton
+                text="Update values"
+                onClick={this.handleSaveValues}
+                status={this.state.saveValuesStatus}
+                statusPosition="right"
+                clearPosition={true}
+                makeFlush={true}
+              />
+            )}
+          </StyledValuesYaml>}
+      </>
     );
     );
   }
   }
 }
 }