]> source.dussan.org Git - sonarqube.git/commitdiff
drop favorites from redux store (#631)
authorStas Vilchik <stas.vilchik@sonarsource.com>
Wed, 22 Aug 2018 11:06:28 +0000 (13:06 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 22 Aug 2018 18:21:22 +0000 (20:21 +0200)
16 files changed:
server/sonar-web/src/main/js/api/components.ts
server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts
server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js [deleted file]
server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/component/components/__tests__/__snapshots__/App-test.tsx.snap
server/sonar-web/src/main/js/components/SourceViewer/SourceViewer.tsx
server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx
server/sonar-web/src/main/js/components/SourceViewer/SourceViewerHeader.tsx
server/sonar-web/src/main/js/components/controls/FavoriteBase.tsx
server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.tsx [deleted file]
server/sonar-web/src/main/js/components/controls/FavoriteContainer.ts [deleted file]
server/sonar-web/src/main/js/components/controls/__tests__/FavoriteBaseStateless-test.tsx [deleted file]
server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/FavoriteBaseStateless-test.tsx.snap [deleted file]
server/sonar-web/src/main/js/components/workspace/__tests__/__snapshots__/WorkspaceComponentViewer-test.tsx.snap
server/sonar-web/src/main/js/store/favorites/duck.ts [deleted file]
server/sonar-web/src/main/js/store/rootReducer.js

index 899e6a1c4503a724e16a5b409d82bb4bca0875ed..671fb298cbf11a6fda9654cf1cd9fa0438edb1bb 100644 (file)
@@ -26,7 +26,8 @@ import {
   MyProject,
   Metric,
   ComponentMeasure,
-  LightComponent
+  LightComponent,
+  SourceViewerFile
 } from '../app/types';
 
 export interface BaseSearchProjectsParameters {
@@ -287,7 +288,7 @@ export function getSuggestions(
 
 export function getComponentForSourceViewer(
   data: { component: string } & BranchParameters
-): Promise<any> {
+): Promise<SourceViewerFile> {
   return getJSON('/api/components/app', data);
 }
 
index e86d1d372d2a1b02fdad194304fec71d07e54726..36abc33bb097de0492ee43f713a366b21184773d 100644 (file)
@@ -27,7 +27,7 @@ import * as request from '../../../helpers/request';
 import DateFromNow from '../../../components/intl/DateFromNow';
 import DateFormatter from '../../../components/intl/DateFormatter';
 import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
-import FavoriteContainer from '../../../components/controls/FavoriteContainer';
+import Favorite from '../../../components/controls/Favorite';
 import HomePageSelect from '../../../components/controls/HomePageSelect';
 import ListFooter from '../../../components/controls/ListFooter';
 import Modal from '../../../components/controls/Modal';
@@ -86,7 +86,7 @@ const exposeLibraries = () => {
     DropdownIcon,
     DuplicationsRating,
     EditButton,
-    FavoriteContainer,
+    Favorite,
     HelpIcon,
     HelpTooltip,
     HomePageSelect,
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.js
deleted file mode 100644 (file)
index 627913a..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import { connect } from 'react-redux';
-import FavoriteContainer from '../../../components/controls/FavoriteContainer';
-import { getComponentForSourceViewer } from '../../../api/components';
-import { receiveFavorites } from '../../../store/favorites/duck';
-import { isMainBranch } from '../../../helpers/branches';
-
-/*:: type FavComponent = { key: string, canMarkAsFavorite: boolean, fav: boolean }; */
-
-/*:: type Props = {
-  branchLike?: { id?: string; name: string },
-  className?: string,
-  component: string,
-  onReceiveComponent: (component: FavComponent) => void
-}; */
-
-/*:: type State = { component: ?FavComponent }; */
-
-class MeasureFavoriteContainer extends React.PureComponent {
-  /*:: mounted: boolean; */
-  /*:: props: Props; */
-  state /*: State */ = {
-    component: null
-  };
-
-  componentDidMount() {
-    this.mounted = true;
-    this.fetchComponentFavorite(this.props);
-  }
-
-  componentWillReceiveProps(nextProps /*: Props */) {
-    if (nextProps.component !== this.props.component) {
-      this.fetchComponentFavorite(nextProps);
-    }
-  }
-
-  componentWillUnmount() {
-    this.mounted = false;
-  }
-
-  fetchComponentFavorite({ component, onReceiveComponent } /*: Props */) {
-    getComponentForSourceViewer({ component }).then(component => {
-      this.setState({ component });
-      onReceiveComponent(component);
-    });
-  }
-
-  render() {
-    const { component } = this.state;
-    if (
-      component == null ||
-      !component.canMarkAsFavorite ||
-      (this.props.branchLike && !isMainBranch(this.props.branchLike))
-    ) {
-      return null;
-    }
-    return (
-      <FavoriteContainer className={this.props.className} componentKey={this.props.component} />
-    );
-  }
-}
-
-const mapStateToProps = null;
-
-const mapDispatchToProps = {
-  onReceiveComponent: (component /*: FavComponent */) => dispatch => {
-    if (component.canMarkAsFavorite) {
-      const favorites = [];
-      const notFavorites = [];
-      if (component.fav) {
-        favorites.push({ key: component.key });
-      } else {
-        notFavorites.push({ key: component.key });
-      }
-      dispatch(receiveFavorites(favorites, notFavorites));
-    }
-  }
-};
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(MeasureFavoriteContainer);
diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.tsx b/server/sonar-web/src/main/js/apps/component-measures/components/MeasureFavoriteContainer.tsx
new file mode 100644 (file)
index 0000000..d062ad6
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import Favorite from '../../../components/controls/Favorite';
+import { getComponentForSourceViewer } from '../../../api/components';
+import { isMainBranch } from '../../../helpers/branches';
+import { BranchLike, SourceViewerFile } from '../../../app/types';
+
+type FavComponent = Pick<SourceViewerFile, 'canMarkAsFavorite' | 'fav' | 'key' | 'q'>;
+
+interface Props {
+  branchLike?: BranchLike;
+  className?: string;
+  component: string;
+}
+
+interface State {
+  component?: FavComponent;
+}
+
+export default class MeasureFavoriteContainer extends React.PureComponent<Props, State> {
+  mounted = false;
+  state: State = {};
+
+  componentDidMount() {
+    this.mounted = true;
+    this.fetchComponentFavorite();
+  }
+
+  componentDidUpdate(prevProps: Props) {
+    if (prevProps.component !== this.props.component) {
+      this.fetchComponentFavorite();
+    }
+  }
+
+  componentWillUnmount() {
+    this.mounted = false;
+  }
+
+  fetchComponentFavorite() {
+    getComponentForSourceViewer({ component: this.props.component }).then(
+      component => {
+        if (this.mounted) {
+          this.setState({ component });
+        }
+      },
+      () => {}
+    );
+  }
+
+  render() {
+    const { component } = this.state;
+    if (
+      !component ||
+      !component.canMarkAsFavorite ||
+      (this.props.branchLike && !isMainBranch(this.props.branchLike))
+    ) {
+      return null;
+    }
+    return (
+      <Favorite
+        className={this.props.className}
+        component={component.key}
+        favorite={component.fav || false}
+        qualifier={component.q}
+      />
+    );
+  }
+}
index c513d6b7a6d2dd0fcc8eb00ec82aed9dc38d8e2f..80a0c87199cccb0648d909ea95eea24fd88ac375 100644 (file)
@@ -4,7 +4,7 @@ exports[`renders 1`] = `
 <div
   className="page page-limited"
 >
-  <Connect(LazyLoader)
+  <LazyLoader
     aroundLine={7}
     branchLike={
       Object {
index 5e6a563abf25e86e7b36dea151e75e00bb9318ad..f322716526afb7f339e54a95ce51f5a6ef43b786 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
-import { Dispatch } from 'redux';
-import { connect, Omit } from 'react-redux';
-import { Props } from './SourceViewerBase';
 import { lazyLoad } from '../lazyLoad';
-import { SourceViewerFile } from '../../app/types';
-import { receiveFavorites } from '../../store/favorites/duck';
 
-const mapStateToProps = null;
-
-interface DispatchProps {
-  onReceiveComponent: (component: SourceViewerFile) => void;
-}
-
-const onReceiveComponent = (component: SourceViewerFile) => (dispatch: Dispatch<any>) => {
-  if (component.canMarkAsFavorite) {
-    const favorites = [];
-    const notFavorites = [];
-    if (component.fav) {
-      favorites.push({ key: component.key });
-    } else {
-      notFavorites.push({ key: component.key });
-    }
-    dispatch(receiveFavorites(favorites, notFavorites));
-  }
-};
-
-const mapDispatchToProps: DispatchProps = { onReceiveComponent };
-
-type OwnProps = Omit<Props, keyof DispatchProps>;
-
-export default connect<null, DispatchProps, OwnProps>(
-  mapStateToProps,
-  mapDispatchToProps
-)(lazyLoad(() => import(/* webpackPrefetch: true */ './SourceViewerBase')));
+const SourceViewer = lazyLoad(() => import(/* webpackPrefetch: true */ './SourceViewerBase'));
+export default SourceViewer;
index c403c76d948064bd757bc5a1492b13fd4eeacd80..6ea9df12ea08391b715fc6d2124ab21d65a965aa 100644 (file)
@@ -67,17 +67,17 @@ export interface Props {
   // but kept to maintaint the location indexes
   highlightedLocations?: (FlowLocation | undefined)[];
   highlightedLocationMessage?: { index: number; text: string | undefined };
-  loadComponent?: (
+  loadComponent: (
     component: string,
     branchLike: BranchLike | undefined
   ) => Promise<SourceViewerFile>;
-  loadIssues?: (
+  loadIssues: (
     component: string,
     from: number,
     to: number,
     branchLike: BranchLike | undefined
   ) => Promise<Issue[]>;
-  loadSources?: (
+  loadSources: (
     component: string,
     from: number,
     to: number,
@@ -88,7 +88,6 @@ export interface Props {
   onIssueChange?: (issue: Issue) => void;
   onIssueSelect?: (issueKey: string) => void;
   onIssueUnselect?: () => void;
-  onReceiveComponent: (component: SourceViewerFile) => void;
   scroll?: (element: HTMLElement) => void;
   selectedIssue?: string;
 }
@@ -128,7 +127,10 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
     displayAllIssues: false,
     displayIssueLocationsCount: true,
     displayIssueLocationsLink: true,
-    displayLocationMarkers: true
+    displayLocationMarkers: true,
+    loadComponent: defaultLoadComponent,
+    loadIssues: defaultLoadIssues,
+    loadSources: defaultLoadSources
   };
 
   constructor(props: Props) {
@@ -204,21 +206,6 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
     this.mounted = false;
   }
 
-  // react typings do not take `defaultProps` into account,
-  // so use these getters to get type-safe methods
-
-  get safeLoadComponent() {
-    return this.props.loadComponent || defaultLoadComponent;
-  }
-
-  get safeLoadIssues() {
-    return this.props.loadIssues || defaultLoadIssues;
-  }
-
-  get safeLoadSources() {
-    return this.props.loadSources || defaultLoadSources;
-  }
-
   computeCoverageStatus(lines: SourceLine[]) {
     return lines.map(line => ({ ...line, coverageStatus: getCoverageStatus(line) }));
   }
@@ -237,7 +224,7 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
   fetchComponent() {
     this.setState({ loading: true });
     const loadIssues = (component: SourceViewerFile, sources: SourceLine[]) => {
-      this.safeLoadIssues(this.props.component, 1, LINES, this.props.branchLike).then(
+      this.props.loadIssues(this.props.component, 1, LINES, this.props.branchLike).then(
         issues => {
           if (this.mounted) {
             const finalSources = sources.slice(0, LINES);
@@ -301,7 +288,6 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
     };
 
     const onResolve = (component: SourceViewerFile) => {
-      this.props.onReceiveComponent(component);
       const sourcesRequest =
         component.q === 'FIL' || component.q === 'UTS' ? this.loadSources() : Promise.resolve([]);
       sourcesRequest.then(
@@ -310,10 +296,9 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
       );
     };
 
-    this.safeLoadComponent(this.props.component, this.props.branchLike).then(
-      onResolve,
-      onFailLoadComponent
-    );
+    this.props
+      .loadComponent(this.props.component, this.props.branchLike)
+      .then(onResolve, onFailLoadComponent);
   }
 
   fetchSources() {
@@ -346,25 +331,27 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
     }
     const firstSourceLine = this.state.sources[0];
     const lastSourceLine = this.state.sources[this.state.sources.length - 1];
-    this.safeLoadIssues(
-      this.props.component,
-      firstSourceLine && firstSourceLine.line,
-      lastSourceLine && lastSourceLine.line,
-      this.props.branchLike
-    ).then(
-      issues => {
-        if (this.mounted) {
-          this.setState({
-            issues,
-            issuesByLine: issuesByLine(issues),
-            issueLocationsByLine: locationsByLine(issues)
-          });
+    this.props
+      .loadIssues(
+        this.props.component,
+        firstSourceLine && firstSourceLine.line,
+        lastSourceLine && lastSourceLine.line,
+        this.props.branchLike
+      )
+      .then(
+        issues => {
+          if (this.mounted) {
+            this.setState({
+              issues,
+              issuesByLine: issuesByLine(issues),
+              issueLocationsByLine: locationsByLine(issues)
+            });
+          }
+        },
+        () => {
+          // TODO
         }
-      },
-      () => {
-        // TODO
-      }
-    );
+      );
   }
 
   loadSources = (): Promise<SourceLine[]> => {
@@ -390,10 +377,9 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
       // request one additional line to define `hasSourcesAfter`
       to++;
 
-      return this.safeLoadSources(this.props.component, from, to, this.props.branchLike).then(
-        sources => resolve(sources),
-        onFailLoadSources
-      );
+      return this.props
+        .loadSources(this.props.component, from, to, this.props.branchLike)
+        .then(sources => resolve(sources), onFailLoadSources);
     });
   };
 
@@ -404,46 +390,43 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
     const firstSourceLine = this.state.sources[0];
     this.setState({ loadingSourcesBefore: true });
     const from = Math.max(1, firstSourceLine.line - LINES);
-    this.safeLoadSources(
-      this.props.component,
-      from,
-      firstSourceLine.line - 1,
-      this.props.branchLike
-    ).then(
-      sources => {
-        this.safeLoadIssues(
-          this.props.component,
-          from,
-          firstSourceLine.line - 1,
-          this.props.branchLike
-        ).then(
-          issues => {
-            if (this.mounted) {
-              this.setState(prevState => {
-                const nextIssues = uniqBy(
-                  [...issues, ...(prevState.issues || [])],
-                  issue => issue.key
-                );
-                return {
-                  issues: nextIssues,
-                  issuesByLine: issuesByLine(nextIssues),
-                  issueLocationsByLine: locationsByLine(nextIssues),
-                  loadingSourcesBefore: false,
-                  sources: [...this.computeCoverageStatus(sources), ...(prevState.sources || [])],
-                  symbolsByLine: { ...prevState.symbolsByLine, ...symbolsByLine(sources) }
-                };
-              });
-            }
-          },
-          () => {
-            // TODO
-          }
-        );
-      },
-      () => {
-        // TODO
-      }
-    );
+    this.props
+      .loadSources(this.props.component, from, firstSourceLine.line - 1, this.props.branchLike)
+      .then(
+        sources => {
+          this.props
+            .loadIssues(this.props.component, from, firstSourceLine.line - 1, this.props.branchLike)
+            .then(
+              issues => {
+                if (this.mounted) {
+                  this.setState(prevState => {
+                    const nextIssues = uniqBy(
+                      [...issues, ...(prevState.issues || [])],
+                      issue => issue.key
+                    );
+                    return {
+                      issues: nextIssues,
+                      issuesByLine: issuesByLine(nextIssues),
+                      issueLocationsByLine: locationsByLine(nextIssues),
+                      loadingSourcesBefore: false,
+                      sources: [
+                        ...this.computeCoverageStatus(sources),
+                        ...(prevState.sources || [])
+                      ],
+                      symbolsByLine: { ...prevState.symbolsByLine, ...symbolsByLine(sources) }
+                    };
+                  });
+                }
+              },
+              () => {
+                // TODO
+              }
+            );
+        },
+        () => {
+          // TODO
+        }
+      );
   };
 
   loadSourcesAfter = () => {
@@ -455,9 +438,9 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
     const fromLine = lastSourceLine.line + 1;
     // request one additional line to define `hasSourcesAfter`
     const toLine = lastSourceLine.line + LINES + 1;
-    this.safeLoadSources(this.props.component, fromLine, toLine, this.props.branchLike).then(
+    this.props.loadSources(this.props.component, fromLine, toLine, this.props.branchLike).then(
       sources => {
-        this.safeLoadIssues(this.props.component, fromLine, toLine, this.props.branchLike).then(
+        this.props.loadIssues(this.props.component, fromLine, toLine, this.props.branchLike).then(
           issues => {
             if (this.mounted) {
               this.setState(prevState => {
@@ -749,13 +732,13 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
   }
 }
 
-function defaultLoadComponent(key: string, branchLike: BranchLike | undefined) {
+function defaultLoadComponent(component: string, branchLike: BranchLike | undefined) {
   return Promise.all([
-    getComponentForSourceViewer({ component: key, ...getBranchLikeQuery(branchLike) }),
-    getComponentData({ component: key, ...getBranchLikeQuery(branchLike) })
+    getComponentForSourceViewer({ component, ...getBranchLikeQuery(branchLike) }),
+    getComponentData({ component, ...getBranchLikeQuery(branchLike) })
   ]).then(([component, data]) => ({
     ...component,
-    leakPeriodDate: data.leakPeriodDate && parseDate(data.leakPeriodDate)
+    leakPeriodDate: data.leakPeriodDate
   }));
 }
 
index 80ce4ba53d2fccd7697d8e05209b901bc5c3c0f4..36595d0185697fd193376c1445f48bfbc37621fb 100644 (file)
@@ -25,7 +25,7 @@ import MeasuresOverlay from './components/MeasuresOverlay';
 import { SourceViewerFile, BranchLike } from '../../app/types';
 import QualifierIcon from '../icons-components/QualifierIcon';
 import Dropdown from '../controls/Dropdown';
-import FavoriteContainer from '../controls/FavoriteContainer';
+import Favorite from '../controls/Favorite';
 import ListIcon from '../icons-components/ListIcon';
 import { ButtonIcon } from '../ui/buttons';
 import { PopupPlacement } from '../ui/popups';
@@ -122,7 +122,12 @@ export default class SourceViewerHeader extends React.PureComponent<Props, State
               <span className="component-name-file">{fileFromPath(path)}</span>
               {this.props.sourceViewerFile.canMarkAsFavorite &&
                 (!this.props.branchLike || isMainBranch(this.props.branchLike)) && (
-                  <FavoriteContainer className="component-name-favorite" componentKey={key} />
+                  <Favorite
+                    className="component-name-favorite"
+                    component={key}
+                    favorite={this.props.sourceViewerFile.fav || false}
+                    qualifier={this.props.sourceViewerFile.q}
+                  />
                 )}
             </div>
           </div>
index a1bd2cc6866d020e14eb358a7a8c452360af5127..4dbd3b05cea332b141f50cc86cf9e400f0d06151 100644 (file)
@@ -67,19 +67,25 @@ export default class FavoriteBase extends React.PureComponent<Props, State> {
   };
 
   addFavorite() {
-    this.props.addFavorite().then(() => {
-      if (this.mounted) {
-        this.setState({ favorite: true });
-      }
-    });
+    this.props.addFavorite().then(
+      () => {
+        if (this.mounted) {
+          this.setState({ favorite: true });
+        }
+      },
+      () => {}
+    );
   }
 
   removeFavorite() {
-    this.props.removeFavorite().then(() => {
-      if (this.mounted) {
-        this.setState({ favorite: false });
-      }
-    });
+    this.props.removeFavorite().then(
+      () => {
+        if (this.mounted) {
+          this.setState({ favorite: false });
+        }
+      },
+      () => {}
+    );
   }
 
   render() {
diff --git a/server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.tsx b/server/sonar-web/src/main/js/components/controls/FavoriteBaseStateless.tsx
deleted file mode 100644 (file)
index 544056d..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import * as React from 'react';
-import * as classNames from 'classnames';
-import FavoriteIcon from '../icons-components/FavoriteIcon';
-
-interface Props {
-  addFavorite: () => void;
-  className?: string;
-  favorite: boolean;
-  removeFavorite: () => void;
-}
-
-export default class FavoriteBaseStateless extends React.PureComponent<Props> {
-  toggleFavorite = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
-    event.preventDefault();
-    if (this.props.favorite) {
-      this.props.removeFavorite();
-    } else {
-      this.props.addFavorite();
-    }
-  };
-
-  render() {
-    return (
-      <a
-        className={classNames('link-no-underline', this.props.className)}
-        href="#"
-        onClick={this.toggleFavorite}>
-        <FavoriteIcon favorite={this.props.favorite} />
-      </a>
-    );
-  }
-}
diff --git a/server/sonar-web/src/main/js/components/controls/FavoriteContainer.ts b/server/sonar-web/src/main/js/components/controls/FavoriteContainer.ts
deleted file mode 100644 (file)
index 8d9da47..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { connect } from 'react-redux';
-import FavoriteBaseStateless from './FavoriteBaseStateless';
-import { isFavorite } from '../../store/rootReducer';
-import * as actionCreators from '../../store/favorites/duck';
-import * as api from '../../api/favorites';
-import { addGlobalErrorMessage } from '../../store/globalMessages/duck';
-import { parseError } from '../../helpers/request';
-
-const addFavorite = (componentKey: string) => (dispatch: Function) => {
-  // optimistic update
-  dispatch(actionCreators.addFavorite(componentKey));
-  api.addFavorite(componentKey).catch(error => {
-    dispatch(actionCreators.removeFavorite(componentKey));
-    parseError(error).then(message => dispatch(addGlobalErrorMessage(message)));
-  });
-};
-
-const removeFavorite = (componentKey: string) => (dispatch: Function) => {
-  // optimistic update
-  dispatch(actionCreators.removeFavorite(componentKey));
-  api.removeFavorite(componentKey).catch(error => {
-    dispatch(actionCreators.addFavorite(componentKey));
-    parseError(error).then(message => dispatch(addGlobalErrorMessage(message)));
-  });
-};
-
-const mapStateToProps = (state: any, ownProps: any) => ({
-  favorite: isFavorite(state, ownProps.componentKey)
-});
-
-const mapDispatchToProps = (dispatch: Function, ownProps: any) => ({
-  addFavorite: () => dispatch(addFavorite(ownProps.componentKey)),
-  removeFavorite: () => dispatch(removeFavorite(ownProps.componentKey))
-});
-
-export default connect(
-  mapStateToProps,
-  mapDispatchToProps
-)(FavoriteBaseStateless);
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/FavoriteBaseStateless-test.tsx b/server/sonar-web/src/main/js/components/controls/__tests__/FavoriteBaseStateless-test.tsx
deleted file mode 100644 (file)
index 2ed0bd1..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import * as React from 'react';
-import { shallow } from 'enzyme';
-import FavoriteBaseStateless from '../FavoriteBaseStateless';
-import { click } from '../../../helpers/testUtils';
-
-it('renders', () => {
-  expect(
-    shallow(
-      <FavoriteBaseStateless addFavorite={jest.fn()} favorite={true} removeFavorite={jest.fn()} />
-    )
-  ).toMatchSnapshot();
-});
-
-it('adds favorite', () => {
-  const addFavorite = jest.fn();
-  const wrapper = shallow(
-    <FavoriteBaseStateless addFavorite={addFavorite} favorite={false} removeFavorite={jest.fn()} />
-  );
-  click(wrapper);
-  expect(addFavorite).toBeCalled();
-});
-
-it('removes favorite', () => {
-  const removeFavorite = jest.fn();
-  const wrapper = shallow(
-    <FavoriteBaseStateless
-      addFavorite={jest.fn()}
-      favorite={true}
-      removeFavorite={removeFavorite}
-    />
-  );
-  click(wrapper);
-  expect(removeFavorite).toBeCalled();
-});
diff --git a/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/FavoriteBaseStateless-test.tsx.snap b/server/sonar-web/src/main/js/components/controls/__tests__/__snapshots__/FavoriteBaseStateless-test.tsx.snap
deleted file mode 100644 (file)
index 9edbec0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`renders 1`] = `
-<a
-  className="link-no-underline"
-  href="#"
-  onClick={[Function]}
->
-  <FavoriteIcon
-    favorite={true}
-  />
-</a>
-`;
index 7453ffec0823d6f87e49b28ec31c890fd55d93a6..fb3201016c1c9ac168d14cb6229892f8b45d2f50 100644 (file)
@@ -28,7 +28,7 @@ exports[`should render 1`] = `
       }
     }
   >
-    <Connect(LazyLoader)
+    <LazyLoader
       component="foo"
       onLoaded={[Function]}
     />
diff --git a/server/sonar-web/src/main/js/store/favorites/duck.ts b/server/sonar-web/src/main/js/store/favorites/duck.ts
deleted file mode 100644 (file)
index 710151e..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import { uniq, without } from 'lodash';
-
-interface Favorite {
-  key: string;
-}
-
-interface ReceiveFavoritesAction {
-  type: 'RECEIVE_FAVORITES';
-  favorites: Array<Favorite>;
-  notFavorites: Array<Favorite>;
-}
-
-interface AddFavoriteAction {
-  type: 'ADD_FAVORITE';
-  componentKey: string;
-}
-
-interface RemoveFavoriteAction {
-  type: 'REMOVE_FAVORITE';
-  componentKey: string;
-}
-
-type Action = ReceiveFavoritesAction | AddFavoriteAction | RemoveFavoriteAction;
-
-type State = string[];
-
-export function receiveFavorites(
-  favorites: Favorite[],
-  notFavorites: Favorite[] = []
-): ReceiveFavoritesAction {
-  return { type: 'RECEIVE_FAVORITES', favorites, notFavorites };
-}
-
-export function addFavorite(componentKey: string): AddFavoriteAction {
-  return { type: 'ADD_FAVORITE', componentKey };
-}
-
-export function removeFavorite(componentKey: string): RemoveFavoriteAction {
-  return { type: 'REMOVE_FAVORITE', componentKey };
-}
-
-export default function(state: State = [], action: Action): State {
-  if (action.type === 'RECEIVE_FAVORITES') {
-    const toAdd = action.favorites.map(f => f.key);
-    const toRemove = action.notFavorites.map(f => f.key);
-    return without(uniq([...state, ...toAdd]), ...toRemove);
-  }
-
-  if (action.type === 'ADD_FAVORITE') {
-    return uniq([...state, action.componentKey]);
-  }
-
-  if (action.type === 'REMOVE_FAVORITE') {
-    return without(state, action.componentKey);
-  }
-
-  return state;
-}
-
-export function isFavorite(state: State, componentKey: string) {
-  return state.includes(componentKey);
-}
index 73c0dc340a1203bba0ae2a9f893ccd095c466d44..21e8c8285002eb52404616e6bedf76a71e8a6b6b 100644 (file)
@@ -20,7 +20,6 @@
 import { combineReducers } from 'redux';
 import appState from './appState/duck';
 import users, * as fromUsers from './users/reducer';
-import favorites, * as fromFavorites from './favorites/duck';
 import languages, * as fromLanguages from './languages/reducer';
 import metrics, * as fromMetrics from './metrics/reducer';
 import organizations, * as fromOrganizations from './organizations/duck';
@@ -33,7 +32,6 @@ import settingsApp, * as fromSettingsApp from '../apps/settings/store/rootReduce
 export default combineReducers({
   appState,
   globalMessages,
-  favorites,
   languages,
   metrics,
   organizations,
@@ -66,9 +64,6 @@ export const getUsersByLogins = (state, logins) => fromUsers.getUsersByLogins(st
 
 export const getUsers = state => fromUsers.getUsers(state.users);
 
-export const isFavorite = (state, componentKey) =>
-  fromFavorites.isFavorite(state.favorites, componentKey);
-
 export const getMarketplaceState = state => state.marketplace;
 
 export const getMetrics = state => fromMetrics.getMetrics(state.metrics);