Browse Source

dashfolders: Add a Team Picker component and use it on the dashboard permissions page #10275

Johannes Schill 8 years ago
parent
commit
5a9fe9aff9

+ 1 - 1
public/app/core/angular_wrappers.ts

@@ -19,7 +19,7 @@ export function registerAngularDirectives() {
     ['onSelect', { watchDepth: 'reference' }],
     ['tagOptions', { watchDepth: 'reference' }],
   ]);
-  react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'userPicked']);
+  react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'handlePicked']);
   react2AngularDirective('permissions', Permissions, [
     'error',
     'newType',

+ 9 - 3
public/app/core/components/Permissions/Permissions.tsx

@@ -3,6 +3,7 @@ import PermissionsList from './PermissionsList';
 import DevTools from 'mobx-react-devtools';
 import { inject, observer } from 'mobx-react';
 import UserPicker, { User } from 'app/core/components/UserPicker/UserPicker';
+import TeamPicker, { Team } from 'app/core/components/UserPicker/TeamPicker';
 
 export interface DashboardAcl {
   id?: number;
@@ -61,6 +62,7 @@ class Permissions extends Component<IProps, any> {
     this.removeItem = this.removeItem.bind(this);
     this.update = this.update.bind(this);
     this.userPicked = this.userPicked.bind(this);
+    this.teamPicked = this.teamPicked.bind(this);
     permissions.load(dashboardId, isFolder);
 
     this.state = {
@@ -119,6 +121,11 @@ class Permissions extends Component<IProps, any> {
     permissions.addStoreItem({ userId: user.id, userLogin: user.login, permission: 1 });
   }
 
+  teamPicked(team: Team) {
+    const { permissions } = this.props;
+    permissions.addStoreItem({ teamId: team.id, team: team.name, permission: 1 });
+  }
+
   render() {
     console.log('Permissions render');
     const { error, permissions, backendSrv } = this.props;
@@ -167,14 +174,13 @@ class Permissions extends Component<IProps, any> {
                     refreshList="ctrl.get"
                     teamMembers="ctrl.teamMembers"
                   /> */}
-                  <UserPicker backendSrv={backendSrv} userPicked={this.userPicked} />
+                  <UserPicker backendSrv={backendSrv} handlePicked={this.userPicked} />
                 </div>
               ) : null}
 
               {newType === 'Group' ? (
                 <div className="gf-form">
-                  Team picker
-                  {/* <team-picker team-picked="ctrl.groupPicked($group)" /> */}
+                  <TeamPicker backendSrv={backendSrv} handlePicked={this.teamPicked} />
                 </div>
               ) : null}
             </div>

+ 81 - 0
public/app/core/components/UserPicker/TeamPicker.tsx

@@ -0,0 +1,81 @@
+import React, { Component } from 'react';
+import Select from 'react-select';
+import UserPickerOption from './UserPickerOption';
+import withPicker from './withPicker';
+import { debounce } from 'lodash';
+
+export interface IProps {
+  backendSrv: any;
+  isLoading: boolean;
+  toggleLoading: any;
+  handlePicked: (user) => void;
+}
+
+export interface Team {
+  id: number;
+  label: string;
+  name: string;
+  avatarUrl: string;
+}
+
+class TeamPicker extends Component<IProps, any> {
+  debouncedSearch: any;
+  backendSrv: any;
+
+  constructor(props) {
+    super(props);
+    this.state = {};
+    this.search = this.search.bind(this);
+    // this.handleChange = this.handleChange.bind(this);
+    this.debouncedSearch = debounce(this.search, 300, {
+      leading: true,
+      trailing: false,
+    });
+  }
+
+  search(query?: string) {
+    const { toggleLoading, backendSrv } = this.props;
+
+    toggleLoading(true);
+
+    return backendSrv.get(`/api/teams/search?perpage=10&page=1&query=${query}`).then(result => {
+      const teams = result.teams.map(team => {
+        // return { text: ug.name, value: ug };
+        return {
+          id: team.id,
+          label: team.name,
+          name: team.name,
+          avatarUrl: team.avatarUrl,
+        };
+      });
+
+      toggleLoading(false);
+      return { options: teams };
+    });
+  }
+
+  render() {
+    const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async;
+    const { isLoading, handlePicked } = this.props;
+
+    return (
+      <div className="user-picker">
+        <AsyncComponent
+          valueKey="id"
+          multi={this.state.multi}
+          labelKey="label"
+          cache={false}
+          isLoading={isLoading}
+          loadOptions={this.debouncedSearch}
+          loadingPlaceholder="Loading..."
+          onChange={handlePicked}
+          className="width-8 gf-form-input gf-form-input--form-dropdown"
+          optionComponent={UserPickerOption}
+          placeholder="Choose"
+        />
+      </div>
+    );
+  }
+}
+
+export default withPicker(TeamPicker);

+ 11 - 15
public/app/core/components/UserPicker/UserPicker.tsx

@@ -1,4 +1,4 @@
-import React, { Component } from 'react';
+import React, { Component } from 'react';
 import Select from 'react-select';
 import UserPickerOption from './UserPickerOption';
 import withPicker from './withPicker';
@@ -8,7 +8,7 @@ export interface IProps {
   backendSrv: any;
   isLoading: boolean;
   toggleLoading: any;
-  userPicked: (user) => void;
+  handlePicked: (user) => void;
 }
 
 export interface User {
@@ -19,26 +19,21 @@ export interface User {
 }
 
 class UserPicker extends Component<IProps, any> {
-  debouncedSearchUsers: any;
+  debouncedSearch: any;
   backendSrv: any;
 
   constructor(props) {
     super(props);
     this.state = {};
-    this.searchUsers = this.searchUsers.bind(this);
-    this.handleChange = this.handleChange.bind(this);
-    this.debouncedSearchUsers = debounce(this.searchUsers, 300, {
+    this.search = this.search.bind(this);
+    // this.handleChange = this.handleChange.bind(this);
+    this.debouncedSearch = debounce(this.search, 300, {
       leading: true,
       trailing: false,
     });
   }
 
-  handleChange(user: User) {
-    const { userPicked } = this.props;
-    userPicked(user);
-  }
-
-  searchUsers(query?: string) {
+  search(query?: string) {
     const { toggleLoading, backendSrv } = this.props;
 
     toggleLoading(true);
@@ -58,6 +53,7 @@ class UserPicker extends Component<IProps, any> {
 
   render() {
     const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async;
+    const { isLoading, handlePicked } = this.props;
 
     return (
       <div className="user-picker">
@@ -66,11 +62,11 @@ class UserPicker extends Component<IProps, any> {
           multi={this.state.multi}
           labelKey="label"
           cache={false}
-          isLoading={this.props.isLoading}
-          loadOptions={this.debouncedSearchUsers}
+          isLoading={isLoading}
+          loadOptions={this.debouncedSearch}
           loadingPlaceholder="Loading..."
           noResultsText="No users found"
-          onChange={this.handleChange}
+          onChange={handlePicked}
           className="width-8 gf-form-input gf-form-input--form-dropdown"
           optionComponent={UserPickerOption}
           placeholder="Choose"

+ 1 - 1
public/app/core/components/UserPicker/withPicker.tsx

@@ -2,7 +2,7 @@
 
 export interface IProps {
   backendSrv: any;
-  userPicked: (user) => void;
+  handlePicked: (data) => void;
 }
 
 // export interface User {

+ 1 - 1
public/app/features/org/partials/team_details.html

@@ -33,7 +33,7 @@
 				Old picker
 				<user-picker user-picked="ctrl.userPicked($user)"></user-picker>
 				-->
-				<select-user-picker userPicked="ctrl.userPicked" backendSrv="ctrl.backendSrv"></select-user-picker>
+				<select-user-picker handlePicked="ctrl.userPicked" backendSrv="ctrl.backendSrv"></select-user-picker>
       </div>
     </form>