فهرست منبع

UserProfile: convert user organizations section to react (#18707)

* convert user organizations section to react

* reload page on org change
Shavonn Brown 6 سال پیش
والد
کامیت
e80e3608ad

+ 42 - 3
public/app/core/utils/UserProvider.tsx

@@ -1,19 +1,24 @@
 import React, { PureComponent } from 'react';
 import { getBackendSrv } from '@grafana/runtime';
 import { User, Team } from 'app/types';
+import { config } from 'app/core/config';
 
 export interface UserAPI {
   changePassword: (changePassword: ChangePasswordFields) => void;
   updateUserProfile: (profile: ProfileUpdateFields) => void;
   loadUser: () => void;
   loadTeams: () => void;
+  loadOrgs: () => void;
+  setUserOrg: (org: UserOrg) => void;
 }
 
 interface LoadingStates {
   changePassword: boolean;
   loadUser: boolean;
   loadTeams: boolean;
+  loadOrgs: boolean;
   updateUserProfile: boolean;
+  updateUserOrg: boolean;
 }
 
 export interface ChangePasswordFields {
@@ -28,25 +33,35 @@ export interface ProfileUpdateFields {
   login: string;
 }
 
+export interface UserOrg {
+  orgId: number;
+  name: string;
+  role: string;
+}
+
 export interface Props {
   userId?: number; // passed, will load user on mount
-  children: (api: UserAPI, states: LoadingStates, teams: Team[], user?: User) => JSX.Element;
+  children: (api: UserAPI, states: LoadingStates, teams: Team[], orgs: UserOrg[], user?: User) => JSX.Element;
 }
 
 export interface State {
   user?: User;
   teams: Team[];
+  orgs: UserOrg[];
   loadingStates: LoadingStates;
 }
 
 export class UserProvider extends PureComponent<Props, State> {
   state: State = {
     teams: [] as Team[],
+    orgs: [] as UserOrg[],
     loadingStates: {
       changePassword: false,
       loadUser: true,
       loadTeams: false,
+      loadOrgs: false,
       updateUserProfile: false,
+      updateUserOrg: false,
     },
   };
 
@@ -78,6 +93,28 @@ export class UserProvider extends PureComponent<Props, State> {
     this.setState({ teams, loadingStates: { ...this.state.loadingStates, loadTeams: false } });
   };
 
+  loadOrgs = async () => {
+    this.setState({
+      loadingStates: { ...this.state.loadingStates, loadOrgs: true },
+    });
+    const orgs = await getBackendSrv().get('/api/user/orgs');
+    this.setState({ orgs, loadingStates: { ...this.state.loadingStates, loadOrgs: false } });
+  };
+
+  setUserOrg = async (org: UserOrg) => {
+    this.setState({
+      loadingStates: { ...this.state.loadingStates, updateUserOrg: true },
+    });
+    await getBackendSrv()
+      .post('/api/user/using/' + org.orgId, {})
+      .then(() => {
+        window.location.href = config.appSubUrl + '/profile';
+      })
+      .finally(() => {
+        this.setState({ loadingStates: { ...this.state.loadingStates, updateUserOrg: false } });
+      });
+  };
+
   updateUserProfile = async (payload: ProfileUpdateFields) => {
     this.setState({ loadingStates: { ...this.state.loadingStates, updateUserProfile: true } });
     await getBackendSrv()
@@ -93,16 +130,18 @@ export class UserProvider extends PureComponent<Props, State> {
 
   render() {
     const { children } = this.props;
-    const { loadingStates, teams, user } = this.state;
+    const { loadingStates, teams, orgs, user } = this.state;
 
     const api = {
       changePassword: this.changePassword,
       loadUser: this.loadUser,
       loadTeams: this.loadTeams,
+      loadOrgs: this.loadOrgs,
       updateUserProfile: this.updateUserProfile,
+      setUserOrg: this.setUserOrg,
     };
 
-    return <>{children(api, loadingStates, teams, user)}</>;
+    return <>{children(api, loadingStates, teams, orgs, user)}</>;
   }
 }
 

+ 0 - 21
public/app/features/profile/ProfileCtrl.ts

@@ -1,23 +1,15 @@
-import config from 'app/core/config';
 import { coreModule, NavModelSrv } from 'app/core/core';
 import { dateTime } from '@grafana/data';
 import { UserSession } from 'app/types';
 import { BackendSrv } from 'app/core/services/backend_srv';
 
 export class ProfileCtrl {
-  user: any;
-  oldTheme: any;
-  orgs: any = [];
   sessions: object[] = [];
-  userForm: any;
-  showOrgsList = false;
-  readonlyLoginFields = config.disableLoginForm;
   navModel: any;
 
   /** @ngInject */
   constructor(private backendSrv: BackendSrv, navModelSrv: NavModelSrv) {
     this.getUserSessions();
-    this.getUserOrgs();
     this.navModel = navModelSrv.getNav('profile', 'profile-settings', 0);
   }
 
@@ -66,19 +58,6 @@ export class ProfileCtrl {
         });
       });
   }
-
-  getUserOrgs() {
-    this.backendSrv.get('/api/user/orgs').then((orgs: any) => {
-      this.orgs = orgs;
-      this.showOrgsList = orgs.length > 1;
-    });
-  }
-
-  setUsingOrg(org: any) {
-    this.backendSrv.post('/api/user/using/' + org.orgId).then(() => {
-      window.location.href = config.appSubUrl + '/profile';
-    });
-  }
 }
 
 coreModule.controller('ProfileCtrl', ProfileCtrl);

+ 9 - 1
public/app/features/profile/ReactProfileWrapper.tsx

@@ -3,12 +3,13 @@ import { UserProvider } from 'app/core/utils/UserProvider';
 import { UserProfileEditForm } from './UserProfileEditForm';
 import { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences';
 import { UserTeams } from './UserTeams';
+import { UserOrganizations } from './UserOrganizations';
 import { config } from '@grafana/runtime';
 import { LoadingPlaceholder } from '@grafana/ui';
 
 export const ReactProfileWrapper = () => (
   <UserProvider userId={config.bootData.user.id}>
-    {(api, states, teams, user) => {
+    {(api, states, teams, orgs, user) => {
       return (
         <>
           {states.loadUser ? (
@@ -22,6 +23,13 @@ export const ReactProfileWrapper = () => (
           )}
           <SharedPreferences resourceUri="user" />
           <UserTeams isLoading={states.loadTeams} loadTeams={api.loadTeams} teams={teams} />
+          <UserOrganizations
+            isLoading={states.loadOrgs}
+            setUserOrg={api.setUserOrg}
+            loadOrgs={api.loadOrgs}
+            orgs={orgs}
+            user={user}
+          />
         </>
       );
     }}

+ 74 - 0
public/app/features/profile/UserOrganizations.tsx

@@ -0,0 +1,74 @@
+import React, { PureComponent } from 'react';
+import { User } from 'app/types';
+import { UserOrg } from 'app/core/utils/UserProvider';
+import { LoadingPlaceholder, Button } from '@grafana/ui';
+
+export interface Props {
+  user: User;
+  orgs: UserOrg[];
+  isLoading: boolean;
+  loadOrgs: () => void;
+  setUserOrg: (org: UserOrg) => void;
+}
+
+export class UserOrganizations extends PureComponent<Props> {
+  componentDidMount() {
+    this.props.loadOrgs();
+  }
+
+  render() {
+    const { isLoading, orgs, user } = this.props;
+
+    if (isLoading) {
+      return <LoadingPlaceholder text="Loading organizations..." />;
+    }
+
+    return (
+      <>
+        {orgs.length > 0 && (
+          <>
+            <h3 className="page-sub-heading">Organizations</h3>
+            <div className="gf-form-group">
+              <table className="filter-table form-inline">
+                <thead>
+                  <tr>
+                    <th>Name</th>
+                    <th>Role</th>
+                    <th />
+                  </tr>
+                </thead>
+                <tbody>
+                  {orgs.map((org: UserOrg, index) => {
+                    return (
+                      <tr key={index}>
+                        <td>{org.name}</td>
+                        <td>{org.role}</td>
+                        <td className="text-right">
+                          {org.orgId === user.orgId ? (
+                            <span className="btn btn-primary btn-small">Current</span>
+                          ) : (
+                            <Button
+                              variant="inverse"
+                              size="sm"
+                              onClick={() => {
+                                this.props.setUserOrg(org);
+                              }}
+                            >
+                              Select
+                            </Button>
+                          )}
+                        </td>
+                      </tr>
+                    );
+                  })}
+                </tbody>
+              </table>
+            </div>
+          </>
+        )}
+      </>
+    );
+  }
+}
+
+export default UserOrganizations;

+ 0 - 31
public/app/features/profile/partials/profile.html

@@ -3,37 +3,6 @@
 <div class="page-container page-body">
   <react-profile-wrapper></react-profile-wrapper>
 
-  <h3 class="page-heading" ng-show="ctrl.showOrgsList">Organizations</h3>
-  <div class="gf-form-group" ng-show="ctrl.showOrgsList">
-    <table class="filter-table form-inline">
-      <thead>
-        <tr>
-          <th>Name</th>
-          <th>Role</th>
-          <th></th>
-        </tr>
-      </thead>
-      <tbody>
-        <tr ng-repeat="org in ctrl.orgs">
-          <td>{{ org.name }}</td>
-          <td>{{ org.role }}</td>
-          <td class="text-right">
-            <span class="btn btn-primary btn-small" ng-show="org.orgId === contextSrv.user.orgId">
-              Current
-            </span>
-            <a
-              ng-click="ctrl.setUsingOrg(org)"
-              class="btn btn-inverse btn-small"
-              ng-show="org.orgId !== contextSrv.user.orgId"
-            >
-              Select
-            </a>
-          </td>
-        </tr>
-      </tbody>
-    </table>
-  </div>
-
   <h3 class="page-heading">Sessions</h3>
   <div class="gf-form-group">
     <table class="filter-table form-inline">

+ 1 - 0
public/app/types/user.ts

@@ -18,6 +18,7 @@ export interface User {
   login: string;
   email: string;
   name: string;
+  orgId?: number;
 }
 
 export interface Invitee {