소스 검색

Merge pull request #15391 from grafana/fixed-double-datasource-edit-page

Fixed issues with double page body and husky pre-commit hook
Torkel Ödegaard 6 년 전
부모
커밋
ef7236439a

+ 1 - 2
package.json

@@ -65,7 +65,7 @@
     "html-loader": "^0.5.1",
     "html-webpack-harddisk-plugin": "^0.2.0",
     "html-webpack-plugin": "^3.2.0",
-    "husky": "^0.14.3",
+    "husky": "^1.3.1",
     "jest": "^23.6.0",
     "jest-date-mock": "^1.0.6",
     "lint-staged": "^8.1.3",
@@ -120,7 +120,6 @@
     "typecheck": "tsc --noEmit",
     "jest": "jest --notify --watch",
     "api-tests": "jest --notify --watch --config=tests/api/jest.js",
-    "precommit": "grunt precommit",
     "storybook": "cd packages/grafana-ui && yarn storybook"
   },
   "husky": {

+ 27 - 29
public/app/features/datasources/NewDataSourcePage.tsx

@@ -35,34 +35,32 @@ class NewDataSourcePage extends PureComponent<Props> {
     return (
       <Page navModel={navModel}>
         <Page.Contents isLoading={isLoading}>
-          <div className="page-container page-body">
-            <h2 className="add-data-source-header">Choose data source type</h2>
-            <div className="add-data-source-search">
-              <label className="gf-form--has-input-icon">
-                <input
-                  type="text"
-                  className="gf-form-input width-20"
-                  value={dataSourceTypeSearchQuery}
-                  onChange={this.onSearchQueryChange}
-                  placeholder="Filter by name or type"
-                />
-                <i className="gf-form-input-icon fa fa-search" />
-              </label>
-            </div>
-            <div className="add-data-source-grid">
-              {dataSourceTypes.map((plugin, index) => {
-                return (
-                  <div
-                    onClick={() => this.onDataSourceTypeClicked(plugin)}
-                    className="add-data-source-grid-item"
-                    key={`${plugin.id}-${index}`}
-                  >
-                    <img className="add-data-source-grid-item-logo" src={plugin.info.logos.small} />
-                    <span className="add-data-source-grid-item-text">{plugin.name}</span>
-                  </div>
-                );
-              })}
-            </div>
+          <h2 className="add-data-source-header">Choose data source type</h2>
+          <div className="add-data-source-search">
+            <label className="gf-form--has-input-icon">
+              <input
+                type="text"
+                className="gf-form-input width-20"
+                value={dataSourceTypeSearchQuery}
+                onChange={this.onSearchQueryChange}
+                placeholder="Filter by name or type"
+              />
+              <i className="gf-form-input-icon fa fa-search" />
+            </label>
+          </div>
+          <div className="add-data-source-grid">
+            {dataSourceTypes.map((plugin, index) => {
+              return (
+                <div
+                  onClick={() => this.onDataSourceTypeClicked(plugin)}
+                  className="add-data-source-grid-item"
+                  key={`${plugin.id}-${index}`}
+                >
+                  <img className="add-data-source-grid-item-logo" src={plugin.info.logos.small} />
+                  <span className="add-data-source-grid-item-text">{plugin.name}</span>
+                </div>
+              );
+            })}
           </div>
         </Page.Contents>
       </Page>
@@ -74,7 +72,7 @@ function mapStateToProps(state: StoreState) {
   return {
     navModel: getNavModel(state.navIndex, 'datasources'),
     dataSourceTypes: getDataSourceTypes(state.dataSources),
-    isLoading: state.dataSources.isLoadingDataSources
+    isLoading: state.dataSources.isLoadingDataSources,
   };
 }
 

+ 5 - 3
public/app/features/datasources/settings/ButtonRow.tsx

@@ -10,9 +10,11 @@ export interface Props {
 const ButtonRow: FC<Props> = ({ isReadOnly, onDelete, onSubmit, onTest }) => {
   return (
     <div className="gf-form-button-row">
-      <button type="submit" className="btn btn-primary" disabled={isReadOnly} onClick={event => onSubmit(event)}>
-        Save &amp; Test
-      </button>
+      {!isReadOnly && (
+        <button type="submit" className="btn btn-primary" disabled={isReadOnly} onClick={event => onSubmit(event)}>
+          Save &amp; Test
+        </button>
+      )}
       {isReadOnly && (
         <button type="submit" className="btn btn-success" onClick={onTest}>
           Test

+ 42 - 44
public/app/features/datasources/settings/DataSourceSettingsPage.tsx

@@ -187,52 +187,50 @@ export class DataSourceSettingsPage extends PureComponent<Props, State> {
       <Page navModel={navModel}>
         <Page.Contents isLoading={!this.hasDataSource}>
           {this.hasDataSource && (
-            <div className="page-container page-body">
-              <div>
-                <form onSubmit={this.onSubmit}>
-                  {this.isReadOnly() && this.renderIsReadOnlyMessage()}
-                  {this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
-
-                  <BasicSettings
-                    dataSourceName={dataSource.name}
-                    isDefault={dataSource.isDefault}
-                    onDefaultChange={state => setIsDefault(state)}
-                    onNameChange={name => setDataSourceName(name)}
+            <div>
+              <form onSubmit={this.onSubmit}>
+                {this.isReadOnly() && this.renderIsReadOnlyMessage()}
+                {this.shouldRenderInfoBox() && <div className="grafana-info-box">{this.getInfoText()}</div>}
+
+                <BasicSettings
+                  dataSourceName={dataSource.name}
+                  isDefault={dataSource.isDefault}
+                  onDefaultChange={state => setIsDefault(state)}
+                  onNameChange={name => setDataSourceName(name)}
+                />
+
+                {dataSourceMeta.module && (
+                  <PluginSettings
+                    dataSource={dataSource}
+                    dataSourceMeta={dataSourceMeta}
+                    onModelChange={this.onModelChange}
                   />
-
-                  {dataSourceMeta.module && (
-                    <PluginSettings
-                      dataSource={dataSource}
-                      dataSourceMeta={dataSourceMeta}
-                      onModelChange={this.onModelChange}
-                    />
-                  )}
-
-                  <div className="gf-form-group section">
-                    {testingMessage && (
-                      <div className={`alert-${testingStatus} alert`}>
-                        <div className="alert-icon">
-                          {testingStatus === 'error' ? (
-                            <i className="fa fa-exclamation-triangle" />
-                          ) : (
-                            <i className="fa fa-check" />
-                          )}
-                        </div>
-                        <div className="alert-body">
-                          <div className="alert-title">{testingMessage}</div>
-                        </div>
+                )}
+
+                <div className="gf-form-group">
+                  {testingMessage && (
+                    <div className={`alert-${testingStatus} alert`}>
+                      <div className="alert-icon">
+                        {testingStatus === 'error' ? (
+                          <i className="fa fa-exclamation-triangle" />
+                        ) : (
+                          <i className="fa fa-check" />
+                        )}
                       </div>
-                    )}
-                  </div>
-
-                  <ButtonRow
-                    onSubmit={event => this.onSubmit(event)}
-                    isReadOnly={this.isReadOnly()}
-                    onDelete={this.onDelete}
-                    onTest={event => this.onTest(event)}
-                  />
-                </form>
-              </div>
+                      <div className="alert-body">
+                        <div className="alert-title">{testingMessage}</div>
+                      </div>
+                    </div>
+                  )}
+                </div>
+
+                <ButtonRow
+                  onSubmit={event => this.onSubmit(event)}
+                  isReadOnly={this.isReadOnly()}
+                  onDelete={this.onDelete}
+                  onTest={event => this.onTest(event)}
+                />
+              </form>
             </div>
           )}
         </Page.Contents>

+ 0 - 8
public/app/features/datasources/settings/__snapshots__/ButtonRow.test.tsx.snap

@@ -4,14 +4,6 @@ exports[`Render should render component 1`] = `
 <div
   className="gf-form-button-row"
 >
-  <button
-    className="btn btn-primary"
-    disabled={true}
-    onClick={[Function]}
-    type="submit"
-  >
-    Save & Test
-  </button>
   <button
     className="btn btn-success"
     onClick={[MockFunction]}

+ 336 - 352
public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap

@@ -7,100 +7,96 @@ exports[`Render should render alpha info text 1`] = `
   <PageContents
     isLoading={false}
   >
-    <div
-      className="page-container page-body"
-    >
-      <div>
-        <form
-          onSubmit={[Function]}
+    <div>
+      <form
+        onSubmit={[Function]}
+      >
+        <div
+          className="grafana-info-box"
         >
-          <div
-            className="grafana-info-box"
-          >
-            This plugin is marked as being in alpha state, which means it is in early development phase and updates will include breaking changes.
-          </div>
-          <BasicSettings
-            dataSourceName="gdev-cloudwatch"
-            isDefault={false}
-            onDefaultChange={[Function]}
-            onNameChange={[Function]}
-          />
-          <PluginSettings
-            dataSource={
-              Object {
-                "access": "",
-                "basicAuth": false,
-                "basicAuthPassword": "",
-                "basicAuthUser": "",
-                "database": "",
-                "id": 13,
-                "isDefault": false,
-                "jsonData": Object {
-                  "authType": "credentials",
-                  "defaultRegion": "eu-west-2",
-                },
-                "name": "gdev-cloudwatch",
-                "orgId": 1,
-                "password": "",
-                "readOnly": false,
-                "type": "cloudwatch",
-                "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
-                "url": "",
-                "user": "",
-                "withCredentials": false,
-              }
+          This plugin is marked as being in alpha state, which means it is in early development phase and updates will include breaking changes.
+        </div>
+        <BasicSettings
+          dataSourceName="gdev-cloudwatch"
+          isDefault={false}
+          onDefaultChange={[Function]}
+          onNameChange={[Function]}
+        />
+        <PluginSettings
+          dataSource={
+            Object {
+              "access": "",
+              "basicAuth": false,
+              "basicAuthPassword": "",
+              "basicAuthUser": "",
+              "database": "",
+              "id": 13,
+              "isDefault": false,
+              "jsonData": Object {
+                "authType": "credentials",
+                "defaultRegion": "eu-west-2",
+              },
+              "name": "gdev-cloudwatch",
+              "orgId": 1,
+              "password": "",
+              "readOnly": false,
+              "type": "cloudwatch",
+              "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
+              "url": "",
+              "user": "",
+              "withCredentials": false,
             }
-            dataSourceMeta={
-              Object {
-                "defaultNavUrl": "some/url",
-                "enabled": false,
-                "hasUpdate": false,
-                "id": "1",
-                "info": Object {
-                  "author": Object {
-                    "name": "Grafana Labs",
-                    "url": "url/to/GrafanaLabs",
-                  },
-                  "description": "pretty decent plugin",
-                  "links": Array [
-                    Object {
-                      "name": "project",
-                      "url": "one link",
-                    },
-                  ],
-                  "logos": Object {
-                    "large": "large/logo",
-                    "small": "small/logo",
+          }
+          dataSourceMeta={
+            Object {
+              "defaultNavUrl": "some/url",
+              "enabled": false,
+              "hasUpdate": false,
+              "id": "1",
+              "info": Object {
+                "author": Object {
+                  "name": "Grafana Labs",
+                  "url": "url/to/GrafanaLabs",
+                },
+                "description": "pretty decent plugin",
+                "links": Array [
+                  Object {
+                    "name": "project",
+                    "url": "one link",
                   },
-                  "screenshots": Array [
-                    Object {
-                      "path": "screenshot",
-                    },
-                  ],
-                  "updated": "2018-09-26",
-                  "version": "1",
+                ],
+                "logos": Object {
+                  "large": "large/logo",
+                  "small": "small/logo",
                 },
-                "latestVersion": "1",
-                "module": Object {},
-                "name": "pretty cool plugin 1",
-                "pinned": false,
-                "state": "alpha",
-                "type": "",
-              }
+                "screenshots": Array [
+                  Object {
+                    "path": "screenshot",
+                  },
+                ],
+                "updated": "2018-09-26",
+                "version": "1",
+              },
+              "latestVersion": "1",
+              "module": Object {},
+              "name": "pretty cool plugin 1",
+              "pinned": false,
+              "state": "alpha",
+              "type": "",
             }
-            onModelChange={[Function]}
-          />
-          <div
-            className="gf-form-group section"
-          />
-          <ButtonRow
-            isReadOnly={false}
-            onDelete={[Function]}
-            onSubmit={[Function]}
-            onTest={[Function]}
-          />
-        </form>
-      </div>
+          }
+          onModelChange={[Function]}
+        />
+        <div
+          className="gf-form-group"
+        />
+        <ButtonRow
+          isReadOnly={false}
+          onDelete={[Function]}
+          onSubmit={[Function]}
+          onTest={[Function]}
+        />
+      </form>
     </div>
   </PageContents>
 </Page>
@@ -113,100 +109,96 @@ exports[`Render should render beta info text 1`] = `
   <PageContents
     isLoading={false}
   >
-    <div
-      className="page-container page-body"
-    >
-      <div>
-        <form
-          onSubmit={[Function]}
+    <div>
+      <form
+        onSubmit={[Function]}
+      >
+        <div
+          className="grafana-info-box"
         >
-          <div
-            className="grafana-info-box"
-          >
-            This plugin is marked as being in a beta development state. This means it is in currently in active development and could be missing important features.
-          </div>
-          <BasicSettings
-            dataSourceName="gdev-cloudwatch"
-            isDefault={false}
-            onDefaultChange={[Function]}
-            onNameChange={[Function]}
-          />
-          <PluginSettings
-            dataSource={
-              Object {
-                "access": "",
-                "basicAuth": false,
-                "basicAuthPassword": "",
-                "basicAuthUser": "",
-                "database": "",
-                "id": 13,
-                "isDefault": false,
-                "jsonData": Object {
-                  "authType": "credentials",
-                  "defaultRegion": "eu-west-2",
-                },
-                "name": "gdev-cloudwatch",
-                "orgId": 1,
-                "password": "",
-                "readOnly": false,
-                "type": "cloudwatch",
-                "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
-                "url": "",
-                "user": "",
-                "withCredentials": false,
-              }
+          This plugin is marked as being in a beta development state. This means it is in currently in active development and could be missing important features.
+        </div>
+        <BasicSettings
+          dataSourceName="gdev-cloudwatch"
+          isDefault={false}
+          onDefaultChange={[Function]}
+          onNameChange={[Function]}
+        />
+        <PluginSettings
+          dataSource={
+            Object {
+              "access": "",
+              "basicAuth": false,
+              "basicAuthPassword": "",
+              "basicAuthUser": "",
+              "database": "",
+              "id": 13,
+              "isDefault": false,
+              "jsonData": Object {
+                "authType": "credentials",
+                "defaultRegion": "eu-west-2",
+              },
+              "name": "gdev-cloudwatch",
+              "orgId": 1,
+              "password": "",
+              "readOnly": false,
+              "type": "cloudwatch",
+              "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
+              "url": "",
+              "user": "",
+              "withCredentials": false,
             }
-            dataSourceMeta={
-              Object {
-                "defaultNavUrl": "some/url",
-                "enabled": false,
-                "hasUpdate": false,
-                "id": "1",
-                "info": Object {
-                  "author": Object {
-                    "name": "Grafana Labs",
-                    "url": "url/to/GrafanaLabs",
-                  },
-                  "description": "pretty decent plugin",
-                  "links": Array [
-                    Object {
-                      "name": "project",
-                      "url": "one link",
-                    },
-                  ],
-                  "logos": Object {
-                    "large": "large/logo",
-                    "small": "small/logo",
+          }
+          dataSourceMeta={
+            Object {
+              "defaultNavUrl": "some/url",
+              "enabled": false,
+              "hasUpdate": false,
+              "id": "1",
+              "info": Object {
+                "author": Object {
+                  "name": "Grafana Labs",
+                  "url": "url/to/GrafanaLabs",
+                },
+                "description": "pretty decent plugin",
+                "links": Array [
+                  Object {
+                    "name": "project",
+                    "url": "one link",
                   },
-                  "screenshots": Array [
-                    Object {
-                      "path": "screenshot",
-                    },
-                  ],
-                  "updated": "2018-09-26",
-                  "version": "1",
+                ],
+                "logos": Object {
+                  "large": "large/logo",
+                  "small": "small/logo",
                 },
-                "latestVersion": "1",
-                "module": Object {},
-                "name": "pretty cool plugin 1",
-                "pinned": false,
-                "state": "beta",
-                "type": "",
-              }
+                "screenshots": Array [
+                  Object {
+                    "path": "screenshot",
+                  },
+                ],
+                "updated": "2018-09-26",
+                "version": "1",
+              },
+              "latestVersion": "1",
+              "module": Object {},
+              "name": "pretty cool plugin 1",
+              "pinned": false,
+              "state": "beta",
+              "type": "",
             }
-            onModelChange={[Function]}
-          />
-          <div
-            className="gf-form-group section"
-          />
-          <ButtonRow
-            isReadOnly={false}
-            onDelete={[Function]}
-            onSubmit={[Function]}
-            onTest={[Function]}
-          />
-        </form>
-      </div>
+          }
+          onModelChange={[Function]}
+        />
+        <div
+          className="gf-form-group"
+        />
+        <ButtonRow
+          isReadOnly={false}
+          onDelete={[Function]}
+          onSubmit={[Function]}
+          onTest={[Function]}
+        />
+      </form>
     </div>
   </PageContents>
 </Page>
@@ -219,95 +211,91 @@ exports[`Render should render component 1`] = `
   <PageContents
     isLoading={false}
   >
-    <div
-      className="page-container page-body"
-    >
-      <div>
-        <form
-          onSubmit={[Function]}
-        >
-          <BasicSettings
-            dataSourceName="gdev-cloudwatch"
-            isDefault={false}
-            onDefaultChange={[Function]}
-            onNameChange={[Function]}
-          />
-          <PluginSettings
-            dataSource={
-              Object {
-                "access": "",
-                "basicAuth": false,
-                "basicAuthPassword": "",
-                "basicAuthUser": "",
-                "database": "",
-                "id": 13,
-                "isDefault": false,
-                "jsonData": Object {
-                  "authType": "credentials",
-                  "defaultRegion": "eu-west-2",
-                },
-                "name": "gdev-cloudwatch",
-                "orgId": 1,
-                "password": "",
-                "readOnly": false,
-                "type": "cloudwatch",
-                "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
-                "url": "",
-                "user": "",
-                "withCredentials": false,
-              }
+    <div>
+      <form
+        onSubmit={[Function]}
+      >
+        <BasicSettings
+          dataSourceName="gdev-cloudwatch"
+          isDefault={false}
+          onDefaultChange={[Function]}
+          onNameChange={[Function]}
+        />
+        <PluginSettings
+          dataSource={
+            Object {
+              "access": "",
+              "basicAuth": false,
+              "basicAuthPassword": "",
+              "basicAuthUser": "",
+              "database": "",
+              "id": 13,
+              "isDefault": false,
+              "jsonData": Object {
+                "authType": "credentials",
+                "defaultRegion": "eu-west-2",
+              },
+              "name": "gdev-cloudwatch",
+              "orgId": 1,
+              "password": "",
+              "readOnly": false,
+              "type": "cloudwatch",
+              "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
+              "url": "",
+              "user": "",
+              "withCredentials": false,
             }
-            dataSourceMeta={
-              Object {
-                "defaultNavUrl": "some/url",
-                "enabled": false,
-                "hasUpdate": false,
-                "id": "1",
-                "info": Object {
-                  "author": Object {
-                    "name": "Grafana Labs",
-                    "url": "url/to/GrafanaLabs",
-                  },
-                  "description": "pretty decent plugin",
-                  "links": Array [
-                    Object {
-                      "name": "project",
-                      "url": "one link",
-                    },
-                  ],
-                  "logos": Object {
-                    "large": "large/logo",
-                    "small": "small/logo",
+          }
+          dataSourceMeta={
+            Object {
+              "defaultNavUrl": "some/url",
+              "enabled": false,
+              "hasUpdate": false,
+              "id": "1",
+              "info": Object {
+                "author": Object {
+                  "name": "Grafana Labs",
+                  "url": "url/to/GrafanaLabs",
+                },
+                "description": "pretty decent plugin",
+                "links": Array [
+                  Object {
+                    "name": "project",
+                    "url": "one link",
                   },
-                  "screenshots": Array [
-                    Object {
-                      "path": "screenshot",
-                    },
-                  ],
-                  "updated": "2018-09-26",
-                  "version": "1",
+                ],
+                "logos": Object {
+                  "large": "large/logo",
+                  "small": "small/logo",
                 },
-                "latestVersion": "1",
-                "module": Object {},
-                "name": "pretty cool plugin 1",
-                "pinned": false,
-                "state": "",
-                "type": "",
-              }
+                "screenshots": Array [
+                  Object {
+                    "path": "screenshot",
+                  },
+                ],
+                "updated": "2018-09-26",
+                "version": "1",
+              },
+              "latestVersion": "1",
+              "module": Object {},
+              "name": "pretty cool plugin 1",
+              "pinned": false,
+              "state": "",
+              "type": "",
             }
-            onModelChange={[Function]}
-          />
-          <div
-            className="gf-form-group section"
-          />
-          <ButtonRow
-            isReadOnly={false}
-            onDelete={[Function]}
-            onSubmit={[Function]}
-            onTest={[Function]}
-          />
-        </form>
-      </div>
+          }
+          onModelChange={[Function]}
+        />
+        <div
+          className="gf-form-group"
+        />
+        <ButtonRow
+          isReadOnly={false}
+          onDelete={[Function]}
+          onSubmit={[Function]}
+          onTest={[Function]}
+        />
+      </form>
     </div>
   </PageContents>
 </Page>
@@ -320,100 +308,96 @@ exports[`Render should render is ready only message 1`] = `
   <PageContents
     isLoading={false}
   >
-    <div
-      className="page-container page-body"
-    >
-      <div>
-        <form
-          onSubmit={[Function]}
+    <div>
+      <form
+        onSubmit={[Function]}
+      >
+        <div
+          className="grafana-info-box span8"
         >
-          <div
-            className="grafana-info-box span8"
-          >
-            This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.
-          </div>
-          <BasicSettings
-            dataSourceName="gdev-cloudwatch"
-            isDefault={false}
-            onDefaultChange={[Function]}
-            onNameChange={[Function]}
-          />
-          <PluginSettings
-            dataSource={
-              Object {
-                "access": "",
-                "basicAuth": false,
-                "basicAuthPassword": "",
-                "basicAuthUser": "",
-                "database": "",
-                "id": 13,
-                "isDefault": false,
-                "jsonData": Object {
-                  "authType": "credentials",
-                  "defaultRegion": "eu-west-2",
-                },
-                "name": "gdev-cloudwatch",
-                "orgId": 1,
-                "password": "",
-                "readOnly": true,
-                "type": "cloudwatch",
-                "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
-                "url": "",
-                "user": "",
-                "withCredentials": false,
-              }
+          This datasource was added by config and cannot be modified using the UI. Please contact your server admin to update this datasource.
+        </div>
+        <BasicSettings
+          dataSourceName="gdev-cloudwatch"
+          isDefault={false}
+          onDefaultChange={[Function]}
+          onNameChange={[Function]}
+        />
+        <PluginSettings
+          dataSource={
+            Object {
+              "access": "",
+              "basicAuth": false,
+              "basicAuthPassword": "",
+              "basicAuthUser": "",
+              "database": "",
+              "id": 13,
+              "isDefault": false,
+              "jsonData": Object {
+                "authType": "credentials",
+                "defaultRegion": "eu-west-2",
+              },
+              "name": "gdev-cloudwatch",
+              "orgId": 1,
+              "password": "",
+              "readOnly": true,
+              "type": "cloudwatch",
+              "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png",
+              "url": "",
+              "user": "",
+              "withCredentials": false,
             }
-            dataSourceMeta={
-              Object {
-                "defaultNavUrl": "some/url",
-                "enabled": false,
-                "hasUpdate": false,
-                "id": "1",
-                "info": Object {
-                  "author": Object {
-                    "name": "Grafana Labs",
-                    "url": "url/to/GrafanaLabs",
-                  },
-                  "description": "pretty decent plugin",
-                  "links": Array [
-                    Object {
-                      "name": "project",
-                      "url": "one link",
-                    },
-                  ],
-                  "logos": Object {
-                    "large": "large/logo",
-                    "small": "small/logo",
+          }
+          dataSourceMeta={
+            Object {
+              "defaultNavUrl": "some/url",
+              "enabled": false,
+              "hasUpdate": false,
+              "id": "1",
+              "info": Object {
+                "author": Object {
+                  "name": "Grafana Labs",
+                  "url": "url/to/GrafanaLabs",
+                },
+                "description": "pretty decent plugin",
+                "links": Array [
+                  Object {
+                    "name": "project",
+                    "url": "one link",
                   },
-                  "screenshots": Array [
-                    Object {
-                      "path": "screenshot",
-                    },
-                  ],
-                  "updated": "2018-09-26",
-                  "version": "1",
+                ],
+                "logos": Object {
+                  "large": "large/logo",
+                  "small": "small/logo",
                 },
-                "latestVersion": "1",
-                "module": Object {},
-                "name": "pretty cool plugin 1",
-                "pinned": false,
-                "state": "",
-                "type": "",
-              }
+                "screenshots": Array [
+                  Object {
+                    "path": "screenshot",
+                  },
+                ],
+                "updated": "2018-09-26",
+                "version": "1",
+              },
+              "latestVersion": "1",
+              "module": Object {},
+              "name": "pretty cool plugin 1",
+              "pinned": false,
+              "state": "",
+              "type": "",
             }
-            onModelChange={[Function]}
-          />
-          <div
-            className="gf-form-group section"
-          />
-          <ButtonRow
-            isReadOnly={true}
-            onDelete={[Function]}
-            onSubmit={[Function]}
-            onTest={[Function]}
-          />
-        </form>
-      </div>
+          }
+          onModelChange={[Function]}
+        />
+        <div
+          className="gf-form-group"
+        />
+        <ButtonRow
+          isReadOnly={true}
+          onDelete={[Function]}
+          onSubmit={[Function]}
+          onTest={[Function]}
+        />
+      </form>
     </div>
   </PageContents>
 </Page>

+ 24 - 26
public/app/features/folders/FolderSettingsPage.tsx

@@ -26,7 +26,7 @@ export class FolderSettingsPage extends PureComponent<Props, State> {
   constructor(props: Props) {
     super(props);
     this.state = {
-      isLoading: false
+      isLoading: false,
     };
   }
 
@@ -41,9 +41,9 @@ export class FolderSettingsPage extends PureComponent<Props, State> {
   onSave = async (evt: React.FormEvent<HTMLFormElement>) => {
     evt.preventDefault();
     evt.stopPropagation();
-    this.setState({isLoading: true});
+    this.setState({ isLoading: true });
     await this.props.saveFolder(this.props.folder);
-    this.setState({isLoading: false});
+    this.setState({ isLoading: false });
   };
 
   onDelete = (evt: React.MouseEvent<HTMLButtonElement>) => {
@@ -67,30 +67,28 @@ export class FolderSettingsPage extends PureComponent<Props, State> {
     return (
       <Page navModel={navModel}>
         <Page.Contents isLoading={this.state.isLoading}>
-          <div className="page-container page-body">
-            <h2 className="page-sub-heading">Folder Settings</h2>
+          <h2 className="page-sub-heading">Folder Settings</h2>
 
-            <div className="section gf-form-group">
-              <form name="folderSettingsForm" onSubmit={this.onSave}>
-                <div className="gf-form">
-                  <label className="gf-form-label width-7">Name</label>
-                  <input
-                    type="text"
-                    className="gf-form-input width-30"
-                    value={folder.title}
-                    onChange={this.onTitleChange}
-                  />
-                </div>
-                <div className="gf-form-button-row">
-                  <button type="submit" className="btn btn-primary" disabled={!folder.canSave || !folder.hasChanged}>
-                    <i className="fa fa-save" /> Save
-                  </button>
-                  <button className="btn btn-danger" onClick={this.onDelete} disabled={!folder.canSave}>
-                    <i className="fa fa-trash" /> Delete
-                  </button>
-                </div>
-              </form>
-            </div>
+          <div className="section gf-form-group">
+            <form name="folderSettingsForm" onSubmit={this.onSave}>
+              <div className="gf-form">
+                <label className="gf-form-label width-7">Name</label>
+                <input
+                  type="text"
+                  className="gf-form-input width-30"
+                  value={folder.title}
+                  onChange={this.onTitleChange}
+                />
+              </div>
+              <div className="gf-form-button-row">
+                <button type="submit" className="btn btn-primary" disabled={!folder.canSave || !folder.hasChanged}>
+                  <i className="fa fa-save" /> Save
+                </button>
+                <button className="btn btn-danger" onClick={this.onDelete} disabled={!folder.canSave}>
+                  <i className="fa fa-trash" /> Delete
+                </button>
+              </div>
+            </form>
           </div>
         </Page.Contents>
       </Page>

+ 90 - 98
public/app/features/folders/__snapshots__/FolderSettingsPage.test.tsx.snap

@@ -7,62 +7,58 @@ exports[`Render should enable save button 1`] = `
   <PageContents
     isLoading={false}
   >
+    <h2
+      className="page-sub-heading"
+    >
+      Folder Settings
+    </h2>
     <div
-      className="page-container page-body"
+      className="section gf-form-group"
     >
-      <h2
-        className="page-sub-heading"
-      >
-        Folder Settings
-      </h2>
-      <div
-        className="section gf-form-group"
+      <form
+        name="folderSettingsForm"
+        onSubmit={[Function]}
       >
-        <form
-          name="folderSettingsForm"
-          onSubmit={[Function]}
+        <div
+          className="gf-form"
         >
-          <div
-            className="gf-form"
+          <label
+            className="gf-form-label width-7"
           >
-            <label
-              className="gf-form-label width-7"
-            >
-              Name
-            </label>
-            <input
-              className="gf-form-input width-30"
-              onChange={[Function]}
-              type="text"
-              value="loading"
+            Name
+          </label>
+          <input
+            className="gf-form-input width-30"
+            onChange={[Function]}
+            type="text"
+            value="loading"
+          />
+        </div>
+        <div
+          className="gf-form-button-row"
+        >
+          <button
+            className="btn btn-primary"
+            disabled={false}
+            type="submit"
+          >
+            <i
+              className="fa fa-save"
             />
-          </div>
-          <div
-            className="gf-form-button-row"
+             Save
+          </button>
+          <button
+            className="btn btn-danger"
+            disabled={false}
+            onClick={[Function]}
           >
-            <button
-              className="btn btn-primary"
-              disabled={false}
-              type="submit"
-            >
-              <i
-                className="fa fa-save"
-              />
-               Save
-            </button>
-            <button
-              className="btn btn-danger"
-              disabled={false}
-              onClick={[Function]}
-            >
-              <i
-                className="fa fa-trash"
-              />
-               Delete
-            </button>
-          </div>
-        </form>
-      </div>
+            <i
+              className="fa fa-trash"
+            />
+             Delete
+          </button>
+        </div>
+      </form>
     </div>
   </PageContents>
 </Page>
@@ -75,62 +71,58 @@ exports[`Render should render component 1`] = `
   <PageContents
     isLoading={false}
   >
+    <h2
+      className="page-sub-heading"
+    >
+      Folder Settings
+    </h2>
     <div
-      className="page-container page-body"
+      className="section gf-form-group"
     >
-      <h2
-        className="page-sub-heading"
-      >
-        Folder Settings
-      </h2>
-      <div
-        className="section gf-form-group"
+      <form
+        name="folderSettingsForm"
+        onSubmit={[Function]}
       >
-        <form
-          name="folderSettingsForm"
-          onSubmit={[Function]}
+        <div
+          className="gf-form"
         >
-          <div
-            className="gf-form"
+          <label
+            className="gf-form-label width-7"
           >
-            <label
-              className="gf-form-label width-7"
-            >
-              Name
-            </label>
-            <input
-              className="gf-form-input width-30"
-              onChange={[Function]}
-              type="text"
-              value="loading"
+            Name
+          </label>
+          <input
+            className="gf-form-input width-30"
+            onChange={[Function]}
+            type="text"
+            value="loading"
+          />
+        </div>
+        <div
+          className="gf-form-button-row"
+        >
+          <button
+            className="btn btn-primary"
+            disabled={true}
+            type="submit"
+          >
+            <i
+              className="fa fa-save"
             />
-          </div>
-          <div
-            className="gf-form-button-row"
+             Save
+          </button>
+          <button
+            className="btn btn-danger"
+            disabled={false}
+            onClick={[Function]}
           >
-            <button
-              className="btn btn-primary"
-              disabled={true}
-              type="submit"
-            >
-              <i
-                className="fa fa-save"
-              />
-               Save
-            </button>
-            <button
-              className="btn btn-danger"
-              disabled={false}
-              onClick={[Function]}
-            >
-              <i
-                className="fa fa-trash"
-              />
-               Delete
-            </button>
-          </div>
-        </form>
-      </div>
+            <i
+              className="fa fa-trash"
+            />
+             Delete
+          </button>
+        </div>
+      </form>
     </div>
   </PageContents>
 </Page>

+ 2 - 2
public/app/features/teams/TeamPages.tsx

@@ -49,9 +49,9 @@ export class TeamPages extends PureComponent<Props, State> {
 
   async fetchTeam() {
     const { loadTeam, teamId } = this.props;
-    this.setState({isLoading: true});
+    this.setState({ isLoading: true });
     const team = await loadTeam(teamId);
-    this.setState({isLoading: false});
+    this.setState({ isLoading: false });
     return team;
   }
 

+ 51 - 18
yarn.lock

@@ -4719,6 +4719,11 @@ ci-info@^1.5.0:
   resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
   integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
 
+ci-info@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+  integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
 cidr-regex@1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-1.0.6.tgz#74abfd619df370b9d54ab14475568e97dd64c0c1"
@@ -7929,6 +7934,11 @@ get-stdin@^4.0.1:
   resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
   integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
 
+get-stdin@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
+  integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
+
 get-stream@3.0.0, get-stream@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
@@ -8893,14 +8903,21 @@ humanize-ms@^1.2.1:
   dependencies:
     ms "^2.0.0"
 
-husky@^0.14.3:
-  version "0.14.3"
-  resolved "https://registry.yarnpkg.com/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3"
-  integrity sha512-e21wivqHpstpoiWA/Yi8eFti8E+sQDSS53cpJsPptPs295QTOQR0ZwnHo2TXy1XOpZFD9rPOd3NpmqTK6uMLJA==
+husky@^1.3.1:
+  version "1.3.1"
+  resolved "https://registry.yarnpkg.com/husky/-/husky-1.3.1.tgz#26823e399300388ca2afff11cfa8a86b0033fae0"
+  integrity sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==
   dependencies:
-    is-ci "^1.0.10"
-    normalize-path "^1.0.0"
-    strip-indent "^2.0.0"
+    cosmiconfig "^5.0.7"
+    execa "^1.0.0"
+    find-up "^3.0.0"
+    get-stdin "^6.0.0"
+    is-ci "^2.0.0"
+    pkg-dir "^3.0.0"
+    please-upgrade-node "^3.1.1"
+    read-pkg "^4.0.1"
+    run-node "^1.0.0"
+    slash "^2.0.0"
 
 iconv-lite@0.4, iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
   version "0.4.24"
@@ -9286,6 +9303,13 @@ is-ci@^1.0.10:
   dependencies:
     ci-info "^1.5.0"
 
+is-ci@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
+  integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+  dependencies:
+    ci-info "^2.0.0"
+
 is-cidr@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-1.0.0.tgz#fb5aacf659255310359da32cae03e40c6a1c2afc"
@@ -11932,11 +11956,6 @@ normalize-path@2.0.1:
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a"
   integrity sha1-R4hqwWYnYNQmG32XnSQXCdPOP3o=
 
-normalize-path@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379"
-  integrity sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=
-
 normalize-path@^2.0.0, normalize-path@^2.0.1, normalize-path@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
@@ -12955,7 +12974,7 @@ pkg-up@^1.0.0:
   dependencies:
     find-up "^1.0.0"
 
-please-upgrade-node@^3.0.2:
+please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac"
   integrity sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==
@@ -14343,6 +14362,15 @@ read-pkg@^3.0.0:
     normalize-package-data "^2.3.2"
     path-type "^3.0.0"
 
+read-pkg@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
+  integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc=
+  dependencies:
+    normalize-package-data "^2.3.2"
+    parse-json "^4.0.0"
+    pify "^3.0.0"
+
 read@1, read@~1.0.1, read@~1.0.7:
   version "1.0.7"
   resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
@@ -15002,6 +15030,11 @@ run-async@^2.0.0, run-async@^2.2.0:
   dependencies:
     is-promise "^2.1.0"
 
+run-node@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e"
+  integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==
+
 run-queue@^1.0.0, run-queue@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
@@ -15460,6 +15493,11 @@ slash@^1.0.0:
   resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
   integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
 
+slash@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
+  integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==
+
 slate-base64-serializer@^0.2.36:
   version "0.2.94"
   resolved "https://registry.yarnpkg.com/slate-base64-serializer/-/slate-base64-serializer-0.2.94.tgz#b908c3af481b9a0ead78f313653414c4b2b4b2d5"
@@ -16159,11 +16197,6 @@ strip-indent@^1.0.1:
   dependencies:
     get-stdin "^4.0.1"
 
-strip-indent@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68"
-  integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=
-
 strip-json-comments@~1.0.1:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"