Ver Fonte

wip: solid progress on redux -> angular location bridge update

Torkel Ödegaard há 7 anos atrás
pai
commit
de456f8b73

+ 2 - 1
public/app/core/actions/index.ts

@@ -1,3 +1,4 @@
 import { initNav } from './navModel';
+import { updateLocation } from './location';
 
-export { initNav };
+export { initNav, updateLocation };

+ 13 - 0
public/app/core/actions/location.ts

@@ -0,0 +1,13 @@
+import { LocationUpdate } from 'app/types';
+
+export type Action = UpdateLocationAction;
+
+export interface UpdateLocationAction {
+  type: 'UPDATE_LOCATION';
+  payload: LocationUpdate;
+}
+
+export const updateLocation = (location: LocationUpdate): UpdateLocationAction => ({
+  type: 'UPDATE_LOCATION',
+  payload: location,
+});

+ 2 - 0
public/app/core/reducers/index.ts

@@ -1,5 +1,7 @@
 import navModel from './navModel';
+import location from './location';
 
 export default {
   navModel,
+  location,
 };

+ 35 - 0
public/app/core/reducers/location.ts

@@ -0,0 +1,35 @@
+import { Action } from 'app/core/actions/location';
+import { LocationState, UrlQueryMap } from 'app/types';
+import { toUrlParams } from 'app/core/utils/url';
+
+export const initialState: LocationState = {
+  url: '',
+  path: '',
+  query: {},
+  routeParams: {},
+};
+
+function renderUrl(path: string, query: UrlQueryMap): string {
+  if (Object.keys(query).length > 0) {
+    path += '?' + toUrlParams(query);
+  }
+  return path;
+}
+
+const routerReducer = (state = initialState, action: Action): LocationState => {
+  switch (action.type) {
+    case 'UPDATE_LOCATION': {
+      const { path, query, routeParams } = action.payload;
+      return {
+        url: renderUrl(path || state.path, query),
+        path: path || state.path,
+        query: query || state.query,
+        routeParams: routeParams || state.routeParams,
+      };
+    }
+  }
+
+  return state;
+};
+
+export default routerReducer;

+ 33 - 0
public/app/core/services/bridge_srv.ts

@@ -1,8 +1,10 @@
 import coreModule from 'app/core/core_module';
 import appEvents from 'app/core/app_events';
 import { store } from 'app/stores/store';
+import { store as reduxStore } from 'app/stores/configureStore';
 import { reaction } from 'mobx';
 import locationUtil from 'app/core/utils/location_util';
+import { updateLocation } from 'app/core/actions';
 
 // Services that handles angular -> mobx store sync & other react <-> angular sync
 export class BridgeSrv {
@@ -19,12 +21,30 @@ export class BridgeSrv {
       if (store.view.currentUrl !== angularUrl) {
         store.view.updatePathAndQuery(this.$location.path(), this.$location.search(), this.$route.current.params);
       }
+      const state = reduxStore.getState();
+      if (state.location.url !== angularUrl) {
+        reduxStore.dispatch(
+          updateLocation({
+            path: this.$location.path(),
+            query: this.$location.search(),
+            routeParams: this.$route.current.params,
+          })
+        );
+      }
     });
 
     this.$rootScope.$on('$routeChangeSuccess', (evt, data) => {
       store.view.updatePathAndQuery(this.$location.path(), this.$location.search(), this.$route.current.params);
+      reduxStore.dispatch(
+        updateLocation({
+          path: this.$location.path(),
+          query: this.$location.search(),
+          routeParams: this.$route.current.params,
+        })
+      );
     });
 
+    // listen for mobx store changes and update angular
     reaction(
       () => store.view.currentUrl,
       currentUrl => {
@@ -39,6 +59,19 @@ export class BridgeSrv {
       }
     );
 
+    // Listen for changes in redux location -> update angular location
+    reduxStore.subscribe(() => {
+      const state = reduxStore.getState();
+      const angularUrl = this.$location.url();
+      const url = locationUtil.stripBaseFromUrl(state.location.url);
+      if (angularUrl !== url) {
+        this.$timeout(() => {
+          this.$location.url(url);
+        });
+        console.log('store updating angular $location.url', url);
+      }
+    });
+
     appEvents.on('location-change', payload => {
       const urlWithoutBase = locationUtil.stripBaseFromUrl(payload.href);
       if (this.fullPageReloadRoutes.indexOf(urlWithoutBase) > -1) {

+ 9 - 6
public/app/features/alerting/containers/AlertRuleList.tsx

@@ -5,11 +5,13 @@ import classNames from 'classnames';
 import PageHeader from 'app/core/components/PageHeader/PageHeader';
 import appEvents from 'app/core/app_events';
 import Highlighter from 'react-highlight-words';
-import { initNav } from 'app/core/actions';
+import { initNav, updateLocation } from 'app/core/actions';
 import { ContainerProps } from 'app/types';
 import { getAlertRules, AlertRule } from '../apis';
 
-interface Props extends ContainerProps {}
+interface Props extends ContainerProps {
+  updateLocation: typeof updateLocation;
+}
 
 interface State {
   rules: AlertRule[];
@@ -44,7 +46,9 @@ export class AlertRuleList extends PureComponent<Props, State> {
   }
 
   onStateFilterChanged = evt => {
-    // this.props.view.updateQuery({ state: evt.target.value });
+    this.props.updateLocation({
+      query: { state: evt.target.value },
+    });
     // this.fetchRules();
   };
 
@@ -113,9 +117,7 @@ export class AlertRuleList extends PureComponent<Props, State> {
 
           <section>
             <ol className="alert-rule-list">
-              {rules.map(rule => (
-                <AlertRuleItem rule={rule} key={rule.id} search={search} />
-              ))}
+              {rules.map(rule => <AlertRuleItem rule={rule} key={rule.id} search={search} />)}
             </ol>
           </section>
         </div>
@@ -204,6 +206,7 @@ const mapStateToProps = state => ({
 
 const mapDispatchToProps = {
   initNav,
+  updateLocation,
 };
 
 export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(AlertRuleList));

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

@@ -1,4 +1,5 @@
 import { NavModel, NavModelItem } from './navModel';
 import { ContainerProps } from './container';
+import { LocationState, LocationUpdate, UrlQueryMap, UrlQueryValue } from './location';
 
-export { NavModel, NavModelItem, ContainerProps };
+export { NavModel, NavModelItem, ContainerProps, LocationState, LocationUpdate, UrlQueryValue, UrlQueryMap };

+ 15 - 0
public/app/types/location.ts

@@ -0,0 +1,15 @@
+export interface LocationUpdate {
+  path?: string;
+  query?: UrlQueryMap;
+  routeParams?: UrlQueryMap;
+}
+
+export interface LocationState {
+  url: string;
+  path: string;
+  query: UrlQueryMap;
+  routeParams: UrlQueryMap;
+}
+
+export type UrlQueryValue = string | number | boolean | string[] | number[] | boolean[];
+export type UrlQueryMap = { [s: string]: UrlQueryValue };