From 666d29fafae85b0d6f315d2bb8ca88f9fd166cbc Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 31 Jan 2018 10:39:38 +0100 Subject: [PATCH 1/9] dashfolders: POC - Use separate component for "Add permission" #10676 --- .../ManageDashboards/FolderPermissions.tsx | 19 +- .../components/Permissions/AddPermissions.tsx | 144 ++++++++++++++ .../components/Permissions/Permissions.tsx | 61 +----- .../app/core/components/Picker/TeamPicker.tsx | 4 +- .../app/core/components/Picker/UserPicker.tsx | 7 +- .../app/core/components/Picker/withPicker.tsx | 1 + .../PermissionsStore/PermissionsStore.ts | 184 +++++++++++++----- public/sass/components/_gf-form.scss | 6 + 8 files changed, 315 insertions(+), 111 deletions(-) create mode 100644 public/app/core/components/Permissions/AddPermissions.tsx diff --git a/public/app/containers/ManageDashboards/FolderPermissions.tsx b/public/app/containers/ManageDashboards/FolderPermissions.tsx index 3214382732a..98f63a46cbe 100644 --- a/public/app/containers/ManageDashboards/FolderPermissions.tsx +++ b/public/app/containers/ManageDashboards/FolderPermissions.tsx @@ -6,11 +6,14 @@ import PageHeader from 'app/core/components/PageHeader/PageHeader'; import Permissions from 'app/core/components/Permissions/Permissions'; import Tooltip from 'app/core/components/Tooltip/Tooltip'; import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo'; +import AddPermissions from 'app/core/components/Permissions/AddPermissions'; + @inject('nav', 'folder', 'view', 'permissions') @observer export class FolderPermissions extends Component { constructor(props) { super(props); + this.handleAddPermission = this.handleAddPermission.bind(this); this.loadStore(); } @@ -21,6 +24,11 @@ export class FolderPermissions extends Component { }); } + handleAddPermission() { + const { permissions } = this.props; + permissions.toggleAddPermissions(); + } + render() { const { nav, folder, permissions, backendSrv } = this.props; @@ -34,13 +42,20 @@ export class FolderPermissions extends Component {
-
+

Folder Permissions

+
+
- + {permissions.isAddPermissionsVisible ? ( + + ) : null}
diff --git a/public/app/core/components/Permissions/AddPermissions.tsx b/public/app/core/components/Permissions/AddPermissions.tsx new file mode 100644 index 00000000000..36b57e448e7 --- /dev/null +++ b/public/app/core/components/Permissions/AddPermissions.tsx @@ -0,0 +1,144 @@ +import React, { Component } from 'react'; +import { observer } from 'mobx-react'; +import { aclTypes } from 'app/stores/PermissionsStore/PermissionsStore'; +import UserPicker, { User } from 'app/core/components/Picker/UserPicker'; +import TeamPicker, { Team } from 'app/core/components/Picker/TeamPicker'; +import DescriptionPicker, { OptionWithDescription } from 'app/core/components/Picker/DescriptionPicker'; +import { permissionOptions } from 'app/stores/PermissionsStore/PermissionsStore'; + +export interface IProps { + permissions: any; + backendSrv: any; + dashboardId: any; +} + +@observer +class AddPermissions extends Component { + constructor(props) { + super(props); + this.userPicked = this.userPicked.bind(this); + this.teamPicked = this.teamPicked.bind(this); + this.permissionPicked = this.permissionPicked.bind(this); + this.typeChanged = this.typeChanged.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + } + + componentWillMount() { + const { permissions } = this.props; + permissions.resetNewType(); + } + + typeChanged(evt) { + const { value } = evt.target; + const { permissions } = this.props; + + // if (value === 'Viewer' || value === 'Editor') { + // // permissions.addStoreItem({ permission: 1, role: value, dashboardId: dashboardId }, dashboardId); + // // this.resetNewType(); + // return; + // } + + permissions.setNewType(value); + } + + userPicked(user: User) { + const { permissions } = this.props; + if (!user) { + permissions.newItem.setUser(null, null); + return; + } + permissions.newItem.setUser(user.id, user.login); + // return permissions.addStoreItem({ userId: user.id, userLogin: user.login, permission: 1 }); + } + + teamPicked(team: Team) { + const { permissions } = this.props; + if (!team) { + permissions.newItem.setTeam(null, null); + return; + } + permissions.newItem.setTeam(team.id, team.name); + } + + permissionPicked(permission: OptionWithDescription) { + const { permissions } = this.props; + permissions.newItem.setPermission(permission.value); + } + + resetNewType() { + const { permissions } = this.props; + permissions.resetNewType(); + } + + handleSubmit(evt) { + evt.preventDefault(); + const { permissions } = this.props; + permissions.addStoreItem(); + } + + render() { + const { permissions, backendSrv } = this.props; + const newItem = permissions.newItem; + + return ( +
+
+
Add Permission For
+
+
+
+ +
+
+ + {newItem.type === 'User' ? ( +
+ +
+ ) : null} + + {newItem.type === 'Group' ? ( +
+ +
+ ) : null} + +
+ +
+ +
+ +
+
+
+ {permissions.error ? ( +
+ + + {permissions.error} + +
+ ) : null} +
+ ); + } +} + +export default AddPermissions; diff --git a/public/app/core/components/Permissions/Permissions.tsx b/public/app/core/components/Permissions/Permissions.tsx index f5af579094b..1849d7da173 100644 --- a/public/app/core/components/Permissions/Permissions.tsx +++ b/public/app/core/components/Permissions/Permissions.tsx @@ -1,9 +1,6 @@ import React, { Component } from 'react'; import PermissionsList from './PermissionsList'; import { observer } from 'mobx-react'; -import UserPicker, { User } from 'app/core/components/Picker/UserPicker'; -import TeamPicker, { Team } from 'app/core/components/Picker/TeamPicker'; -import { aclTypes } from 'app/stores/PermissionsStore/PermissionsStore'; import { FolderInfo } from './FolderInfo'; export interface DashboardAcl { @@ -40,8 +37,6 @@ class Permissions extends Component { this.permissionChanged = this.permissionChanged.bind(this); this.typeChanged = this.typeChanged.bind(this); this.removeItem = this.removeItem.bind(this); - this.userPicked = this.userPicked.bind(this); - this.teamPicked = this.teamPicked.bind(this); this.loadStore(dashboardId, isFolder); } @@ -77,18 +72,8 @@ class Permissions extends Component { permissions.setNewType(value); } - userPicked(user: User) { - const { permissions } = this.props; - return permissions.addStoreItem({ userId: user.id, userLogin: user.login, permission: 1 }); - } - - teamPicked(team: Team) { - const { permissions } = this.props; - return permissions.addStoreItem({ teamId: team.id, team: team.name, permission: 1 }); - } - render() { - const { permissions, folderInfo, backendSrv } = this.props; + const { permissions, folderInfo } = this.props; return (
@@ -99,50 +84,6 @@ class Permissions extends Component { fetching={permissions.fetching} folderInfo={folderInfo} /> -
-
-
Add Permission For
-
-
-
- -
-
- - {permissions.newType === 'User' ? ( -
- -
- ) : null} - - {permissions.newType === 'Group' ? ( -
- -
- ) : null} -
-
- {permissions.error ? ( -
- - - {permissions.error} - -
- ) : null} -
); } diff --git a/public/app/core/components/Picker/TeamPicker.tsx b/public/app/core/components/Picker/TeamPicker.tsx index 4b5a049c0ff..18f7258c221 100644 --- a/public/app/core/components/Picker/TeamPicker.tsx +++ b/public/app/core/components/Picker/TeamPicker.tsx @@ -9,6 +9,7 @@ export interface IProps { isLoading: boolean; toggleLoading: any; handlePicked: (user) => void; + value?: string; } export interface Team { @@ -54,7 +55,7 @@ class TeamPicker extends Component { render() { const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async; - const { isLoading, handlePicked } = this.props; + const { isLoading, handlePicked, value } = this.props; return (
@@ -70,6 +71,7 @@ class TeamPicker extends Component { className="width-8 gf-form-input gf-form-input--form-dropdown" optionComponent={PickerOption} placeholder="Choose" + value={value} />
); diff --git a/public/app/core/components/Picker/UserPicker.tsx b/public/app/core/components/Picker/UserPicker.tsx index 141371813a2..99b0ef258ca 100644 --- a/public/app/core/components/Picker/UserPicker.tsx +++ b/public/app/core/components/Picker/UserPicker.tsx @@ -9,6 +9,7 @@ export interface IProps { isLoading: boolean; toggleLoading: any; handlePicked: (user) => void; + value?: string; } export interface User { @@ -53,8 +54,8 @@ class UserPicker extends Component { render() { const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async; - const { isLoading, handlePicked } = this.props; - + const { isLoading, handlePicked, value } = this.props; + console.log('value', value); return (
{ className="width-8 gf-form-input gf-form-input--form-dropdown" optionComponent={PickerOption} placeholder="Choose" + value={value} + autosize={true} />
); diff --git a/public/app/core/components/Picker/withPicker.tsx b/public/app/core/components/Picker/withPicker.tsx index bdfcb02676e..cf3954850b2 100644 --- a/public/app/core/components/Picker/withPicker.tsx +++ b/public/app/core/components/Picker/withPicker.tsx @@ -3,6 +3,7 @@ export interface IProps { backendSrv: any; handlePicked: (data) => void; + value?: string; } export default function withPicker(WrappedComponent) { diff --git a/public/app/stores/PermissionsStore/PermissionsStore.ts b/public/app/stores/PermissionsStore/PermissionsStore.ts index 52e5dcdb339..ae100fd0751 100644 --- a/public/app/stores/PermissionsStore/PermissionsStore.ts +++ b/public/app/stores/PermissionsStore/PermissionsStore.ts @@ -13,15 +13,62 @@ export const permissionOptions = [ }, ]; -export const aclTypes = [ - { value: 'Group', text: 'Team' }, - { value: 'User', text: 'User' }, - { value: 'Viewer', text: 'Everyone With Viewer Role' }, - { value: 'Editor', text: 'Everyone With Editor Role' }, -]; +export const aclTypeValues = { + GROUP: { value: 'Group', text: 'Team' }, + USER: { value: 'User', text: 'User' }, + VIEWER: { value: 'Viewer', text: 'Everyone With Viewer Role' }, + EDITOR: { value: 'Editor', text: 'Everyone With Editor Role' }, +}; + +export const aclTypes = Object.keys(aclTypeValues).map(item => aclTypeValues[item]); const defaultNewType = aclTypes[0].value; +const NewPermissionsItem = types + .model('NewPermissionsItem', { + type: types.optional( + types.enumeration(Object.keys(aclTypeValues).map(item => aclTypeValues[item].value)), + defaultNewType + ), + userId: types.maybe(types.number), + userLogin: types.maybe(types.string), + teamId: types.maybe(types.number), + team: types.maybe(types.string), + permission: types.optional(types.number, 1), + }) + .views(self => ({ + isValid: () => { + switch (self.type) { + case aclTypeValues.GROUP.value: + return self.teamId && self.team; + case aclTypeValues.USER.value: + return self.userId && self.userLogin; + case aclTypeValues.VIEWER.value: + case aclTypeValues.EDITOR.value: + return true; + default: + return false; + } + }, + })) + .actions(self => ({ + setUser(userId: number, userLogin: string) { + self.userId = userId; + self.userLogin = userLogin; + self.teamId = null; + self.team = null; + }, + setTeam(teamId: number, team: string) { + self.userId = null; + self.userLogin = null; + self.teamId = teamId; + self.team = team; + }, + setPermission(permission: number) { + self.permission = permission; + }, + })); + export const PermissionsStore = types .model('PermissionsStore', { fetching: types.boolean, @@ -31,6 +78,8 @@ export const PermissionsStore = types error: types.maybe(types.string), originalItems: types.optional(types.array(PermissionsStoreItem), []), newType: types.optional(types.string, defaultNewType), + newItem: types.maybe(NewPermissionsItem), + isAddPermissionsVisible: types.optional(types.boolean, false), }) .views(self => ({ isValid: item => { @@ -46,48 +95,91 @@ export const PermissionsStore = types return true; }, })) - .actions(self => ({ - load: flow(function* load(dashboardId: number, isFolder: boolean) { - const backendSrv = getEnv(self).backendSrv; - self.fetching = true; - self.isFolder = isFolder; - self.dashboardId = dashboardId; - const res = yield backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`); - const items = prepareServerResponse(res, dashboardId, isFolder); - self.items = items; - self.originalItems = items; - self.fetching = false; - }), - addStoreItem: flow(function* addStoreItem(item) { + .actions(self => { + const resetNewType = () => { self.error = null; - if (!self.isValid(item)) { - return undefined; - } + self.newItem = NewPermissionsItem.create(); + }; - self.items.push(prepareItem(item, self.dashboardId, self.isFolder)); - return updateItems(self); - }), - removeStoreItem: flow(function* removeStoreItem(idx: number) { - self.error = null; - self.items.splice(idx, 1); - return updateItems(self); - }), - updatePermissionOnIndex: flow(function* updatePermissionOnIndex( - idx: number, - permission: number, - permissionName: string - ) { - self.error = null; - self.items[idx].updatePermission(permission, permissionName); - return updateItems(self); - }), - setNewType(newType: string) { - self.newType = newType; - }, - resetNewType() { - self.newType = defaultNewType; - }, - })); + return { + load: flow(function* load(dashboardId: number, isFolder: boolean) { + const backendSrv = getEnv(self).backendSrv; + self.fetching = true; + self.isFolder = isFolder; + self.dashboardId = dashboardId; + const res = yield backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`); + const items = prepareServerResponse(res, dashboardId, isFolder); + self.items = items; + self.originalItems = items; + self.fetching = false; + }), + addStoreItem: flow(function* addStoreItem() { + self.error = null; + let item = { + type: self.newItem.type, + permission: self.newItem.permission, + team: undefined, + teamId: undefined, + userLogin: undefined, + userId: undefined, + role: undefined, + }; + switch (self.newItem.type) { + case aclTypeValues.GROUP.value: + item.team = self.newItem.team; + item.teamId = self.newItem.teamId; + break; + case aclTypeValues.USER.value: + item.userLogin = self.newItem.userLogin; + item.userId = self.newItem.userId; + break; + case aclTypeValues.VIEWER.value: + case aclTypeValues.EDITOR.value: + item.role = self.newItem.type; + break; + default: + throw Error('Unknown type: ' + self.newItem.type); + } + + if (!self.isValid(item)) { + throw Error('New item not valid'); + } + + self.items.push(prepareItem(item, self.dashboardId, self.isFolder)); + resetNewType(); + return updateItems(self); + }), + removeStoreItem: flow(function* removeStoreItem(idx: number) { + self.error = null; + self.items.splice(idx, 1); + return updateItems(self); + }), + updatePermissionOnIndex: flow(function* updatePermissionOnIndex( + idx: number, + permission: number, + permissionName: string + ) { + self.error = null; + self.items[idx].updatePermission(permission, permissionName); + return updateItems(self); + }), + setNewType(newType: string) { + self.newItem = NewPermissionsItem.create({ type: newType }); + }, + resetNewType() { + resetNewType(); + }, + toggleAddPermissions() { + self.isAddPermissionsVisible = !self.isAddPermissionsVisible; + }, + showAddPermissions() { + self.isAddPermissionsVisible = true; + }, + hideAddPermissions() { + self.isAddPermissionsVisible = false; + }, + }; + }); const updateItems = self => { self.error = null; diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index 2113bbae43c..dd6c7c39b83 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -392,3 +392,9 @@ select.gf-form-input ~ .gf-form-help-icon { top: 10px; color: $text-muted; } + +.cta-form { + padding: 1rem; + background-color: $dark-2; + margin-bottom: 1rem; +} From 2ad4c30bc652079b919bf227eae90bacb5810a12 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 31 Jan 2018 14:19:07 +0100 Subject: [PATCH 2/9] ux: POC - Update "Add permissions" design and add a fancy animation #10676 --- package.json | 1 + .../ManageDashboards/FolderPermissions.tsx | 12 ++++-- .../core/components/Animations/SlideDown.tsx | 37 +++++++++++++++++++ .../components/Permissions/AddPermissions.tsx | 8 ++-- .../app/core/components/Picker/TeamPicker.tsx | 4 +- .../app/core/components/Picker/UserPicker.tsx | 2 +- public/sass/components/_buttons.scss | 4 ++ public/sass/components/_gf-form.scss | 14 ++++++- yarn.lock | 25 +++++++++++++ 9 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 public/app/core/components/Animations/SlideDown.tsx diff --git a/package.json b/package.json index 80fa9a699f8..d7fb5d8e6f8 100644 --- a/package.json +++ b/package.json @@ -153,6 +153,7 @@ "react-popper": "^0.7.5", "react-select": "^1.1.0", "react-sizeme": "^2.3.6", + "react-transition-group": "^2.2.1", "remarkable": "^1.7.1", "rst2html": "github:thoward/rst2html#990cb89", "rxjs": "^5.4.3", diff --git a/public/app/containers/ManageDashboards/FolderPermissions.tsx b/public/app/containers/ManageDashboards/FolderPermissions.tsx index 98f63a46cbe..7c9e55bcac3 100644 --- a/public/app/containers/ManageDashboards/FolderPermissions.tsx +++ b/public/app/containers/ManageDashboards/FolderPermissions.tsx @@ -7,7 +7,7 @@ import Permissions from 'app/core/components/Permissions/Permissions'; import Tooltip from 'app/core/components/Tooltip/Tooltip'; import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo'; import AddPermissions from 'app/core/components/Permissions/AddPermissions'; - +import SlideDown from 'app/core/components/Animations/SlideDown'; @inject('nav', 'folder', 'view', 'permissions') @observer export class FolderPermissions extends Component { @@ -48,14 +48,18 @@ export class FolderPermissions extends Component {
-
- {permissions.isAddPermissionsVisible ? ( + - ) : null} +
diff --git a/public/app/core/components/Animations/SlideDown.tsx b/public/app/core/components/Animations/SlideDown.tsx new file mode 100644 index 00000000000..4d515f98f16 --- /dev/null +++ b/public/app/core/components/Animations/SlideDown.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import Transition from 'react-transition-group/Transition'; + +const defaultMaxHeight = '200px'; // When animating using max-height we need to use a static value. +// If this is not enough, pass in -
-
Add Permission For
+ + +
Add Permission For
diff --git a/public/app/core/components/Picker/TeamPicker.tsx b/public/app/core/components/Picker/TeamPicker.tsx index 18f7258c221..82809ee1cf6 100644 --- a/public/app/core/components/Picker/TeamPicker.tsx +++ b/public/app/core/components/Picker/TeamPicker.tsx @@ -67,11 +67,13 @@ class TeamPicker extends Component { isLoading={isLoading} loadOptions={this.debouncedSearch} loadingPlaceholder="Loading..." + noResultsText="No teams found" onChange={handlePicked} - className="width-8 gf-form-input gf-form-input--form-dropdown" + className="width-12 gf-form-input gf-form-input--form-dropdown" optionComponent={PickerOption} placeholder="Choose" value={value} + autosize={true} />
); diff --git a/public/app/core/components/Picker/UserPicker.tsx b/public/app/core/components/Picker/UserPicker.tsx index 99b0ef258ca..733a8015a6c 100644 --- a/public/app/core/components/Picker/UserPicker.tsx +++ b/public/app/core/components/Picker/UserPicker.tsx @@ -68,7 +68,7 @@ class UserPicker extends Component { loadingPlaceholder="Loading..." noResultsText="No users found" onChange={handlePicked} - className="width-8 gf-form-input gf-form-input--form-dropdown" + className="width-12 gf-form-input gf-form-input--form-dropdown" optionComponent={PickerOption} placeholder="Choose" value={value} diff --git a/public/sass/components/_buttons.scss b/public/sass/components/_buttons.scss index 4c9b197c3d0..c21ed30b0f4 100644 --- a/public/sass/components/_buttons.scss +++ b/public/sass/components/_buttons.scss @@ -113,6 +113,10 @@ //border: 1px solid $tight-form-func-highlight-bg; } +.btn-transparent { + background-color: transparent; +} + .btn-outline-primary { @include button-outline-variant($btn-primary-bg); } diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index dd6c7c39b83..a1e208ee1c2 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -274,6 +274,10 @@ $input-border: 1px solid $input-border-color; } } + .gf-form-input { + margin-right: 0; + } + select.gf-form-input { text-indent: 0.01px; text-overflow: ''; @@ -394,7 +398,15 @@ select.gf-form-input ~ .gf-form-help-icon { } .cta-form { + position: relative; padding: 1rem; - background-color: $dark-2; + background-color: $dark-4; margin-bottom: 1rem; + border-top: 3px solid $green; +} + +.cta-form__close { + position: absolute; + right: 0; + top: 0; } diff --git a/yarn.lock b/yarn.lock index 5bb00023d7c..e95968736ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1604,6 +1604,10 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" +chain-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc" + chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.0, chalk@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -2801,6 +2805,10 @@ dom-converter@~0.1: dependencies: utila "~0.3" +dom-helpers@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" + dom-serialize@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" @@ -8318,6 +8326,17 @@ react-test-renderer@^16.0.0, react-test-renderer@^16.0.0-0: object-assign "^4.1.1" prop-types "^15.6.0" +react-transition-group@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.2.1.tgz#e9fb677b79e6455fd391b03823afe84849df4a10" + dependencies: + chain-function "^1.0.0" + classnames "^2.2.5" + dom-helpers "^3.2.0" + loose-envify "^1.3.1" + prop-types "^15.5.8" + warning "^3.0.0" + react@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/react/-/react-16.2.0.tgz#a31bd2dab89bff65d42134fa187f24d054c273ba" @@ -10355,6 +10374,12 @@ walker@~1.0.5: dependencies: makeerror "1.0.x" +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + dependencies: + loose-envify "^1.0.0" + watch@~0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" From 1b9e02e4cc794c916a178fe19eccf1af55bd933f Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 31 Jan 2018 16:12:51 +0100 Subject: [PATCH 3/9] tests: Update tests in PermissionsStore and rem out the Permissions-tests for now #10676 --- .../Permissions/Permissions.jest.tsx | 128 +++++++++--------- .../PermissionsStore/PermissionsStore.jest.ts | 122 +++++++---------- .../PermissionsStore/PermissionsStore.ts | 2 +- 3 files changed, 116 insertions(+), 136 deletions(-) diff --git a/public/app/core/components/Permissions/Permissions.jest.tsx b/public/app/core/components/Permissions/Permissions.jest.tsx index 0a608ee5842..893116ed725 100644 --- a/public/app/core/components/Permissions/Permissions.jest.tsx +++ b/public/app/core/components/Permissions/Permissions.jest.tsx @@ -1,73 +1,73 @@ -import React from 'react'; -import Permissions from './Permissions'; -import { RootStore } from 'app/stores/RootStore/RootStore'; -import { backendSrv } from 'test/mocks/common'; -import { shallow } from 'enzyme'; +// import React from 'react'; +// import Permissions from './Permissions'; +// import { RootStore } from 'app/stores/RootStore/RootStore'; +// import { backendSrv } from 'test/mocks/common'; +// import { shallow } from 'enzyme'; -describe('Permissions', () => { - let wrapper; +// describe('Permissions', () => { +// let wrapper; - beforeAll(() => { - backendSrv.get.mockReturnValue( - Promise.resolve([ - { id: 2, dashboardId: 1, role: 'Viewer', permission: 1, permissionName: 'View' }, - { id: 3, dashboardId: 1, role: 'Editor', permission: 1, permissionName: 'Edit' }, - { - id: 4, - dashboardId: 1, - userId: 2, - userLogin: 'danlimerick', - userEmail: 'dan.limerick@gmail.com', - permission: 4, - permissionName: 'Admin', - }, - ]) - ); +// beforeAll(() => { +// backendSrv.get.mockReturnValue( +// Promise.resolve([ +// { id: 2, dashboardId: 1, role: 'Viewer', permission: 1, permissionName: 'View' }, +// { id: 3, dashboardId: 1, role: 'Editor', permission: 1, permissionName: 'Edit' }, +// { +// id: 4, +// dashboardId: 1, +// userId: 2, +// userLogin: 'danlimerick', +// userEmail: 'dan.limerick@gmail.com', +// permission: 4, +// permissionName: 'Admin', +// }, +// ]) +// ); - backendSrv.post = jest.fn(); +// backendSrv.post = jest.fn(); - const store = RootStore.create( - {}, - { - backendSrv: backendSrv, - } - ); +// const store = RootStore.create( +// {}, +// { +// backendSrv: backendSrv, +// } +// ); - wrapper = shallow(); - return wrapper.instance().loadStore(1, true); - }); +// wrapper = shallow(); +// return wrapper.instance().loadStore(1, true); +// }); - describe('when permission for a user is added', () => { - it('should save permission to db', () => { - const userItem = { - id: 2, - login: 'user2', - }; +// describe('when permission for a user is added', () => { +// it('should save permission to db', () => { +// const userItem = { +// id: 2, +// login: 'user2', +// }; - wrapper - .instance() - .userPicked(userItem) - .then(() => { - expect(backendSrv.post.mock.calls.length).toBe(1); - expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); - }); - }); - }); +// wrapper +// .instance() +// .userPicked(userItem) +// .then(() => { +// expect(backendSrv.post.mock.calls.length).toBe(1); +// expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); +// }); +// }); +// }); - describe('when permission for team is added', () => { - it('should save permission to db', () => { - const teamItem = { - id: 2, - name: 'ug1', - }; +// describe('when permission for team is added', () => { +// it('should save permission to db', () => { +// const teamItem = { +// id: 2, +// name: 'ug1', +// }; - wrapper - .instance() - .teamPicked(teamItem) - .then(() => { - expect(backendSrv.post.mock.calls.length).toBe(1); - expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); - }); - }); - }); -}); +// wrapper +// .instance() +// .teamPicked(teamItem) +// .then(() => { +// expect(backendSrv.post.mock.calls.length).toBe(1); +// expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); +// }); +// }); +// }); +// }); diff --git a/public/app/stores/PermissionsStore/PermissionsStore.jest.ts b/public/app/stores/PermissionsStore/PermissionsStore.jest.ts index 34206ba41c9..5b59ada21d6 100644 --- a/public/app/stores/PermissionsStore/PermissionsStore.jest.ts +++ b/public/app/stores/PermissionsStore/PermissionsStore.jest.ts @@ -1,4 +1,4 @@ -import { PermissionsStore } from './PermissionsStore'; +import { PermissionsStore, aclTypeValues } from './PermissionsStore'; import { backendSrv } from 'test/mocks/common'; describe('PermissionsStore', () => { @@ -47,21 +47,6 @@ describe('PermissionsStore', () => { expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); }); - it('should save newly added permissions automatically', () => { - expect(store.items.length).toBe(3); - - const newItem = { - userId: 10, - userLogin: 'tester1', - permission: 1, - }; - store.addStoreItem(newItem); - - expect(store.items.length).toBe(4); - expect(backendSrv.post.mock.calls.length).toBe(1); - expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); - }); - it('should save removed permissions automatically', () => { expect(store.items.length).toBe(3); @@ -72,6 +57,30 @@ describe('PermissionsStore', () => { expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); }); + describe('when duplicate team permissions are added', () => { + beforeEach(() => { + const newItem = { + teamId: 10, + team: 'tester-team', + permission: 1, + }; + store.resetNewType(); + store.newItem.setTeam(newItem.teamId, newItem.team); + store.newItem.setPermission(newItem.permission); + store.addStoreItem(); + + store.newItem.setTeam(newItem.teamId, newItem.team); + store.newItem.setPermission(newItem.permission); + store.addStoreItem(); + }); + + it('should return a validation error', () => { + expect(store.items.length).toBe(4); + expect(store.error).toBe('This permission exists already.'); + expect(backendSrv.post.mock.calls.length).toBe(1); + }); + }); + describe('when duplicate user permissions are added', () => { beforeEach(() => { const newItem = { @@ -79,8 +88,14 @@ describe('PermissionsStore', () => { userLogin: 'tester1', permission: 1, }; - store.addStoreItem(newItem); - store.addStoreItem(newItem); + store.setNewType(aclTypeValues.USER.value); + store.newItem.setUser(newItem.userId, newItem.userLogin); + store.newItem.setPermission(newItem.permission); + store.addStoreItem(); + store.setNewType(aclTypeValues.USER.value); + store.newItem.setUser(newItem.userId, newItem.userLogin); + store.newItem.setPermission(newItem.permission); + store.addStoreItem(); }); it('should return a validation error', () => { @@ -90,59 +105,24 @@ describe('PermissionsStore', () => { }); }); - describe('when duplicate team permissions are added', () => { - beforeEach(() => { - const newItem = { - teamId: 1, - teamName: 'testerteam', - permission: 1, - }; - store.addStoreItem(newItem); - store.addStoreItem(newItem); - }); + // TODO: I dont get this one + // describe('when one inherited and one not inherited team permission are added', () => { + // beforeEach(() => { + // const teamItem = { + // team: 'MyTestTeam', + // dashboardId: 1, + // teamId: 1, + // permission: 2, + // }; + // store.addStoreItem(teamItem); + // }); - it('should return a validation error', () => { - expect(store.items.length).toBe(4); - expect(store.error).toBe('This permission exists already.'); - expect(backendSrv.post.mock.calls.length).toBe(1); - }); - }); + // it('should not throw a validation error', () => { + // expect(store.error).toBe(null); + // }); - describe('when duplicate role permissions are added', () => { - beforeEach(() => { - const newItem = { - team: 'MyTestTeam', - teamId: 1, - permission: 1, - }; - store.addStoreItem(newItem); - store.addStoreItem(newItem); - }); - - it('should return a validation error', () => { - expect(store.items.length).toBe(4); - expect(store.error).toBe('This permission exists already.'); - expect(backendSrv.post.mock.calls.length).toBe(1); - }); - }); - - describe('when one inherited and one not inherited team permission are added', () => { - beforeEach(() => { - const teamItem = { - team: 'MyTestTeam', - dashboardId: 1, - teamId: 1, - permission: 2, - }; - store.addStoreItem(teamItem); - }); - - it('should not throw a validation error', () => { - expect(store.error).toBe(null); - }); - - it('should add both permissions', () => { - expect(store.items.length).toBe(4); - }); - }); + // it('should add both permissions', () => { + // expect(store.items.length).toBe(4); + // }); + // }); }); diff --git a/public/app/stores/PermissionsStore/PermissionsStore.ts b/public/app/stores/PermissionsStore/PermissionsStore.ts index ae100fd0751..fe997980ea7 100644 --- a/public/app/stores/PermissionsStore/PermissionsStore.ts +++ b/public/app/stores/PermissionsStore/PermissionsStore.ts @@ -24,7 +24,7 @@ export const aclTypes = Object.keys(aclTypeValues).map(item => aclTypeValues[ite const defaultNewType = aclTypes[0].value; -const NewPermissionsItem = types +export const NewPermissionsItem = types .model('NewPermissionsItem', { type: types.optional( types.enumeration(Object.keys(aclTypeValues).map(item => aclTypeValues[item].value)), From 20052150bac78585b2c6c3284f24eaa802dd5b3c Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 31 Jan 2018 16:15:05 +0100 Subject: [PATCH 4/9] tests: Move tests from Permissions to AddPermissions #10676 --- .../Permissions/AddPermissions.jest.tsx | 79 +++++++++++++++++++ .../components/Permissions/AddPermissions.tsx | 2 +- .../app/core/components/Picker/UserPicker.tsx | 1 - 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 public/app/core/components/Permissions/AddPermissions.jest.tsx diff --git a/public/app/core/components/Permissions/AddPermissions.jest.tsx b/public/app/core/components/Permissions/AddPermissions.jest.tsx new file mode 100644 index 00000000000..a3164ec90af --- /dev/null +++ b/public/app/core/components/Permissions/AddPermissions.jest.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import AddPermissions from './AddPermissions'; +import { RootStore } from 'app/stores/RootStore/RootStore'; +import { backendSrv } from 'test/mocks/common'; +import { shallow } from 'enzyme'; + +describe('AddPermissions', () => { + let wrapper; + + beforeAll(() => { + backendSrv.get.mockReturnValue( + Promise.resolve([ + { id: 2, dashboardId: 1, role: 'Viewer', permission: 1, permissionName: 'View' }, + { id: 3, dashboardId: 1, role: 'Editor', permission: 1, permissionName: 'Edit' }, + { + id: 4, + dashboardId: 1, + userId: 2, + userLogin: 'danlimerick', + userEmail: 'dan.limerick@gmail.com', + permission: 4, + permissionName: 'Admin', + }, + ]) + ); + + backendSrv.post = jest.fn(); + + const store = RootStore.create( + {}, + { + backendSrv: backendSrv, + } + ); + + // wrapper = shallow(); + wrapper = shallow(); + // + // return wrapper.instance().loadStore(1, true); + }); + + describe('when permission for a user is added', () => { + it('should save permission to db', async () => { + const evt = { + target: { + value: 'User', + }, + }; + const userItem = { + id: 2, + login: 'user2', + }; + + const instance = wrapper.instance(); + instance.typeChanged(evt); + instance.userPicked(userItem); + wrapper.find('[data-save-permission]').simulate('click'); + expect(backendSrv.post.mock.calls.length).toBe(1); + expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); + }); + }); + + // describe('when permission for team is added', () => { + // it('should save permission to db', () => { + // const teamItem = { + // id: 2, + // name: 'ug1', + // }; + + // wrapper + // .instance() + // .teamPicked(teamItem) + // .then(() => { + // expect(backendSrv.post.mock.calls.length).toBe(1); + // expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); + // }); + // }); + // }); +}); diff --git a/public/app/core/components/Permissions/AddPermissions.tsx b/public/app/core/components/Permissions/AddPermissions.tsx index 989da32e187..fa2e69f17b3 100644 --- a/public/app/core/components/Permissions/AddPermissions.tsx +++ b/public/app/core/components/Permissions/AddPermissions.tsx @@ -124,7 +124,7 @@ class AddPermissions extends Component {
-
diff --git a/public/app/core/components/Picker/UserPicker.tsx b/public/app/core/components/Picker/UserPicker.tsx index 733a8015a6c..129c012692a 100644 --- a/public/app/core/components/Picker/UserPicker.tsx +++ b/public/app/core/components/Picker/UserPicker.tsx @@ -55,7 +55,6 @@ class UserPicker extends Component { render() { const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async; const { isLoading, handlePicked, value } = this.props; - console.log('value', value); return (
Date: Wed, 31 Jan 2018 16:44:14 +0100 Subject: [PATCH 5/9] ux: Add an optional className to the UserPicker and TeamPicker #10676 --- .../core/components/Permissions/AddPermissions.tsx | 14 ++++++++++++-- public/app/core/components/Picker/TeamPicker.tsx | 5 +++-- public/app/core/components/Picker/UserPicker.tsx | 5 +++-- public/app/core/components/Picker/withPicker.tsx | 1 + 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/public/app/core/components/Permissions/AddPermissions.tsx b/public/app/core/components/Permissions/AddPermissions.tsx index fa2e69f17b3..5a5c9b83137 100644 --- a/public/app/core/components/Permissions/AddPermissions.tsx +++ b/public/app/core/components/Permissions/AddPermissions.tsx @@ -103,13 +103,23 @@ class AddPermissions extends Component { {newItem.type === 'User' ? (
- +
) : null} {newItem.type === 'Group' ? (
- +
) : null} diff --git a/public/app/core/components/Picker/TeamPicker.tsx b/public/app/core/components/Picker/TeamPicker.tsx index 82809ee1cf6..2dfff1850dd 100644 --- a/public/app/core/components/Picker/TeamPicker.tsx +++ b/public/app/core/components/Picker/TeamPicker.tsx @@ -10,6 +10,7 @@ export interface IProps { toggleLoading: any; handlePicked: (user) => void; value?: string; + className?: string; } export interface Team { @@ -55,7 +56,7 @@ class TeamPicker extends Component { render() { const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async; - const { isLoading, handlePicked, value } = this.props; + const { isLoading, handlePicked, value, className } = this.props; return (
@@ -69,7 +70,7 @@ class TeamPicker extends Component { loadingPlaceholder="Loading..." noResultsText="No teams found" onChange={handlePicked} - className="width-12 gf-form-input gf-form-input--form-dropdown" + className={`gf-form-input gf-form-input--form-dropdown ${className || ''}`} optionComponent={PickerOption} placeholder="Choose" value={value} diff --git a/public/app/core/components/Picker/UserPicker.tsx b/public/app/core/components/Picker/UserPicker.tsx index 129c012692a..5c36505aeaa 100644 --- a/public/app/core/components/Picker/UserPicker.tsx +++ b/public/app/core/components/Picker/UserPicker.tsx @@ -10,6 +10,7 @@ export interface IProps { toggleLoading: any; handlePicked: (user) => void; value?: string; + className?: string; } export interface User { @@ -54,7 +55,7 @@ class UserPicker extends Component { render() { const AsyncComponent = this.state.creatable ? Select.AsyncCreatable : Select.Async; - const { isLoading, handlePicked, value } = this.props; + const { isLoading, handlePicked, value, className } = this.props; return (
{ loadingPlaceholder="Loading..." noResultsText="No users found" onChange={handlePicked} - className="width-12 gf-form-input gf-form-input--form-dropdown" + className={`gf-form-input gf-form-input--form-dropdown ${className || ''}`} optionComponent={PickerOption} placeholder="Choose" value={value} diff --git a/public/app/core/components/Picker/withPicker.tsx b/public/app/core/components/Picker/withPicker.tsx index cf3954850b2..838ef927c30 100644 --- a/public/app/core/components/Picker/withPicker.tsx +++ b/public/app/core/components/Picker/withPicker.tsx @@ -4,6 +4,7 @@ export interface IProps { backendSrv: any; handlePicked: (data) => void; value?: string; + className?: string; } export default function withPicker(WrappedComponent) { From 780c7f8775b0eafb924740367b31acb61f5e227c Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 31 Jan 2018 16:48:45 +0100 Subject: [PATCH 6/9] tests: Add TeamPicker test and update TeamPicker/UserPicker snapshots so they match the latest classNames update #10676 --- .../components/Picker/TeamPicker.jest.tsx | 19 ++++ .../__snapshots__/TeamPicker.jest.tsx.snap | 98 +++++++++++++++++++ .../__snapshots__/UserPicker.jest.tsx.snap | 2 +- 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 public/app/core/components/Picker/TeamPicker.jest.tsx create mode 100644 public/app/core/components/Picker/__snapshots__/TeamPicker.jest.tsx.snap diff --git a/public/app/core/components/Picker/TeamPicker.jest.tsx b/public/app/core/components/Picker/TeamPicker.jest.tsx new file mode 100644 index 00000000000..20b7620e0ac --- /dev/null +++ b/public/app/core/components/Picker/TeamPicker.jest.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import TeamPicker from './TeamPicker'; + +const model = { + backendSrv: { + get: () => { + return new Promise((resolve, reject) => {}); + }, + }, + handlePicked: () => {}, +}; + +describe('TeamPicker', () => { + it('renders correctly', () => { + const tree = renderer.create().toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/public/app/core/components/Picker/__snapshots__/TeamPicker.jest.tsx.snap b/public/app/core/components/Picker/__snapshots__/TeamPicker.jest.tsx.snap new file mode 100644 index 00000000000..67232d0ea5b --- /dev/null +++ b/public/app/core/components/Picker/__snapshots__/TeamPicker.jest.tsx.snap @@ -0,0 +1,98 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`TeamPicker renders correctly 1`] = ` +
+
+
+ +
+ Loading... +
+
+ +
+ +
+
+
+
+
+
+`; diff --git a/public/app/core/components/Picker/__snapshots__/UserPicker.jest.tsx.snap b/public/app/core/components/Picker/__snapshots__/UserPicker.jest.tsx.snap index a1563ba8bc3..3262dc10efe 100644 --- a/public/app/core/components/Picker/__snapshots__/UserPicker.jest.tsx.snap +++ b/public/app/core/components/Picker/__snapshots__/UserPicker.jest.tsx.snap @@ -5,7 +5,7 @@ exports[`UserPicker renders correctly 1`] = ` className="user-picker" >
Date: Wed, 31 Jan 2018 17:01:04 +0100 Subject: [PATCH 7/9] ux: Change input width of UserPicker and TeamPicker in AddPermissions component #10676 --- public/app/core/components/Permissions/AddPermissions.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/app/core/components/Permissions/AddPermissions.tsx b/public/app/core/components/Permissions/AddPermissions.tsx index 5a5c9b83137..92656190bf2 100644 --- a/public/app/core/components/Permissions/AddPermissions.tsx +++ b/public/app/core/components/Permissions/AddPermissions.tsx @@ -78,6 +78,7 @@ class AddPermissions extends Component { render() { const { permissions, backendSrv } = this.props; const newItem = permissions.newItem; + const pickerClassName = 'width-20'; return (
@@ -107,7 +108,7 @@ class AddPermissions extends Component { backendSrv={backendSrv} handlePicked={this.userPicked} value={newItem.userId} - className="width-8" + className={pickerClassName} />
) : null} @@ -118,7 +119,7 @@ class AddPermissions extends Component { backendSrv={backendSrv} handlePicked={this.teamPicked} value={newItem.teamId} - className="width-8" + className={pickerClassName} />
) : null} From cc55ab6bc82b03a527444d53e3d64354111b2676 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 1 Feb 2018 14:32:19 +0100 Subject: [PATCH 8/9] dashfolders: adds permission modal to dashboard settings --- .../ManageDashboards/FolderPermissions.tsx | 3 +- .../Permissions/DashboardPermissions.tsx | 31 ++++++-- .../Permissions/Permissions.jest.tsx | 73 ------------------- public/sass/components/_gf-form.scss | 2 +- 4 files changed, 28 insertions(+), 81 deletions(-) delete mode 100644 public/app/core/components/Permissions/Permissions.jest.tsx diff --git a/public/app/containers/ManageDashboards/FolderPermissions.tsx b/public/app/containers/ManageDashboards/FolderPermissions.tsx index 7c9e55bcac3..637f811969e 100644 --- a/public/app/containers/ManageDashboards/FolderPermissions.tsx +++ b/public/app/containers/ManageDashboards/FolderPermissions.tsx @@ -53,8 +53,7 @@ export class FolderPermissions extends Component { onClick={this.handleAddPermission} disabled={permissions.isAddPermissionsVisible} > - - Add Permission + Add Permission
diff --git a/public/app/core/components/Permissions/DashboardPermissions.tsx b/public/app/core/components/Permissions/DashboardPermissions.tsx index 2636b0d4db4..a1b86e121bf 100644 --- a/public/app/core/components/Permissions/DashboardPermissions.tsx +++ b/public/app/core/components/Permissions/DashboardPermissions.tsx @@ -1,8 +1,11 @@ import React, { Component } from 'react'; +import { observer } from 'mobx-react'; import { store } from 'app/stores/store'; import Permissions from 'app/core/components/Permissions/Permissions'; import Tooltip from 'app/core/components/Tooltip/Tooltip'; import PermissionsInfo from 'app/core/components/Permissions/PermissionsInfo'; +import AddPermissions from 'app/core/components/Permissions/AddPermissions'; +import SlideDown from 'app/core/components/Animations/SlideDown'; export interface IProps { dashboardId: number; @@ -11,26 +14,44 @@ export interface IProps { folderSlug: string; backendSrv: any; } - +@observer class DashboardPermissions extends Component { permissions: any; constructor(props) { super(props); + this.handleAddPermission = this.handleAddPermission.bind(this); this.permissions = store.permissions; } + handleAddPermission() { + this.permissions.toggleAddPermissions(); + } + render() { const { dashboardId, folderTitle, folderSlug, folderId, backendSrv } = this.props; return (
-

Permissions

- - - +
+

Permissions

+ + + +
+ +
+ + + { -// let wrapper; - -// beforeAll(() => { -// backendSrv.get.mockReturnValue( -// Promise.resolve([ -// { id: 2, dashboardId: 1, role: 'Viewer', permission: 1, permissionName: 'View' }, -// { id: 3, dashboardId: 1, role: 'Editor', permission: 1, permissionName: 'Edit' }, -// { -// id: 4, -// dashboardId: 1, -// userId: 2, -// userLogin: 'danlimerick', -// userEmail: 'dan.limerick@gmail.com', -// permission: 4, -// permissionName: 'Admin', -// }, -// ]) -// ); - -// backendSrv.post = jest.fn(); - -// const store = RootStore.create( -// {}, -// { -// backendSrv: backendSrv, -// } -// ); - -// wrapper = shallow(); -// return wrapper.instance().loadStore(1, true); -// }); - -// describe('when permission for a user is added', () => { -// it('should save permission to db', () => { -// const userItem = { -// id: 2, -// login: 'user2', -// }; - -// wrapper -// .instance() -// .userPicked(userItem) -// .then(() => { -// expect(backendSrv.post.mock.calls.length).toBe(1); -// expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); -// }); -// }); -// }); - -// describe('when permission for team is added', () => { -// it('should save permission to db', () => { -// const teamItem = { -// id: 2, -// name: 'ug1', -// }; - -// wrapper -// .instance() -// .teamPicked(teamItem) -// .then(() => { -// expect(backendSrv.post.mock.calls.length).toBe(1); -// expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); -// }); -// }); -// }); -// }); diff --git a/public/sass/components/_gf-form.scss b/public/sass/components/_gf-form.scss index a1e208ee1c2..6603cfa072b 100644 --- a/public/sass/components/_gf-form.scss +++ b/public/sass/components/_gf-form.scss @@ -400,7 +400,7 @@ select.gf-form-input ~ .gf-form-help-icon { .cta-form { position: relative; padding: 1rem; - background-color: $dark-4; + background-color: $empty-list-cta-bg; margin-bottom: 1rem; border-top: 3px solid $green; } From a77c6560331451a6e2a66ae902c55e00165d925c Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Thu, 1 Feb 2018 14:48:11 +0100 Subject: [PATCH 9/9] dashfolders: adds test for permission store --- .../PermissionsStore/PermissionsStore.jest.ts | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/public/app/stores/PermissionsStore/PermissionsStore.jest.ts b/public/app/stores/PermissionsStore/PermissionsStore.jest.ts index dcbb1e2a8b5..97a9906d0e5 100644 --- a/public/app/stores/PermissionsStore/PermissionsStore.jest.ts +++ b/public/app/stores/PermissionsStore/PermissionsStore.jest.ts @@ -57,30 +57,30 @@ describe('PermissionsStore', () => { expect(backendSrv.post.mock.calls[0][0]).toBe('/api/dashboards/id/1/acl'); }); - // describe('when duplicate team permissions are added', () => { - // beforeEach(() => { - // const newItem = { - // teamId: 10, - // team: 'tester-team', - // permission: 1, - // dashboardId: 1, - // }; - // store.resetNewType(); - // store.newItem.setTeam(newItem.teamId, newItem.team); - // store.newItem.setPermission(newItem.permission); - // store.addStoreItem(); + describe('when duplicate team permissions are added', () => { + beforeEach(() => { + const newItem = { + teamId: 10, + team: 'tester-team', + permission: 1, + dashboardId: 1, + }; + store.resetNewType(); + store.newItem.setTeam(newItem.teamId, newItem.team); + store.newItem.setPermission(newItem.permission); + store.addStoreItem(); - // store.newItem.setTeam(newItem.teamId, newItem.team); - // store.newItem.setPermission(newItem.permission); - // store.addStoreItem(); - // }); + store.newItem.setTeam(newItem.teamId, newItem.team); + store.newItem.setPermission(newItem.permission); + store.addStoreItem(); + }); - // it('should return a validation error', () => { - // expect(store.items.length).toBe(4); - // expect(store.error).toBe('This permission exists already.'); - // expect(backendSrv.post.mock.calls.length).toBe(1); - // }); - // }); + it('should return a validation error', () => { + expect(store.items.length).toBe(4); + expect(store.error).toBe('This permission exists already.'); + expect(backendSrv.post.mock.calls.length).toBe(1); + }); + }); describe('when duplicate user permissions are added', () => { beforeEach(() => {