mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Migration: Create org (#22542)
* Add NewOrgPage * Remove filrs * Remove import * Remove comments * Get navModel from Redux * Add DTO * Get nav model from state * Change error display * Add async await and check if org is available * Fix null strict null error * Update public/app/features/org/NewOrgPage.tsx Co-Authored-By: Dominik Prokop <dominik.prokop@grafana.com> Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
parent
f2742d4a28
commit
a2b3da2792
@ -16,9 +16,21 @@ export interface NavModelItem {
|
||||
showOrgSwitcher?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface used to describe different kinds of page titles and page navigation. Navmodels are usually generated in the backend and stored in Redux.
|
||||
*/
|
||||
export interface NavModel {
|
||||
/**
|
||||
* Main page. that wraps the navigation. Generate the `children` property generate tabs when used with the Page component.
|
||||
*/
|
||||
main: NavModelItem;
|
||||
/**
|
||||
* This is the current active tab/navigation.
|
||||
*/
|
||||
node: NavModelItem;
|
||||
/**
|
||||
* Describes breadcrumbs that are used in places such as data source settings., folder page and plugins page.
|
||||
*/
|
||||
breadcrumbs?: NavModelItem[];
|
||||
}
|
||||
|
||||
|
@ -1,26 +0,0 @@
|
||||
import angular from 'angular';
|
||||
import config from 'app/core/config';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { NavModelSrv } from 'app/core/core';
|
||||
|
||||
export class NewOrgCtrl {
|
||||
/** @ngInject */
|
||||
constructor($scope: any, $http: any, navModelSrv: NavModelSrv) {
|
||||
$scope.navModel = navModelSrv.getNav('admin', 'global-orgs', 0);
|
||||
$scope.newOrg = { name: '' };
|
||||
|
||||
$scope.createOrg = () => {
|
||||
getBackendSrv()
|
||||
.post('/api/orgs/', $scope.newOrg)
|
||||
.then((result: any) => {
|
||||
getBackendSrv()
|
||||
.post('/api/user/using/' + result.orgId)
|
||||
.then(() => {
|
||||
window.location.href = config.appSubUrl + '/org';
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('grafana.controllers').controller('NewOrgCtrl', NewOrgCtrl);
|
85
public/app/features/org/NewOrgPage.tsx
Normal file
85
public/app/features/org/NewOrgPage.tsx
Normal file
@ -0,0 +1,85 @@
|
||||
import React, { FC } from 'react';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { Forms } from '@grafana/ui';
|
||||
import { getConfig } from 'app/core/config';
|
||||
import { StoreState } from 'app/types';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect } from 'react-redux';
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { getNavModel } from '../../core/selectors/navModel';
|
||||
|
||||
const createOrg = async (newOrg: { name: string }) => {
|
||||
const result = await getBackendSrv().post('/api/orgs/', newOrg);
|
||||
|
||||
await getBackendSrv().post('/api/user/using/' + result.orgId);
|
||||
window.location.href = getConfig().appSubUrl + '/org';
|
||||
};
|
||||
|
||||
const validateOrg = async (orgName: string) => {
|
||||
try {
|
||||
await getBackendSrv().get(`api/orgs/name/${encodeURI(orgName)}`);
|
||||
} catch (error) {
|
||||
if (error.status === 404) {
|
||||
error.isHandled = true;
|
||||
return true;
|
||||
}
|
||||
return 'Something went wrong';
|
||||
}
|
||||
return 'Organization already exists';
|
||||
};
|
||||
|
||||
interface PropsWithState {
|
||||
navModel: NavModel;
|
||||
}
|
||||
|
||||
interface CreateOrgFormDTO {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const NewOrgPage: FC<PropsWithState> = ({ navModel }) => {
|
||||
return (
|
||||
<Page navModel={navModel}>
|
||||
<Page.Contents>
|
||||
<h3 className="page-sub-heading">New Organization</h3>
|
||||
|
||||
<p className="playlist-description">
|
||||
Each organization contains their own dashboards, data sources and configuration, and cannot be shared between
|
||||
orgs. While users may belong to more than one, multiple organization are most frequently used in multi-tenant
|
||||
deployments.{' '}
|
||||
</p>
|
||||
|
||||
<Forms.Form<CreateOrgFormDTO> onSubmit={createOrg}>
|
||||
{({ register, errors }) => {
|
||||
return (
|
||||
<>
|
||||
<Forms.Field
|
||||
label="Organization name"
|
||||
invalid={!!errors.name}
|
||||
error={errors.name && errors.name.message}
|
||||
>
|
||||
<Forms.Input
|
||||
size="md"
|
||||
placeholder="Org. name"
|
||||
name="name"
|
||||
ref={register({
|
||||
required: 'Organization name is required',
|
||||
validate: async orgName => await validateOrg(orgName),
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Button type="submit">Create</Forms.Button>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Forms.Form>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state: StoreState) => {
|
||||
return { navModel: getNavModel(state.navIndex, 'global-orgs') };
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps)(NewOrgPage));
|
@ -1,2 +1 @@
|
||||
import './SelectOrgCtrl';
|
||||
import './NewOrgCtrl';
|
||||
|
@ -1,24 +0,0 @@
|
||||
<page-header model="navModel"></page-header>
|
||||
|
||||
<div class="page-container page-body" ng-form="playlistEditForm">
|
||||
<h3 class="page-sub-heading">
|
||||
New Organization
|
||||
</h3>
|
||||
|
||||
<p class="playlist-description">Each organization contains their own dashboards, data sources and configuration, and cannot be shared between orgs. While users may belong to more than one, multiple organization are most frequently used in multi-tenant deployments. </p>
|
||||
|
||||
<form>
|
||||
<div class="gf-form-group">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label width-10">Org. name</span>
|
||||
<input type="text" ng-model="newOrg.name" required class="gf-form-input max-width-21" placeholder="organization name">
|
||||
</div>
|
||||
<br>
|
||||
<div class="gf-form-buttons-row">
|
||||
<button type="submit" class="btn btn-primary" ng-click="createOrg()">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<footer />
|
@ -219,8 +219,10 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati
|
||||
},
|
||||
})
|
||||
.when('/org/new', {
|
||||
templateUrl: 'public/app/features/org/partials/newOrg.html',
|
||||
controller: 'NewOrgCtrl',
|
||||
template: '<react-container />',
|
||||
resolve: {
|
||||
component: () => SafeDynamicImport(import(/* webpackChunkName: "NewOrgPage" */ 'app/features/org/NewOrgPage')),
|
||||
},
|
||||
})
|
||||
.when('/org/users', {
|
||||
template: '<react-container />',
|
||||
|
Loading…
Reference in New Issue
Block a user