Quellcode durchsuchen

mobx -> redux: major progress on folder migration

Torkel Ödegaard vor 7 Jahren
Ursprung
Commit
ec41d76080

+ 0 - 2
public/app/containers/ContainerProps.ts

@@ -1,13 +1,11 @@
 import { NavStore } from './../stores/NavStore/NavStore';
 import { NavStore } from './../stores/NavStore/NavStore';
 import { PermissionsStore } from './../stores/PermissionsStore/PermissionsStore';
 import { PermissionsStore } from './../stores/PermissionsStore/PermissionsStore';
 import { ViewStore } from './../stores/ViewStore/ViewStore';
 import { ViewStore } from './../stores/ViewStore/ViewStore';
-import { FolderStore } from './../stores/FolderStore/FolderStore';
 
 
 interface ContainerProps {
 interface ContainerProps {
   nav: typeof NavStore.Type;
   nav: typeof NavStore.Type;
   permissions: typeof PermissionsStore.Type;
   permissions: typeof PermissionsStore.Type;
   view: typeof ViewStore.Type;
   view: typeof ViewStore.Type;
-  folder: typeof FolderStore.Type;
   backendSrv: any;
   backendSrv: any;
 }
 }
 
 

+ 32 - 17
public/app/containers/ManageDashboards/FolderPermissions.tsx → public/app/features/manage-dashboards/FolderPermissions.tsx

@@ -2,24 +2,34 @@ import React, { Component } from 'react';
 import { hot } from 'react-hot-loader';
 import { hot } from 'react-hot-loader';
 import { inject, observer } from 'mobx-react';
 import { inject, observer } from 'mobx-react';
 import { toJS } from 'mobx';
 import { toJS } from 'mobx';
-import ContainerProps from 'app/containers/ContainerProps';
+import { connect } from 'react-redux';
 import PageHeader from 'app/core/components/PageHeader/PageHeader';
 import PageHeader from 'app/core/components/PageHeader/PageHeader';
 import Permissions from 'app/core/components/Permissions/Permissions';
 import Permissions from 'app/core/components/Permissions/Permissions';
 import Tooltip from 'app/core/components/Tooltip/Tooltip';
 import Tooltip from 'app/core/components/Tooltip/Tooltip';
 import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo';
 import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo';
 import AddPermissions from 'app/core/components/Permissions/AddPermissions';
 import AddPermissions from 'app/core/components/Permissions/AddPermissions';
 import SlideDown from 'app/core/components/Animations/SlideDown';
 import SlideDown from 'app/core/components/Animations/SlideDown';
+import { getNavModel } from 'app/core/selectors/navModel';
+import { NavModel, StoreState, FolderState } from 'app/types';
+import { getFolderByUid, setFolderTitle, saveFolder, deleteFolder } from './state/actions';
 
 
-@inject('nav', 'folder', 'view', 'permissions')
+export interface Props {
+  navModel: NavModel;
+  getFolderByUid: typeof getFolderByUid;
+  folderUid: string;
+  folder: FolderState;
+}
+
+@inject('permissions')
 @observer
 @observer
-export class FolderPermissions extends Component<ContainerProps, any> {
+export class FolderPermissions extends Component<Props> {
   constructor(props) {
   constructor(props) {
     super(props);
     super(props);
     this.handleAddPermission = this.handleAddPermission.bind(this);
     this.handleAddPermission = this.handleAddPermission.bind(this);
   }
   }
 
 
   componentDidMount() {
   componentDidMount() {
-    this.loadStore();
+    this.props.getFolderByUid(this.props.folderUid);
   }
   }
 
 
   componentWillUnmount() {
   componentWillUnmount() {
@@ -27,31 +37,23 @@ export class FolderPermissions extends Component<ContainerProps, any> {
     permissions.hideAddPermissions();
     permissions.hideAddPermissions();
   }
   }
 
 
-  loadStore() {
-    const { nav, folder, view } = this.props;
-    return folder.load(view.routeParams.get('uid') as string).then(res => {
-      view.updatePathAndQuery(`${res.url}/permissions`, {}, {});
-      return nav.initFolderNav(toJS(folder.folder), 'manage-folder-permissions');
-    });
-  }
-
   handleAddPermission() {
   handleAddPermission() {
     const { permissions } = this.props;
     const { permissions } = this.props;
     permissions.toggleAddPermissions();
     permissions.toggleAddPermissions();
   }
   }
 
 
   render() {
   render() {
-    const { nav, folder, permissions, backendSrv } = this.props;
+    const { navModel, permissions, backendSrv, folder } = this.props;
 
 
-    if (!folder.folder || !nav.main) {
+    if (folder.id === 0) {
       return <h2>Loading</h2>;
       return <h2>Loading</h2>;
     }
     }
 
 
-    const dashboardId = folder.folder.id;
+    const dashboardId = folder.id;
 
 
     return (
     return (
       <div>
       <div>
-        <PageHeader model={nav as any} />
+        <PageHeader model={navModel} />
         <div className="page-container page-body">
         <div className="page-container page-body">
           <div className="page-action-bar">
           <div className="page-action-bar">
             <h3 className="page-sub-heading">Folder Permissions</h3>
             <h3 className="page-sub-heading">Folder Permissions</h3>
@@ -77,4 +79,17 @@ export class FolderPermissions extends Component<ContainerProps, any> {
   }
   }
 }
 }
 
 
-export default hot(module)(FolderPermissions);
+const mapStateToProps = (state: StoreState) => {
+  const uid = state.location.routeParams.uid;
+  return {
+    navModel: getNavModel(state.navIndex, `folder-permissions-${uid}`),
+    folderUid: uid,
+    folder: state.folder,
+  };
+};
+
+const mapDispatchToProps = {
+  getFolderByUid,
+};
+
+export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(FolderPermissions));

+ 44 - 74
public/app/features/manage-dashboards/FolderSettingsPage.test.tsx

@@ -1,84 +1,54 @@
 import React from 'react';
 import React from 'react';
-import { FolderSettings } from './FolderSettings';
-import { RootStore } from 'app/stores/RootStore/RootStore';
-import { backendSrv } from 'test/mocks/common';
+import { FolderSettingsPage, Props } from './FolderSettingsPage';
+import { NavModel, FolderState } from '../../types';
 import { shallow } from 'enzyme';
 import { shallow } from 'enzyme';
 
 
-describe('FolderSettings', () => {
-  let wrapper;
-  let page;
+const setup = (propOverrides?: object) => {
+  const props: Props = {
+    navModel: {} as NavModel,
+    folderUid: '1234',
+    folder: {
+      id: 0,
+      uid: '1234',
+      title: 'loading',
+      canSave: true,
+      hasChanged: false,
+      version: 1,
+    },
+    getFolderByUid: jest.fn(),
+    setFolderTitle: jest.fn(),
+    saveFolder: jest.fn(),
+    deleteFolder: jest.fn(),
+  };
+
+  Object.assign(props, propOverrides);
+
+  const wrapper = shallow(<FolderSettingsPage {...props} />);
+  const instance = wrapper.instance() as FolderSettingsPage;
+
+  return {
+    wrapper,
+    instance,
+  };
+};
+
+describe('Render', () => {
+  it('should render component', () => {
+    const { wrapper } = setup();
+    expect(wrapper).toMatchSnapshot();
+  });
 
 
-  beforeAll(() => {
-    backendSrv.getFolderByUid.mockReturnValue(
-      Promise.resolve({
+  it('should enable save button', () => {
+    const { wrapper } = setup({
+      folder: {
         id: 1,
         id: 1,
-        uid: 'uid',
-        title: 'Folder Name',
-        url: '/dashboards/f/uid/folder-name',
+        uid: '1234',
+        title: 'loading',
         canSave: true,
         canSave: true,
+        hasChanged: true,
         version: 1,
         version: 1,
-      })
-    );
-
-    const store = RootStore.create(
-      {
-        view: {
-          path: 'asd',
-          query: {},
-          routeParams: {
-            uid: 'uid-str',
-          },
-        },
       },
       },
-      {
-        backendSrv: backendSrv,
-      }
-    );
-
-    wrapper = shallow(<FolderSettings backendSrv={backendSrv} {...store} />);
-    page = wrapper.dive();
-    return page
-      .instance()
-      .loadStore()
-      .then(() => {
-        page.update();
-      });
-  });
-
-  it('should set the title input field', () => {
-    const titleInput = page.find('.gf-form-input');
-    expect(titleInput).toHaveLength(1);
-    expect(titleInput.prop('value')).toBe('Folder Name');
-  });
-
-  it('should update title and enable save button when changed', () => {
-    const titleInput = page.find('.gf-form-input');
-    const disabledSubmitButton = page.find('button[type="submit"]');
-    expect(disabledSubmitButton.prop('disabled')).toBe(true);
-
-    titleInput.simulate('change', { target: { value: 'New Title' } });
-
-    const updatedTitleInput = page.find('.gf-form-input');
-    expect(updatedTitleInput.prop('value')).toBe('New Title');
-    const enabledSubmitButton = page.find('button[type="submit"]');
-    expect(enabledSubmitButton.prop('disabled')).toBe(false);
-  });
-
-  it('should disable save button if title is changed back to old title', () => {
-    const titleInput = page.find('.gf-form-input');
-
-    titleInput.simulate('change', { target: { value: 'Folder Name' } });
-
-    const enabledSubmitButton = page.find('button[type="submit"]');
-    expect(enabledSubmitButton.prop('disabled')).toBe(true);
-  });
-
-  it('should disable save button if title is changed to empty string', () => {
-    const titleInput = page.find('.gf-form-input');
-
-    titleInput.simulate('change', { target: { value: '' } });
-
-    const enabledSubmitButton = page.find('button[type="submit"]');
-    expect(enabledSubmitButton.prop('disabled')).toBe(true);
+    });
+    expect(wrapper).toMatchSnapshot();
   });
   });
 });
 });

+ 131 - 0
public/app/features/manage-dashboards/__snapshots__/FolderSettingsPage.test.tsx.snap

@@ -0,0 +1,131 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Render should enable save button 1`] = `
+<div>
+  <PageHeader
+    model={Object {}}
+  />
+  <div
+    className="page-container page-body"
+  >
+    <h2
+      className="page-sub-heading"
+    >
+      Folder Settings
+    </h2>
+    <div
+      className="section gf-form-group"
+    >
+      <form
+        name="folderSettingsForm"
+        onSubmit={[Function]}
+      >
+        <div
+          className="gf-form"
+        >
+          <label
+            className="gf-form-label width-7"
+          >
+            Name
+          </label>
+          <input
+            className="gf-form-input width-30"
+            onChange={[Function]}
+            type="text"
+            value="loading"
+          />
+        </div>
+        <div
+          className="gf-form-button-row"
+        >
+          <button
+            className="btn btn-success"
+            disabled={false}
+            type="submit"
+          >
+            <i
+              className="fa fa-save"
+            />
+             Save
+          </button>
+          <button
+            className="btn btn-danger"
+            disabled={false}
+            onClick={[Function]}
+          >
+            <i
+              className="fa fa-trash"
+            />
+             Delete
+          </button>
+        </div>
+      </form>
+    </div>
+  </div>
+</div>
+`;
+
+exports[`Render should render component 1`] = `
+<div>
+  <PageHeader
+    model={Object {}}
+  />
+  <div
+    className="page-container page-body"
+  >
+    <h2
+      className="page-sub-heading"
+    >
+      Folder Settings
+    </h2>
+    <div
+      className="section gf-form-group"
+    >
+      <form
+        name="folderSettingsForm"
+        onSubmit={[Function]}
+      >
+        <div
+          className="gf-form"
+        >
+          <label
+            className="gf-form-label width-7"
+          >
+            Name
+          </label>
+          <input
+            className="gf-form-input width-30"
+            onChange={[Function]}
+            type="text"
+            value="loading"
+          />
+        </div>
+        <div
+          className="gf-form-button-row"
+        >
+          <button
+            className="btn btn-success"
+            disabled={true}
+            type="submit"
+          >
+            <i
+              className="fa fa-save"
+            />
+             Save
+          </button>
+          <button
+            className="btn btn-danger"
+            disabled={false}
+            onClick={[Function]}
+          >
+            <i
+              className="fa fa-trash"
+            />
+             Delete
+          </button>
+        </div>
+      </form>
+    </div>
+  </div>
+</div>
+`;

+ 2 - 2
public/app/features/manage-dashboards/state/reducers.ts

@@ -2,8 +2,8 @@ import { FolderState } from 'app/types';
 import { Action, ActionTypes } from './actions';
 import { Action, ActionTypes } from './actions';
 
 
 export const inititalState: FolderState = {
 export const inititalState: FolderState = {
+  id: 0,
   uid: 'loading',
   uid: 'loading',
-  id: -1,
   title: 'loading',
   title: 'loading',
   url: '',
   url: '',
   canSave: false,
   canSave: false,
@@ -22,7 +22,7 @@ export const folderReducer = (state = inititalState, action: Action): FolderStat
       return {
       return {
         ...state,
         ...state,
         title: action.payload,
         title: action.payload,
-        hasChanged: true,
+        hasChanged: action.payload.trim().length > 0,
       };
       };
   }
   }
   return state;
   return state;

+ 1 - 1
public/app/routes/routes.ts

@@ -3,10 +3,10 @@ import './ReactContainer';
 
 
 import ServerStats from 'app/features/admin/ServerStats';
 import ServerStats from 'app/features/admin/ServerStats';
 import AlertRuleList from 'app/features/alerting/AlertRuleList';
 import AlertRuleList from 'app/features/alerting/AlertRuleList';
-import FolderPermissions from 'app/containers/ManageDashboards/FolderPermissions';
 import TeamPages from 'app/features/teams/TeamPages';
 import TeamPages from 'app/features/teams/TeamPages';
 import TeamList from 'app/features/teams/TeamList';
 import TeamList from 'app/features/teams/TeamList';
 import FolderSettingsPage from 'app/features/manage-dashboards/FolderSettingsPage';
 import FolderSettingsPage from 'app/features/manage-dashboards/FolderSettingsPage';
+import FolderPermissions from 'app/features/manage-dashboards/FolderPermissions';
 
 
 /** @ngInject */
 /** @ngInject */
 export function setupAngularRoutes($routeProvider, $locationProvider) {
 export function setupAngularRoutes($routeProvider, $locationProvider) {

+ 0 - 2
public/app/stores/RootStore/RootStore.ts

@@ -1,7 +1,6 @@
 import { types } from 'mobx-state-tree';
 import { types } from 'mobx-state-tree';
 import { NavStore } from './../NavStore/NavStore';
 import { NavStore } from './../NavStore/NavStore';
 import { ViewStore } from './../ViewStore/ViewStore';
 import { ViewStore } from './../ViewStore/ViewStore';
-import { FolderStore } from './../FolderStore/FolderStore';
 import { PermissionsStore } from './../PermissionsStore/PermissionsStore';
 import { PermissionsStore } from './../PermissionsStore/PermissionsStore';
 
 
 export const RootStore = types.model({
 export const RootStore = types.model({
@@ -15,7 +14,6 @@ export const RootStore = types.model({
     query: {},
     query: {},
     routeParams: {},
     routeParams: {},
   }),
   }),
-  folder: types.optional(FolderStore, {}),
 });
 });
 
 
 type RootStoreType = typeof RootStore.Type;
 type RootStoreType = typeof RootStore.Type;

+ 0 - 0
public/app/types/dashboard.ts → public/app/types/folder.ts


+ 1 - 1
public/app/types/index.ts

@@ -2,7 +2,7 @@ import { Team, TeamsState, TeamState, TeamGroup, TeamMember } from './teams';
 import { AlertRuleDTO, AlertRule, AlertRulesState } from './alerting';
 import { AlertRuleDTO, AlertRule, AlertRulesState } from './alerting';
 import { LocationState, LocationUpdate, UrlQueryMap, UrlQueryValue } from './location';
 import { LocationState, LocationUpdate, UrlQueryMap, UrlQueryValue } from './location';
 import { NavModel, NavModelItem, NavIndex } from './navModel';
 import { NavModel, NavModelItem, NavIndex } from './navModel';
-import { FolderDTO, FolderState } from './dashboard';
+import { FolderDTO, FolderState } from './folder';
 
 
 export {
 export {
   Team,
   Team,