From 5931d6c87d7f42f34bf25bffc96eb1e1cd1ce9fb Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 20 Dec 2017 16:52:43 +0100 Subject: [PATCH 1/9] ux: POC on new select box for the user picker (#10289) --- package.json | 1 + public/app/core/angular_wrappers.ts | 6 + .../core/components/UserPicker/UserPicker.tsx | 118 +++++++++++++ .../UserPicker/UserPickerOption.tsx | 48 +++++ .../features/org/partials/team_details.html | 9 +- public/app/features/org/team_details_ctrl.ts | 14 +- .../org/team_details_ctrl_BACKUP_16633.ts | 127 ++++++++++++++ .../org/team_details_ctrl_BASE_16633.ts | 77 ++++++++ .../org/team_details_ctrl_LOCAL_16633.ts | 79 +++++++++ .../org/team_details_ctrl_REMOTE_16633.ts | 90 ++++++++++ public/sass/_grafana.scss | 3 +- public/sass/components/_form_dropdown.scss | 165 ++++++++++++++++++ public/sass/components/_user-picker.scss | 28 +++ 13 files changed, 759 insertions(+), 6 deletions(-) create mode 100644 public/app/core/components/UserPicker/UserPicker.tsx create mode 100644 public/app/core/components/UserPicker/UserPickerOption.tsx create mode 100644 public/app/features/org/team_details_ctrl_BACKUP_16633.ts create mode 100644 public/app/features/org/team_details_ctrl_BASE_16633.ts create mode 100644 public/app/features/org/team_details_ctrl_LOCAL_16633.ts create mode 100644 public/app/features/org/team_details_ctrl_REMOTE_16633.ts create mode 100644 public/sass/components/_form_dropdown.scss create mode 100644 public/sass/components/_user-picker.scss diff --git a/package.json b/package.json index bf3bdf616a7..2705c34b7fb 100644 --- a/package.json +++ b/package.json @@ -149,6 +149,7 @@ "react": "^16.2.0", "react-dom": "^16.2.0", "react-grid-layout": "^0.16.1", + "react-select": "^1.1.0", "react-sizeme": "^2.3.6", "remarkable": "^1.7.1", "rxjs": "^5.4.3", diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index 839ff011d5a..0b3974e7966 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -4,6 +4,7 @@ import PageHeader from "./components/PageHeader/PageHeader"; import EmptyListCTA from "./components/EmptyListCTA/EmptyListCTA"; import LoginBackground from "./components/Login/LoginBackground"; import { SearchResult } from "./components/search/SearchResult"; +import UserPicker from "./components/UserPicker/UserPicker"; export function registerAngularDirectives() { react2AngularDirective("passwordStrength", PasswordStrength, ["password"]); @@ -11,4 +12,9 @@ export function registerAngularDirectives() { react2AngularDirective("emptyListCta", EmptyListCTA, ["model"]); react2AngularDirective("loginBackground", LoginBackground, []); react2AngularDirective("searchResult", SearchResult, []); + react2AngularDirective("userPickerr", UserPicker, [ + "backendSrv", + "teamId", + "refreshList" + ]); } diff --git a/public/app/core/components/UserPicker/UserPicker.tsx b/public/app/core/components/UserPicker/UserPicker.tsx new file mode 100644 index 00000000000..3ead5be682a --- /dev/null +++ b/public/app/core/components/UserPicker/UserPicker.tsx @@ -0,0 +1,118 @@ +import React, { Component } from "react"; +import { debounce } from "lodash"; +import Select from "react-select"; +import UserPickerOption from "./UserPickerOption"; +export interface IProps { + backendSrv: any; + teamId: string; + refreshList: any; +} + +export interface User { + id: number; + name: string; + login: string; + email: string; +} + +class UserPicker extends Component { + debouncedSearchUsers: any; + backendSrv: any; + teamId: string; + refreshList: any; + + constructor(props) { + super(props); + this.backendSrv = this.props.backendSrv; + this.teamId = this.props.teamId; + this.refreshList = this.props.refreshList; + + this.searchUsers = this.searchUsers.bind(this); + this.handleChange = this.handleChange.bind(this); + this.addUser = this.addUser.bind(this); + this.toggleLoading = this.toggleLoading.bind(this); + + this.debouncedSearchUsers = debounce(this.searchUsers, 300, { + leading: true, + trailing: false + }); + + this.state = { + multi: false, + isLoading: false + }; + } + + componentWillReceiveProps(nextProps) { + console.log("componentWillReceiveProps", nextProps); + } + + handleChange(user) { + console.log("user", user); + this.addUser(user.id); + } + + toggleLoading(isLoading) { + this.setState(prevState => { + return { + ...prevState, + isLoading: isLoading + }; + }); + } + + addUser(userId) { + this.toggleLoading(true); + this.backendSrv + .post(`/api/teams/${this.teamId}/members`, { userId: userId }) + .then(() => { + this.refreshList(); // this.get() in the angular controller + this.toggleLoading(false); + // this.$scope.$broadcast('user-picker-reset'); // TODO? + }); + } + + searchUsers(query) { + this.toggleLoading(true); + + return this.backendSrv + .get(`/api/users/search?perpage=10&page=1&query=${query}`) + .then(result => { + const users = result.users.map(user => { + return { + id: user.id, + label: `${user.login} - ${user.email}`, + avatarUrl: user.avatarUrl + }; + }); + this.toggleLoading(false); + return { options: users }; + }); + } + + render() { + const AsyncComponent = this.state.creatable + ? Select.AsyncCreatable + : Select.Async; + + return ( +
+ +
+ ); + } +} + +export default UserPicker; diff --git a/public/app/core/components/UserPicker/UserPickerOption.tsx b/public/app/core/components/UserPicker/UserPickerOption.tsx new file mode 100644 index 00000000000..145784127ee --- /dev/null +++ b/public/app/core/components/UserPicker/UserPickerOption.tsx @@ -0,0 +1,48 @@ +import React, { Component } from "react"; + +class UserPickerOption extends Component { + constructor(props) { + super(props); + this.handleMouseDown = this.handleMouseDown.bind(this); + this.handleMouseEnter = this.handleMouseEnter.bind(this); + this.handleMouseMove = this.handleMouseMove.bind(this); + } + + handleMouseDown(event) { + event.preventDefault(); + event.stopPropagation(); + this.props.onSelect(this.props.option, event); + } + handleMouseEnter(event) { + this.props.onFocus(this.props.option, event); + } + handleMouseMove(event) { + if (this.props.isFocused) { + return; + } + this.props.onFocus(this.props.option, event); + } + + render() { + const { option, children, className } = this.props; + + return ( + + ); + } +} + +export default UserPickerOption; diff --git a/public/app/features/org/partials/team_details.html b/public/app/features/org/partials/team_details.html index 4835facb785..f91c29c3bb3 100644 --- a/public/app/features/org/partials/team_details.html +++ b/public/app/features/org/partials/team_details.html @@ -30,7 +30,14 @@
Add member - + +
+
+ +
+
+ Add member +
diff --git a/public/app/features/org/team_details_ctrl.ts b/public/app/features/org/team_details_ctrl.ts index 0147e4d3d28..e2ae33491bb 100644 --- a/public/app/features/org/team_details_ctrl.ts +++ b/public/app/features/org/team_details_ctrl.ts @@ -1,4 +1,4 @@ -import coreModule from 'app/core/core_module'; +import coreModule from "app/core/core_module"; export default class TeamDetailsCtrl { team: Team; @@ -6,8 +6,14 @@ export default class TeamDetailsCtrl { navModel: any; /** @ngInject **/ - constructor(private $scope, private backendSrv, private $routeParams, navModelSrv) { - this.navModel = navModelSrv.getNav('cfg', 'teams', 0); + constructor( + private $scope, + private backendSrv, + private $routeParams, + navModelSrv + ) { + this.navModel = navModelSrv.getNav("cfg", "teams", 0); + this.get = this.get.bind(this); this.get(); } @@ -35,7 +41,7 @@ export default class TeamDetailsCtrl { } removeMemberConfirmed(teamMember: TeamMember) { - this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`).then(this.get.bind(this)); + this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`).then(this.get); } update() { diff --git a/public/app/features/org/team_details_ctrl_BACKUP_16633.ts b/public/app/features/org/team_details_ctrl_BACKUP_16633.ts new file mode 100644 index 00000000000..ed98f4c40ff --- /dev/null +++ b/public/app/features/org/team_details_ctrl_BACKUP_16633.ts @@ -0,0 +1,127 @@ +import coreModule from "app/core/core_module"; + +export default class TeamDetailsCtrl { + team: Team; + teamMembers: User[] = []; + navModel: any; + + /** @ngInject **/ + constructor( + private $scope, + private backendSrv, + private $routeParams, + navModelSrv + ) { + this.navModel = navModelSrv.getNav("cfg", "teams", 0); + this.get = this.get.bind(this); + this.get(); + } + + get() { + if (this.$routeParams && this.$routeParams.id) { + this.backendSrv.get(`/api/teams/${this.$routeParams.id}`).then(result => { + this.team = result; + }); +<<<<<<< HEAD + this.backendSrv.get(`/api/teams/${this.$routeParams.id}/members`).then(result => { + this.teamMembers = result; + }); +======= + this.backendSrv + .get(`/api/teams/${this.$routeParams.id}/members`) + .then(result => { + this.teamMembers = result; + }); +>>>>>>> ux: POC on new select box for the user picker (#10289) + } + } + + removeTeamMember(teamMember: TeamMember) { +<<<<<<< HEAD + this.$scope.appEvent('confirm-modal', { + title: 'Remove Member', + text: 'Are you sure you want to remove ' + teamMember.login + ' from this group?', + yesText: 'Remove', + icon: 'fa-warning', +======= + this.$scope.appEvent("confirm-modal", { + title: "Remove Member", + text: + "Are you sure you want to remove " + + teamMember.login + + " from this group?", + yesText: "Remove", + icon: "fa-warning", +>>>>>>> ux: POC on new select box for the user picker (#10289) + onConfirm: () => { + this.removeMemberConfirmed(teamMember); + }, + }); + } + + removeMemberConfirmed(teamMember: TeamMember) { +<<<<<<< HEAD + this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`).then(this.get.bind(this)); +======= + this.backendSrv + .delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`) + .then(this.get); +>>>>>>> ux: POC on new select box for the user picker (#10289) + } + + update() { + if (!this.$scope.teamDetailsForm.$valid) { + return; + } + +<<<<<<< HEAD + this.backendSrv.put('/api/teams/' + this.team.id, { + name: this.team.name, + email: this.team.email, + }); + } + + userPicked(user) { + this.backendSrv.post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }).then(() => { + this.$scope.$broadcast('user-picker-reset'); + this.get(); + }); +======= + this.backendSrv.put("/api/teams/" + this.team.id, { name: this.team.name }); + } + + userPicked(user) { + this.backendSrv + .post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }) + .then(() => { + this.$scope.$broadcast("user-picker-reset"); + this.get(); + }); +>>>>>>> ux: POC on new select box for the user picker (#10289) + } +} + +export interface Team { + id: number; + name: string; + email: string; +} + +export interface User { + id: number; + name: string; + login: string; + email: string; +} + +export interface TeamMember { + userId: number; + name: string; + login: string; +} + +<<<<<<< HEAD +coreModule.controller('TeamDetailsCtrl', TeamDetailsCtrl); +======= +coreModule.controller("TeamDetailsCtrl", TeamDetailsCtrl); +>>>>>>> ux: POC on new select box for the user picker (#10289) diff --git a/public/app/features/org/team_details_ctrl_BASE_16633.ts b/public/app/features/org/team_details_ctrl_BASE_16633.ts new file mode 100644 index 00000000000..e96c3512180 --- /dev/null +++ b/public/app/features/org/team_details_ctrl_BASE_16633.ts @@ -0,0 +1,77 @@ +import coreModule from 'app/core/core_module'; + +export default class TeamDetailsCtrl { + team: Team; + teamMembers: User[] = []; + navModel: any; + + /** @ngInject **/ + constructor(private $scope, private backendSrv, private $routeParams, navModelSrv) { + this.navModel = navModelSrv.getNav('cfg', 'teams', 0); + this.get(); + } + + get() { + if (this.$routeParams && this.$routeParams.id) { + this.backendSrv.get(`/api/teams/${this.$routeParams.id}`) + .then(result => { + this.team = result; + }); + this.backendSrv.get(`/api/teams/${this.$routeParams.id}/members`) + .then(result => { + this.teamMembers = result; + }); + } + } + + removeTeamMember(teamMember: TeamMember) { + this.$scope.appEvent('confirm-modal', { + title: 'Remove Member', + text: 'Are you sure you want to remove ' + teamMember.login + ' from this group?', + yesText: "Remove", + icon: "fa-warning", + onConfirm: () => { + this.removeMemberConfirmed(teamMember); + } + }); + } + + removeMemberConfirmed(teamMember: TeamMember) { + this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`) + .then(this.get.bind(this)); + } + + update() { + if (!this.$scope.teamDetailsForm.$valid) { return; } + + this.backendSrv.put('/api/teams/' + this.team.id, {name: this.team.name}); + } + + userPicked(user) { + this.backendSrv.post(`/api/teams/${this.$routeParams.id}/members`, {userId: user.id}).then(() => { + this.$scope.$broadcast('user-picker-reset'); + this.get(); + }); + } +} + +export interface Team { + id: number; + name: string; +} + +export interface User { + id: number; + name: string; + login: string; + email: string; +} + +export interface TeamMember { + userId: number; + name: string; + login: string; +} + +coreModule.controller('TeamDetailsCtrl', TeamDetailsCtrl); + diff --git a/public/app/features/org/team_details_ctrl_LOCAL_16633.ts b/public/app/features/org/team_details_ctrl_LOCAL_16633.ts new file mode 100644 index 00000000000..0147e4d3d28 --- /dev/null +++ b/public/app/features/org/team_details_ctrl_LOCAL_16633.ts @@ -0,0 +1,79 @@ +import coreModule from 'app/core/core_module'; + +export default class TeamDetailsCtrl { + team: Team; + teamMembers: User[] = []; + navModel: any; + + /** @ngInject **/ + constructor(private $scope, private backendSrv, private $routeParams, navModelSrv) { + this.navModel = navModelSrv.getNav('cfg', 'teams', 0); + this.get(); + } + + get() { + if (this.$routeParams && this.$routeParams.id) { + this.backendSrv.get(`/api/teams/${this.$routeParams.id}`).then(result => { + this.team = result; + }); + this.backendSrv.get(`/api/teams/${this.$routeParams.id}/members`).then(result => { + this.teamMembers = result; + }); + } + } + + removeTeamMember(teamMember: TeamMember) { + this.$scope.appEvent('confirm-modal', { + title: 'Remove Member', + text: 'Are you sure you want to remove ' + teamMember.login + ' from this group?', + yesText: 'Remove', + icon: 'fa-warning', + onConfirm: () => { + this.removeMemberConfirmed(teamMember); + }, + }); + } + + removeMemberConfirmed(teamMember: TeamMember) { + this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`).then(this.get.bind(this)); + } + + update() { + if (!this.$scope.teamDetailsForm.$valid) { + return; + } + + this.backendSrv.put('/api/teams/' + this.team.id, { + name: this.team.name, + email: this.team.email, + }); + } + + userPicked(user) { + this.backendSrv.post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }).then(() => { + this.$scope.$broadcast('user-picker-reset'); + this.get(); + }); + } +} + +export interface Team { + id: number; + name: string; + email: string; +} + +export interface User { + id: number; + name: string; + login: string; + email: string; +} + +export interface TeamMember { + userId: number; + name: string; + login: string; +} + +coreModule.controller('TeamDetailsCtrl', TeamDetailsCtrl); diff --git a/public/app/features/org/team_details_ctrl_REMOTE_16633.ts b/public/app/features/org/team_details_ctrl_REMOTE_16633.ts new file mode 100644 index 00000000000..f623d2941b1 --- /dev/null +++ b/public/app/features/org/team_details_ctrl_REMOTE_16633.ts @@ -0,0 +1,90 @@ +import coreModule from "app/core/core_module"; + +export default class TeamDetailsCtrl { + team: Team; + teamMembers: User[] = []; + navModel: any; + + /** @ngInject **/ + constructor( + private $scope, + private backendSrv, + private $routeParams, + navModelSrv + ) { + this.navModel = navModelSrv.getNav("cfg", "teams", 0); + this.get = this.get.bind(this); + this.get(); + } + + get() { + if (this.$routeParams && this.$routeParams.id) { + this.backendSrv.get(`/api/teams/${this.$routeParams.id}`).then(result => { + this.team = result; + }); + this.backendSrv + .get(`/api/teams/${this.$routeParams.id}/members`) + .then(result => { + this.teamMembers = result; + }); + } + } + + removeTeamMember(teamMember: TeamMember) { + this.$scope.appEvent("confirm-modal", { + title: "Remove Member", + text: + "Are you sure you want to remove " + + teamMember.login + + " from this group?", + yesText: "Remove", + icon: "fa-warning", + onConfirm: () => { + this.removeMemberConfirmed(teamMember); + } + }); + } + + removeMemberConfirmed(teamMember: TeamMember) { + this.backendSrv + .delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`) + .then(this.get); + } + + update() { + if (!this.$scope.teamDetailsForm.$valid) { + return; + } + + this.backendSrv.put("/api/teams/" + this.team.id, { name: this.team.name }); + } + + userPicked(user) { + this.backendSrv + .post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }) + .then(() => { + this.$scope.$broadcast("user-picker-reset"); + this.get(); + }); + } +} + +export interface Team { + id: number; + name: string; +} + +export interface User { + id: number; + name: string; + login: string; + email: string; +} + +export interface TeamMember { + userId: number; + name: string; + login: string; +} + +coreModule.controller("TeamDetailsCtrl", TeamDetailsCtrl); diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 3232e9c7f8e..a973fae1153 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -88,7 +88,8 @@ @import "components/page_header"; @import "components/dashboard_settings"; @import "components/empty_list_cta"; - +@import "components/user-picker"; +@import "components/form_dropdown"; // PAGES @import "pages/login"; @import "pages/dashboard"; diff --git a/public/sass/components/_form_dropdown.scss b/public/sass/components/_form_dropdown.scss new file mode 100644 index 00000000000..a3572afe679 --- /dev/null +++ b/public/sass/components/_form_dropdown.scss @@ -0,0 +1,165 @@ +$select-input-height: 35px; +$select-menu-max-height: 300px; +$select-item-font-size: $font-size-base; +$select-item-bg: $dropdownBackground; +$select-item-fg: $input-color; +$select-option-bg: $dropdownBackground; +$select-option-color: $input-color; +@import "../../../node_modules/react-select/scss/default.scss"; + +@mixin select-control() { + width: 100%; + margin-right: $gf-form-margin; + @include border-radius($input-border-radius-sm); + background-color: $input-bg; +} + +@mixin select-control-focus() { + border-color: $input-border-focus; + outline: none; + $shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px $input-box-shadow-focus; + @include box-shadow($shadow); +} + +// gf- +// .form-dropdown { + +// } + +.gf-form-input--form-dropdown { + padding: 0; + border: 0; + overflow: visible; + + .Select-placeholder { + color: #d8d9da; + } + + > .Select-control { + @include select-control(); + border-color: #262628; + } + + &.is-open > .Select-control { + background: transparent; + border-color: #262628; + } + + &.is-focused > .Select-control { + background-color: $input-bg; + @include select-control-focus(); + } + + .Select-menu-outer { + border: 0; + width: auto; + } + + .Select-option.is-focused { + background-color: $dropdownLinkBackgroundHover; + color: $dropdownLinkColorHover; + + &::before { + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 2px; + display: block; + content: ""; + background-image: linear-gradient( + to bottom, + #ffd500 0%, + #ff4400 99%, + #ff4400 100% + ); + } + } +} + +// gf-form-input--dropdown + +// @mixin select-control() { +// width: 100%; +// margin-right: $gf-form-margin; +// @include border-radius($input-border-radius-sm); +// } + +// @mixin select-control-focus() { +// border-color: $input-border-focus; +// outline: none; +// $shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px $input-box-shadow-focus; +// @include box-shadow($shadow); +// } + +// .gf-form-dropdown-react { +// padding: 0px; +// } + +// .Select { +// &.is-focused > .Select-control { +// background-color: $input-bg; +// @include select-control-focus(); +// } +// &.is-focused:not(.is-open)>.Select-control, +// &.is-focused:not(.is-open).is-pseudo-focused>.Select-control { +// background-color: $input-label-bg; +// border: none; +// box-shadow: none; +// } +// &.has-value.Select--single>.Select-control .Select-value, +// &.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value { +// .Select-value-label { +// color: $input-color; +// } +// } +// } + +// .gf-form-label { + +// .Select-control { +// @include select-control(); +// font-size: $font-size-sm; +// color: $input-color; +// background-color: $input-label-bg; // padding: $input-padding-y $input-padding-x; +// display: block; +// border: $input-btn-border-width solid transparent; +// } +// } + +// .gf-form-input { +// overflow: visible; + +// .Select-control { +// @include select-control(); +// background-color: $input-bg; +// color: $input-color; +// border: $input-btn-border-width solid $input-border-color; +// } +// } + +// .Select-menu-outer { +// margin: 2px 0 0; +// border: 1px solid $dropdownBorder; +// background: $dropdownBackground; +// @include border-radius($input-border-radius-sm); +// } + +// .Select-option { +// font-size: $font-size-sm; +// padding: 3px 20px 3px 15px; +// &:last-child { +// @include border-radius($input-border-radius-sm); +// } +// &.is-selected { +// background-color: $dropdownLinkBackgroundHover; +// color: $dropdownLinkColorHover; +// } +// &.is-focused { +// background-color: $dropdownLinkBackgroundHover; +// color: $dropdownLinkColorHover; +// } +// &.is-disabled { +// color: $gray-2; +// } +// } diff --git a/public/sass/components/_user-picker.scss b/public/sass/components/_user-picker.scss new file mode 100644 index 00000000000..f61dafc54c6 --- /dev/null +++ b/public/sass/components/_user-picker.scss @@ -0,0 +1,28 @@ +.user-picker-option__button { + position: relative; + text-align: left; + width: 100%; + background-color: #171819; + display: block; + border-radius: 0; + + // &:hover { + // background-color: #262628; + // // background-color: blue; + // &::before { + // position: absolute; + // left: 0; + // top: 0; + // height: 100%; + // width: 2px; + // display: block; + // content: ''; + // background-image: linear-gradient(to bottom, #ffd500 0%, #ff4400 99%, #ff4400 100%); + // } + // } +} +.user-picker-option__avatar { + width: 20px; + display: inline-block; + margin-right: 10px; +} From 68d43b865f0f3d9e9401d8d1df39aee6435b4251 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 21 Dec 2017 09:03:30 +0100 Subject: [PATCH 2/9] fix: Add interface for props to UserPickerOption (#10289) --- .../core/components/UserPicker/UserPickerOption.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/public/app/core/components/UserPicker/UserPickerOption.tsx b/public/app/core/components/UserPicker/UserPickerOption.tsx index 145784127ee..c052631d295 100644 --- a/public/app/core/components/UserPicker/UserPickerOption.tsx +++ b/public/app/core/components/UserPicker/UserPickerOption.tsx @@ -1,6 +1,12 @@ import React, { Component } from "react"; - -class UserPickerOption extends Component { +export interface IProps { + onSelect: any; + onFocus: any; + option: any; + isFocused: any; + className: any; +} +class UserPickerOption extends Component { constructor(props) { super(props); this.handleMouseDown = this.handleMouseDown.bind(this); From 76ba7d1f8cf2d3351d6be7f2567d4394a27fadb7 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 21 Dec 2017 10:30:03 +0100 Subject: [PATCH 3/9] test: Add snapshot tests for UserPicker and UserPickerOption (#10289) --- .../EmptyListCTA/EmptyListCTA.jest.tsx | 21 ++-- .../__snapshots__/EmptyListCTA.jest.tsx.snap | 2 +- .../components/UserPicker/UserPicker.jest.tsx | 20 ++++ .../UserPicker/UserPickerOption.jest.tsx | 22 +++++ .../UserPicker/UserPickerOption.tsx | 10 +- .../__snapshots__/UserPicker.jest.tsx.snap | 98 +++++++++++++++++++ .../UserPickerOption.jest.tsx.snap | 17 ++++ 7 files changed, 172 insertions(+), 18 deletions(-) create mode 100644 public/app/core/components/UserPicker/UserPicker.jest.tsx create mode 100644 public/app/core/components/UserPicker/UserPickerOption.jest.tsx create mode 100644 public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap create mode 100644 public/app/core/components/UserPicker/__snapshots__/UserPickerOption.jest.tsx.snap diff --git a/public/app/core/components/EmptyListCTA/EmptyListCTA.jest.tsx b/public/app/core/components/EmptyListCTA/EmptyListCTA.jest.tsx index d62ae892a0a..4af60f3c839 100644 --- a/public/app/core/components/EmptyListCTA/EmptyListCTA.jest.tsx +++ b/public/app/core/components/EmptyListCTA/EmptyListCTA.jest.tsx @@ -3,19 +3,18 @@ import renderer from 'react-test-renderer'; import EmptyListCTA from './EmptyListCTA'; const model = { - title: 'Title', - buttonIcon: 'ga css class', - buttonLink: 'http://url/to/destination', - buttonTitle: 'Click me', - proTip: 'This is a tip', - proTipLink: 'http://url/to/tip/destination', - proTipLinkTitle: 'Learn more', - proTipTarget: '_blank' + title: 'Title', + buttonIcon: 'ga css class', + buttonLink: 'http://url/to/destination', + buttonTitle: 'Click me', + proTip: 'This is a tip', + proTipLink: 'http://url/to/tip/destination', + proTipLinkTitle: 'Learn more', + proTipTarget: '_blank', }; -describe('CollorPalette', () => { - - it('renders correctly', () => { +describe('EmptyListCTA', () => { + it('renders correctly', () => { const tree = renderer.create().toJSON(); expect(tree).toMatchSnapshot(); }); diff --git a/public/app/core/components/EmptyListCTA/__snapshots__/EmptyListCTA.jest.tsx.snap b/public/app/core/components/EmptyListCTA/__snapshots__/EmptyListCTA.jest.tsx.snap index 0da3d94aaa8..6d47c984d5e 100644 --- a/public/app/core/components/EmptyListCTA/__snapshots__/EmptyListCTA.jest.tsx.snap +++ b/public/app/core/components/EmptyListCTA/__snapshots__/EmptyListCTA.jest.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`CollorPalette renders correctly 1`] = ` +exports[`EmptyListCTA renders correctly 1`] = `
diff --git a/public/app/core/components/UserPicker/UserPicker.jest.tsx b/public/app/core/components/UserPicker/UserPicker.jest.tsx new file mode 100644 index 00000000000..0e3c672dcbe --- /dev/null +++ b/public/app/core/components/UserPicker/UserPicker.jest.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import UserPicker from './UserPicker'; + +const model = { + backendSrv: { + get: () => { + return new Promise((resolve, reject) => {}); + }, + }, + refreshList: () => {}, + teamId: '1', +}; + +describe('UserPicker', () => { + it('renders correctly', () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/UserPicker/UserPickerOption.jest.tsx b/public/app/core/components/UserPicker/UserPickerOption.jest.tsx new file mode 100644 index 00000000000..6903d648870 --- /dev/null +++ b/public/app/core/components/UserPicker/UserPickerOption.jest.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import UserPickerOption from './UserPickerOption'; + +const model = { + onSelect: () => {}, + onFocus: () => {}, + isFocused: () => {}, + option: { + title: 'Model title', + avatarUrl: 'url/to/avatar', + label: 'User picker label', + }, + className: 'class-for-user-picker', +}; + +describe('UserPickerOption', () => { + it('renders correctly', () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/UserPicker/UserPickerOption.tsx b/public/app/core/components/UserPicker/UserPickerOption.tsx index c052631d295..42a079802a8 100644 --- a/public/app/core/components/UserPicker/UserPickerOption.tsx +++ b/public/app/core/components/UserPicker/UserPickerOption.tsx @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import React, { Component } from 'react'; export interface IProps { onSelect: any; onFocus: any; @@ -19,9 +19,11 @@ class UserPickerOption extends Component { event.stopPropagation(); this.props.onSelect(this.props.option, event); } + handleMouseEnter(event) { this.props.onFocus(this.props.option, event); } + handleMouseMove(event) { if (this.props.isFocused) { return; @@ -40,11 +42,7 @@ class UserPickerOption extends Component { title={option.title} className={`user-picker-option__button btn btn-link ${className}`} > - {option.label} + {option.label} {children} ); diff --git a/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap b/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap new file mode 100644 index 00000000000..e0d6f2a9a11 --- /dev/null +++ b/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UserPicker renders correctly 1`] = ` +
+
+
+ +
+ Loading... +
+
+ +
+ +
+
+
+
+
+
+`; diff --git a/public/app/core/components/UserPicker/__snapshots__/UserPickerOption.jest.tsx.snap b/public/app/core/components/UserPicker/__snapshots__/UserPickerOption.jest.tsx.snap new file mode 100644 index 00000000000..3b9351b2338 --- /dev/null +++ b/public/app/core/components/UserPicker/__snapshots__/UserPickerOption.jest.tsx.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`UserPickerOption renders correctly 1`] = ` + +`; From 1a993378bd540fd19b7c6111f7e2d5e99bd12854 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 21 Dec 2017 10:34:07 +0100 Subject: [PATCH 4/9] fix: Accidently added the conflict files (#10289) --- .../org/team_details_ctrl_BACKUP_16633.ts | 127 ------------------ .../org/team_details_ctrl_BASE_16633.ts | 77 ----------- .../org/team_details_ctrl_LOCAL_16633.ts | 79 ----------- .../org/team_details_ctrl_REMOTE_16633.ts | 90 ------------- 4 files changed, 373 deletions(-) delete mode 100644 public/app/features/org/team_details_ctrl_BACKUP_16633.ts delete mode 100644 public/app/features/org/team_details_ctrl_BASE_16633.ts delete mode 100644 public/app/features/org/team_details_ctrl_LOCAL_16633.ts delete mode 100644 public/app/features/org/team_details_ctrl_REMOTE_16633.ts diff --git a/public/app/features/org/team_details_ctrl_BACKUP_16633.ts b/public/app/features/org/team_details_ctrl_BACKUP_16633.ts deleted file mode 100644 index ed98f4c40ff..00000000000 --- a/public/app/features/org/team_details_ctrl_BACKUP_16633.ts +++ /dev/null @@ -1,127 +0,0 @@ -import coreModule from "app/core/core_module"; - -export default class TeamDetailsCtrl { - team: Team; - teamMembers: User[] = []; - navModel: any; - - /** @ngInject **/ - constructor( - private $scope, - private backendSrv, - private $routeParams, - navModelSrv - ) { - this.navModel = navModelSrv.getNav("cfg", "teams", 0); - this.get = this.get.bind(this); - this.get(); - } - - get() { - if (this.$routeParams && this.$routeParams.id) { - this.backendSrv.get(`/api/teams/${this.$routeParams.id}`).then(result => { - this.team = result; - }); -<<<<<<< HEAD - this.backendSrv.get(`/api/teams/${this.$routeParams.id}/members`).then(result => { - this.teamMembers = result; - }); -======= - this.backendSrv - .get(`/api/teams/${this.$routeParams.id}/members`) - .then(result => { - this.teamMembers = result; - }); ->>>>>>> ux: POC on new select box for the user picker (#10289) - } - } - - removeTeamMember(teamMember: TeamMember) { -<<<<<<< HEAD - this.$scope.appEvent('confirm-modal', { - title: 'Remove Member', - text: 'Are you sure you want to remove ' + teamMember.login + ' from this group?', - yesText: 'Remove', - icon: 'fa-warning', -======= - this.$scope.appEvent("confirm-modal", { - title: "Remove Member", - text: - "Are you sure you want to remove " + - teamMember.login + - " from this group?", - yesText: "Remove", - icon: "fa-warning", ->>>>>>> ux: POC on new select box for the user picker (#10289) - onConfirm: () => { - this.removeMemberConfirmed(teamMember); - }, - }); - } - - removeMemberConfirmed(teamMember: TeamMember) { -<<<<<<< HEAD - this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`).then(this.get.bind(this)); -======= - this.backendSrv - .delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`) - .then(this.get); ->>>>>>> ux: POC on new select box for the user picker (#10289) - } - - update() { - if (!this.$scope.teamDetailsForm.$valid) { - return; - } - -<<<<<<< HEAD - this.backendSrv.put('/api/teams/' + this.team.id, { - name: this.team.name, - email: this.team.email, - }); - } - - userPicked(user) { - this.backendSrv.post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }).then(() => { - this.$scope.$broadcast('user-picker-reset'); - this.get(); - }); -======= - this.backendSrv.put("/api/teams/" + this.team.id, { name: this.team.name }); - } - - userPicked(user) { - this.backendSrv - .post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }) - .then(() => { - this.$scope.$broadcast("user-picker-reset"); - this.get(); - }); ->>>>>>> ux: POC on new select box for the user picker (#10289) - } -} - -export interface Team { - id: number; - name: string; - email: string; -} - -export interface User { - id: number; - name: string; - login: string; - email: string; -} - -export interface TeamMember { - userId: number; - name: string; - login: string; -} - -<<<<<<< HEAD -coreModule.controller('TeamDetailsCtrl', TeamDetailsCtrl); -======= -coreModule.controller("TeamDetailsCtrl", TeamDetailsCtrl); ->>>>>>> ux: POC on new select box for the user picker (#10289) diff --git a/public/app/features/org/team_details_ctrl_BASE_16633.ts b/public/app/features/org/team_details_ctrl_BASE_16633.ts deleted file mode 100644 index e96c3512180..00000000000 --- a/public/app/features/org/team_details_ctrl_BASE_16633.ts +++ /dev/null @@ -1,77 +0,0 @@ -import coreModule from 'app/core/core_module'; - -export default class TeamDetailsCtrl { - team: Team; - teamMembers: User[] = []; - navModel: any; - - /** @ngInject **/ - constructor(private $scope, private backendSrv, private $routeParams, navModelSrv) { - this.navModel = navModelSrv.getNav('cfg', 'teams', 0); - this.get(); - } - - get() { - if (this.$routeParams && this.$routeParams.id) { - this.backendSrv.get(`/api/teams/${this.$routeParams.id}`) - .then(result => { - this.team = result; - }); - this.backendSrv.get(`/api/teams/${this.$routeParams.id}/members`) - .then(result => { - this.teamMembers = result; - }); - } - } - - removeTeamMember(teamMember: TeamMember) { - this.$scope.appEvent('confirm-modal', { - title: 'Remove Member', - text: 'Are you sure you want to remove ' + teamMember.login + ' from this group?', - yesText: "Remove", - icon: "fa-warning", - onConfirm: () => { - this.removeMemberConfirmed(teamMember); - } - }); - } - - removeMemberConfirmed(teamMember: TeamMember) { - this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`) - .then(this.get.bind(this)); - } - - update() { - if (!this.$scope.teamDetailsForm.$valid) { return; } - - this.backendSrv.put('/api/teams/' + this.team.id, {name: this.team.name}); - } - - userPicked(user) { - this.backendSrv.post(`/api/teams/${this.$routeParams.id}/members`, {userId: user.id}).then(() => { - this.$scope.$broadcast('user-picker-reset'); - this.get(); - }); - } -} - -export interface Team { - id: number; - name: string; -} - -export interface User { - id: number; - name: string; - login: string; - email: string; -} - -export interface TeamMember { - userId: number; - name: string; - login: string; -} - -coreModule.controller('TeamDetailsCtrl', TeamDetailsCtrl); - diff --git a/public/app/features/org/team_details_ctrl_LOCAL_16633.ts b/public/app/features/org/team_details_ctrl_LOCAL_16633.ts deleted file mode 100644 index 0147e4d3d28..00000000000 --- a/public/app/features/org/team_details_ctrl_LOCAL_16633.ts +++ /dev/null @@ -1,79 +0,0 @@ -import coreModule from 'app/core/core_module'; - -export default class TeamDetailsCtrl { - team: Team; - teamMembers: User[] = []; - navModel: any; - - /** @ngInject **/ - constructor(private $scope, private backendSrv, private $routeParams, navModelSrv) { - this.navModel = navModelSrv.getNav('cfg', 'teams', 0); - this.get(); - } - - get() { - if (this.$routeParams && this.$routeParams.id) { - this.backendSrv.get(`/api/teams/${this.$routeParams.id}`).then(result => { - this.team = result; - }); - this.backendSrv.get(`/api/teams/${this.$routeParams.id}/members`).then(result => { - this.teamMembers = result; - }); - } - } - - removeTeamMember(teamMember: TeamMember) { - this.$scope.appEvent('confirm-modal', { - title: 'Remove Member', - text: 'Are you sure you want to remove ' + teamMember.login + ' from this group?', - yesText: 'Remove', - icon: 'fa-warning', - onConfirm: () => { - this.removeMemberConfirmed(teamMember); - }, - }); - } - - removeMemberConfirmed(teamMember: TeamMember) { - this.backendSrv.delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`).then(this.get.bind(this)); - } - - update() { - if (!this.$scope.teamDetailsForm.$valid) { - return; - } - - this.backendSrv.put('/api/teams/' + this.team.id, { - name: this.team.name, - email: this.team.email, - }); - } - - userPicked(user) { - this.backendSrv.post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }).then(() => { - this.$scope.$broadcast('user-picker-reset'); - this.get(); - }); - } -} - -export interface Team { - id: number; - name: string; - email: string; -} - -export interface User { - id: number; - name: string; - login: string; - email: string; -} - -export interface TeamMember { - userId: number; - name: string; - login: string; -} - -coreModule.controller('TeamDetailsCtrl', TeamDetailsCtrl); diff --git a/public/app/features/org/team_details_ctrl_REMOTE_16633.ts b/public/app/features/org/team_details_ctrl_REMOTE_16633.ts deleted file mode 100644 index f623d2941b1..00000000000 --- a/public/app/features/org/team_details_ctrl_REMOTE_16633.ts +++ /dev/null @@ -1,90 +0,0 @@ -import coreModule from "app/core/core_module"; - -export default class TeamDetailsCtrl { - team: Team; - teamMembers: User[] = []; - navModel: any; - - /** @ngInject **/ - constructor( - private $scope, - private backendSrv, - private $routeParams, - navModelSrv - ) { - this.navModel = navModelSrv.getNav("cfg", "teams", 0); - this.get = this.get.bind(this); - this.get(); - } - - get() { - if (this.$routeParams && this.$routeParams.id) { - this.backendSrv.get(`/api/teams/${this.$routeParams.id}`).then(result => { - this.team = result; - }); - this.backendSrv - .get(`/api/teams/${this.$routeParams.id}/members`) - .then(result => { - this.teamMembers = result; - }); - } - } - - removeTeamMember(teamMember: TeamMember) { - this.$scope.appEvent("confirm-modal", { - title: "Remove Member", - text: - "Are you sure you want to remove " + - teamMember.login + - " from this group?", - yesText: "Remove", - icon: "fa-warning", - onConfirm: () => { - this.removeMemberConfirmed(teamMember); - } - }); - } - - removeMemberConfirmed(teamMember: TeamMember) { - this.backendSrv - .delete(`/api/teams/${this.$routeParams.id}/members/${teamMember.userId}`) - .then(this.get); - } - - update() { - if (!this.$scope.teamDetailsForm.$valid) { - return; - } - - this.backendSrv.put("/api/teams/" + this.team.id, { name: this.team.name }); - } - - userPicked(user) { - this.backendSrv - .post(`/api/teams/${this.$routeParams.id}/members`, { userId: user.id }) - .then(() => { - this.$scope.$broadcast("user-picker-reset"); - this.get(); - }); - } -} - -export interface Team { - id: number; - name: string; -} - -export interface User { - id: number; - name: string; - login: string; - email: string; -} - -export interface TeamMember { - userId: number; - name: string; - login: string; -} - -coreModule.controller("TeamDetailsCtrl", TeamDetailsCtrl); From c297a1c5a5fee0de3762cd8550b907a0392fd211 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 3 Jan 2018 15:50:39 +0100 Subject: [PATCH 5/9] fix: Rename directive user-pickerr (yes two r's) to select-user-picker --- public/app/core/angular_wrappers.ts | 30 +++++++--------- public/app/core/angular_wrappers.ts.orig | 36 +++++++++++++++++++ .../features/org/partials/team_details.html | 10 +----- 3 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 public/app/core/angular_wrappers.ts.orig diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index 0b3974e7966..6e68e7c8d2f 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -1,20 +1,16 @@ -import { react2AngularDirective } from "app/core/utils/react2angular"; -import { PasswordStrength } from "./components/PasswordStrength"; -import PageHeader from "./components/PageHeader/PageHeader"; -import EmptyListCTA from "./components/EmptyListCTA/EmptyListCTA"; -import LoginBackground from "./components/Login/LoginBackground"; -import { SearchResult } from "./components/search/SearchResult"; -import UserPicker from "./components/UserPicker/UserPicker"; +import { react2AngularDirective } from 'app/core/utils/react2angular'; +import { PasswordStrength } from './components/PasswordStrength'; +import PageHeader from './components/PageHeader/PageHeader'; +import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA'; +import LoginBackground from './components/Login/LoginBackground'; +import { SearchResult } from './components/search/SearchResult'; +import UserPicker from './components/UserPicker/UserPicker'; export function registerAngularDirectives() { - react2AngularDirective("passwordStrength", PasswordStrength, ["password"]); - react2AngularDirective("pageHeader", PageHeader, ["model", "noTabs"]); - react2AngularDirective("emptyListCta", EmptyListCTA, ["model"]); - react2AngularDirective("loginBackground", LoginBackground, []); - react2AngularDirective("searchResult", SearchResult, []); - react2AngularDirective("userPickerr", UserPicker, [ - "backendSrv", - "teamId", - "refreshList" - ]); + react2AngularDirective('passwordStrength', PasswordStrength, ['password']); + react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); + react2AngularDirective('emptyListCta', EmptyListCTA, ['model']); + react2AngularDirective('loginBackground', LoginBackground, []); + react2AngularDirective('searchResult', SearchResult, []); + react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'teamId', 'refreshList']); } diff --git a/public/app/core/angular_wrappers.ts.orig b/public/app/core/angular_wrappers.ts.orig new file mode 100644 index 00000000000..0ae4d981805 --- /dev/null +++ b/public/app/core/angular_wrappers.ts.orig @@ -0,0 +1,36 @@ +<<<<<<< HEAD +import { react2AngularDirective } from "app/core/utils/react2angular"; +import { PasswordStrength } from "./components/PasswordStrength"; +import PageHeader from "./components/PageHeader/PageHeader"; +import EmptyListCTA from "./components/EmptyListCTA/EmptyListCTA"; +import LoginBackground from "./components/Login/LoginBackground"; +import { SearchResult } from "./components/search/SearchResult"; +import UserPicker from "./components/UserPicker/UserPicker"; + +export function registerAngularDirectives() { + react2AngularDirective("passwordStrength", PasswordStrength, ["password"]); + react2AngularDirective("pageHeader", PageHeader, ["model", "noTabs"]); + react2AngularDirective("emptyListCta", EmptyListCTA, ["model"]); + react2AngularDirective("loginBackground", LoginBackground, []); + react2AngularDirective("searchResult", SearchResult, []); + react2AngularDirective("userPickerr", UserPicker, [ + "backendSrv", + "teamId", + "refreshList" + ]); +======= +import { react2AngularDirective } from 'app/core/utils/react2angular'; +import { PasswordStrength } from './components/PasswordStrength'; +import PageHeader from './components/PageHeader/PageHeader'; +import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA'; +import LoginBackground from './components/Login/LoginBackground'; +import UserPicker from './components/UserPicker/UserPicker'; + +export function registerAngularDirectives() { + react2AngularDirective('passwordStrength', PasswordStrength, ['password']); + react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); + react2AngularDirective('emptyListCta', EmptyListCTA, ['model']); + react2AngularDirective('loginBackground', LoginBackground, []); + react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'teamId', 'refreshList']); +>>>>>>> fix: Rename directive user-pickerr (yes two r's) to select-user-picker +} diff --git a/public/app/features/org/partials/team_details.html b/public/app/features/org/partials/team_details.html index f91c29c3bb3..e2666697869 100644 --- a/public/app/features/org/partials/team_details.html +++ b/public/app/features/org/partials/team_details.html @@ -26,18 +26,10 @@

Team Members

- -
-
- Add member - -
-
-
Add member - +
From c62a6aa7dfa94155031fe7ca039eb63108afdb47 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 3 Jan 2018 16:03:13 +0100 Subject: [PATCH 6/9] fix: Clean up logging and remove unused css #10289 --- .../core/components/UserPicker/UserPicker.tsx | 56 ++++----- public/sass/components/_form_dropdown.scss | 109 +----------------- public/sass/components/_user-picker.scss | 16 --- 3 files changed, 28 insertions(+), 153 deletions(-) diff --git a/public/app/core/components/UserPicker/UserPicker.tsx b/public/app/core/components/UserPicker/UserPicker.tsx index 3ead5be682a..a67c002f0d5 100644 --- a/public/app/core/components/UserPicker/UserPicker.tsx +++ b/public/app/core/components/UserPicker/UserPicker.tsx @@ -1,7 +1,7 @@ -import React, { Component } from "react"; -import { debounce } from "lodash"; -import Select from "react-select"; -import UserPickerOption from "./UserPickerOption"; +import React, { Component } from 'react'; +import { debounce } from 'lodash'; +import Select from 'react-select'; +import UserPickerOption from './UserPickerOption'; export interface IProps { backendSrv: any; teamId: string; @@ -34,21 +34,16 @@ class UserPicker extends Component { this.debouncedSearchUsers = debounce(this.searchUsers, 300, { leading: true, - trailing: false + trailing: false, }); this.state = { multi: false, - isLoading: false + isLoading: false, }; } - componentWillReceiveProps(nextProps) { - console.log("componentWillReceiveProps", nextProps); - } - handleChange(user) { - console.log("user", user); this.addUser(user.id); } @@ -56,44 +51,37 @@ class UserPicker extends Component { this.setState(prevState => { return { ...prevState, - isLoading: isLoading + isLoading: isLoading, }; }); } addUser(userId) { this.toggleLoading(true); - this.backendSrv - .post(`/api/teams/${this.teamId}/members`, { userId: userId }) - .then(() => { - this.refreshList(); // this.get() in the angular controller - this.toggleLoading(false); - // this.$scope.$broadcast('user-picker-reset'); // TODO? - }); + this.backendSrv.post(`/api/teams/${this.teamId}/members`, { userId: userId }).then(() => { + this.refreshList(); + this.toggleLoading(false); + }); } searchUsers(query) { this.toggleLoading(true); - return this.backendSrv - .get(`/api/users/search?perpage=10&page=1&query=${query}`) - .then(result => { - const users = result.users.map(user => { - return { - id: user.id, - label: `${user.login} - ${user.email}`, - avatarUrl: user.avatarUrl - }; - }); - this.toggleLoading(false); - return { options: users }; + return this.backendSrv.get(`/api/users/search?perpage=10&page=1&query=${query}`).then(result => { + const users = result.users.map(user => { + return { + id: user.id, + label: `${user.login} - ${user.email}`, + avatarUrl: user.avatarUrl, + }; }); + this.toggleLoading(false); + return { options: users }; + }); } render() { - const AsyncComponent = this.state.creatable - ? Select.AsyncCreatable - : Select.Async; + const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async; return (
diff --git a/public/sass/components/_form_dropdown.scss b/public/sass/components/_form_dropdown.scss index a3572afe679..7a8a23f3c24 100644 --- a/public/sass/components/_form_dropdown.scss +++ b/public/sass/components/_form_dropdown.scss @@ -5,7 +5,7 @@ $select-item-bg: $dropdownBackground; $select-item-fg: $input-color; $select-option-bg: $dropdownBackground; $select-option-color: $input-color; -@import "../../../node_modules/react-select/scss/default.scss"; +@import '../../../node_modules/react-select/scss/default.scss'; @mixin select-control() { width: 100%; @@ -21,28 +21,23 @@ $select-option-color: $input-color; @include box-shadow($shadow); } -// gf- -// .form-dropdown { - -// } - .gf-form-input--form-dropdown { padding: 0; border: 0; overflow: visible; .Select-placeholder { - color: #d8d9da; + color: $gray-4; } > .Select-control { @include select-control(); - border-color: #262628; + border-color: $dark-3; } &.is-open > .Select-control { background: transparent; - border-color: #262628; + border-color: $dark-3; } &.is-focused > .Select-control { @@ -66,100 +61,8 @@ $select-option-color: $input-color; height: 100%; width: 2px; display: block; - content: ""; - background-image: linear-gradient( - to bottom, - #ffd500 0%, - #ff4400 99%, - #ff4400 100% - ); + content: ''; + background-image: linear-gradient(to bottom, #ffd500 0%, #ff4400 99%, #ff4400 100%); } } } - -// gf-form-input--dropdown - -// @mixin select-control() { -// width: 100%; -// margin-right: $gf-form-margin; -// @include border-radius($input-border-radius-sm); -// } - -// @mixin select-control-focus() { -// border-color: $input-border-focus; -// outline: none; -// $shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px $input-box-shadow-focus; -// @include box-shadow($shadow); -// } - -// .gf-form-dropdown-react { -// padding: 0px; -// } - -// .Select { -// &.is-focused > .Select-control { -// background-color: $input-bg; -// @include select-control-focus(); -// } -// &.is-focused:not(.is-open)>.Select-control, -// &.is-focused:not(.is-open).is-pseudo-focused>.Select-control { -// background-color: $input-label-bg; -// border: none; -// box-shadow: none; -// } -// &.has-value.Select--single>.Select-control .Select-value, -// &.has-value.is-pseudo-focused.Select--single>.Select-control .Select-value { -// .Select-value-label { -// color: $input-color; -// } -// } -// } - -// .gf-form-label { - -// .Select-control { -// @include select-control(); -// font-size: $font-size-sm; -// color: $input-color; -// background-color: $input-label-bg; // padding: $input-padding-y $input-padding-x; -// display: block; -// border: $input-btn-border-width solid transparent; -// } -// } - -// .gf-form-input { -// overflow: visible; - -// .Select-control { -// @include select-control(); -// background-color: $input-bg; -// color: $input-color; -// border: $input-btn-border-width solid $input-border-color; -// } -// } - -// .Select-menu-outer { -// margin: 2px 0 0; -// border: 1px solid $dropdownBorder; -// background: $dropdownBackground; -// @include border-radius($input-border-radius-sm); -// } - -// .Select-option { -// font-size: $font-size-sm; -// padding: 3px 20px 3px 15px; -// &:last-child { -// @include border-radius($input-border-radius-sm); -// } -// &.is-selected { -// background-color: $dropdownLinkBackgroundHover; -// color: $dropdownLinkColorHover; -// } -// &.is-focused { -// background-color: $dropdownLinkBackgroundHover; -// color: $dropdownLinkColorHover; -// } -// &.is-disabled { -// color: $gray-2; -// } -// } diff --git a/public/sass/components/_user-picker.scss b/public/sass/components/_user-picker.scss index f61dafc54c6..35a2a242746 100644 --- a/public/sass/components/_user-picker.scss +++ b/public/sass/components/_user-picker.scss @@ -2,24 +2,8 @@ position: relative; text-align: left; width: 100%; - background-color: #171819; display: block; border-radius: 0; - - // &:hover { - // background-color: #262628; - // // background-color: blue; - // &::before { - // position: absolute; - // left: 0; - // top: 0; - // height: 100%; - // width: 2px; - // display: block; - // content: ''; - // background-image: linear-gradient(to bottom, #ffd500 0%, #ff4400 99%, #ff4400 100%); - // } - // } } .user-picker-option__avatar { width: 20px; From ffda5eef95ac56f7f2853f9f4ce053b5916c422b Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 9 Jan 2018 15:48:02 +0100 Subject: [PATCH 7/9] test: Updated snapshot for UserPicker jest test #10289 --- .../UserPicker/__snapshots__/UserPicker.jest.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap b/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap index e0d6f2a9a11..a1563ba8bc3 100644 --- a/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap +++ b/public/app/core/components/UserPicker/__snapshots__/UserPicker.jest.tsx.snap @@ -5,7 +5,7 @@ exports[`UserPicker renders correctly 1`] = ` className="user-picker" >
Date: Wed, 10 Jan 2018 12:00:28 +0100 Subject: [PATCH 8/9] fix: Remove conflict file #10289 --- public/app/core/angular_wrappers.ts.orig | 36 ------------------------ 1 file changed, 36 deletions(-) delete mode 100644 public/app/core/angular_wrappers.ts.orig diff --git a/public/app/core/angular_wrappers.ts.orig b/public/app/core/angular_wrappers.ts.orig deleted file mode 100644 index 0ae4d981805..00000000000 --- a/public/app/core/angular_wrappers.ts.orig +++ /dev/null @@ -1,36 +0,0 @@ -<<<<<<< HEAD -import { react2AngularDirective } from "app/core/utils/react2angular"; -import { PasswordStrength } from "./components/PasswordStrength"; -import PageHeader from "./components/PageHeader/PageHeader"; -import EmptyListCTA from "./components/EmptyListCTA/EmptyListCTA"; -import LoginBackground from "./components/Login/LoginBackground"; -import { SearchResult } from "./components/search/SearchResult"; -import UserPicker from "./components/UserPicker/UserPicker"; - -export function registerAngularDirectives() { - react2AngularDirective("passwordStrength", PasswordStrength, ["password"]); - react2AngularDirective("pageHeader", PageHeader, ["model", "noTabs"]); - react2AngularDirective("emptyListCta", EmptyListCTA, ["model"]); - react2AngularDirective("loginBackground", LoginBackground, []); - react2AngularDirective("searchResult", SearchResult, []); - react2AngularDirective("userPickerr", UserPicker, [ - "backendSrv", - "teamId", - "refreshList" - ]); -======= -import { react2AngularDirective } from 'app/core/utils/react2angular'; -import { PasswordStrength } from './components/PasswordStrength'; -import PageHeader from './components/PageHeader/PageHeader'; -import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA'; -import LoginBackground from './components/Login/LoginBackground'; -import UserPicker from './components/UserPicker/UserPicker'; - -export function registerAngularDirectives() { - react2AngularDirective('passwordStrength', PasswordStrength, ['password']); - react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); - react2AngularDirective('emptyListCta', EmptyListCTA, ['model']); - react2AngularDirective('loginBackground', LoginBackground, []); - react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'teamId', 'refreshList']); ->>>>>>> fix: Rename directive user-pickerr (yes two r's) to select-user-picker -} From 0b81117ee23f258cbb05b25dcea337a03a783308 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 10 Jan 2018 12:04:46 +0100 Subject: [PATCH 9/9] fix: Make sure orig files are not added to git again #10289 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 12e7bed3f46..deb1c1f882a 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,4 @@ debug.test /vendor/**/*_test.go /vendor/**/.editorconfig /vendor/**/appengine* +*.orig \ No newline at end of file