From d0e23af2283a5afdb6b026bb9e30bcf665a8b5ce Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Mon, 27 Apr 2020 10:00:17 +0200 Subject: [PATCH] Angular/Forms migration: Orgs list (#23821) * Create new components * Fix async issues * Remove comments * Update public/app/features/admin/AdminOrgsTable.tsx * Update public/app/features/admin/AdminListOrgsPage.tsx * Update public/app/features/admin/AdminListOrgsPage.tsx * Remove angular code Co-authored-by: Dominik Prokop --- .../app/features/admin/AdminListOrgsCtrl.ts | 35 ------------ .../app/features/admin/AdminListOrgsPage.tsx | 54 ++++++++++++++++++ public/app/features/admin/AdminOrgsTable.tsx | 57 +++++++++++++++++++ public/app/features/admin/index.ts | 2 - public/app/features/admin/partials/orgs.html | 41 ------------- public/app/routes/routes.ts | 8 ++- 6 files changed, 116 insertions(+), 81 deletions(-) delete mode 100644 public/app/features/admin/AdminListOrgsCtrl.ts create mode 100644 public/app/features/admin/AdminListOrgsPage.tsx create mode 100644 public/app/features/admin/AdminOrgsTable.tsx delete mode 100644 public/app/features/admin/partials/orgs.html diff --git a/public/app/features/admin/AdminListOrgsCtrl.ts b/public/app/features/admin/AdminListOrgsCtrl.ts deleted file mode 100644 index f7d31162000..00000000000 --- a/public/app/features/admin/AdminListOrgsCtrl.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { getBackendSrv } from '@grafana/runtime'; -import { NavModelSrv } from 'app/core/core'; -import { Scope, CoreEvents, AppEventEmitter } from 'app/types'; -import { promiseToDigest } from 'app/core/utils/promiseToDigest'; - -export default class AdminListOrgsCtrl { - /** @ngInject */ - constructor($scope: Scope & AppEventEmitter, navModelSrv: NavModelSrv) { - $scope.init = async () => { - $scope.navModel = navModelSrv.getNav('admin', 'global-orgs', 0); - await $scope.getOrgs(); - }; - - $scope.getOrgs = async () => { - const orgs = await promiseToDigest($scope)(getBackendSrv().get('/api/orgs')); - $scope.orgs = orgs; - }; - - $scope.deleteOrg = (org: any) => { - $scope.appEvent(CoreEvents.showConfirmModal, { - title: 'Delete', - text: `Do you want to delete organization ${org.name}?`, - text2: 'All dashboards for this organization will be removed!', - icon: 'trash-alt', - yesText: 'Delete', - onConfirm: async () => { - await getBackendSrv().delete('/api/orgs/' + org.id); - await $scope.getOrgs(); - }, - }); - }; - - $scope.init(); - } -} diff --git a/public/app/features/admin/AdminListOrgsPage.tsx b/public/app/features/admin/AdminListOrgsPage.tsx new file mode 100644 index 00000000000..791598b270e --- /dev/null +++ b/public/app/features/admin/AdminListOrgsPage.tsx @@ -0,0 +1,54 @@ +import React, { FC, useEffect } from 'react'; +import { getNavModel } from 'app/core/selectors/navModel'; +import Page from 'app/core/components/Page/Page'; +import { useSelector } from 'react-redux'; +import { StoreState } from 'app/types/store'; +import { LinkButton } from '@grafana/ui'; +import { getBackendSrv } from '@grafana/runtime'; +import { AdminOrgsTable } from './AdminOrgsTable'; +import useAsyncFn from 'react-use/lib/useAsyncFn'; + +const deleteOrg = async (orgId: number) => { + return await getBackendSrv().delete('/api/orgs/' + orgId); +}; + +const getOrgs = async () => { + return await getBackendSrv().get('/api/orgs'); +}; + +export const AdminListOrgsPages: FC = () => { + const navIndex = useSelector((state: StoreState) => state.navIndex); + const navModel = getNavModel(navIndex, 'global-orgs'); + const [state, fetchOrgs] = useAsyncFn(async () => await getOrgs(), []); + useEffect(() => { + fetchOrgs(); + }, []); + + return ( + + + <> +
+
+ + New org + +
+ {state.loading && 'Fetching organizations'} + {state.error} + {state.value && ( + { + deleteOrg(orgId); + fetchOrgs(); + }} + /> + )} + +
+
+ ); +}; + +export default AdminListOrgsPages; diff --git a/public/app/features/admin/AdminOrgsTable.tsx b/public/app/features/admin/AdminOrgsTable.tsx new file mode 100644 index 00000000000..8439924bb04 --- /dev/null +++ b/public/app/features/admin/AdminOrgsTable.tsx @@ -0,0 +1,57 @@ +import React, { FC, useState } from 'react'; +import { Organization } from 'app/types'; +import { Button, ConfirmModal } from '@grafana/ui'; + +interface Props { + orgs: Organization[]; + onDelete: (orgId: number) => void; +} + +export const AdminOrgsTable: FC = ({ orgs, onDelete }) => { + const [deleteOrg, setDeleteOrg] = useState(); + return ( + + + + + + + + + + {orgs.map(org => ( + + + + + + ))} + + {deleteOrg && ( + + Are you sure you want to delete `${deleteOrg.name}`? +
All dashboards for this organization will be removed! + + } + confirmText="Delete" + onDismiss={() => setDeleteOrg(null)} + onConfirm={() => { + onDelete(deleteOrg.id); + setDeleteOrg(null); + }} + /> + )} +
IdName
+ {org.id} + + {org.name} + +
+ ); +}; diff --git a/public/app/features/admin/index.ts b/public/app/features/admin/index.ts index c43f16fb3fa..36a1feccf68 100644 --- a/public/app/features/admin/index.ts +++ b/public/app/features/admin/index.ts @@ -1,5 +1,4 @@ import AdminEditUserCtrl from './AdminEditUserCtrl'; -import AdminListOrgsCtrl from './AdminListOrgsCtrl'; import AdminEditOrgCtrl from './AdminEditOrgCtrl'; import coreModule from 'app/core/core_module'; @@ -15,6 +14,5 @@ class AdminHomeCtrl { } coreModule.controller('AdminEditUserCtrl', AdminEditUserCtrl); -coreModule.controller('AdminListOrgsCtrl', AdminListOrgsCtrl); coreModule.controller('AdminEditOrgCtrl', AdminEditOrgCtrl); coreModule.controller('AdminHomeCtrl', AdminHomeCtrl); diff --git a/public/app/features/admin/partials/orgs.html b/public/app/features/admin/partials/orgs.html deleted file mode 100644 index 434b2b12054..00000000000 --- a/public/app/features/admin/partials/orgs.html +++ /dev/null @@ -1,41 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - -
IdName
- - - -
-
- -